# Adapty Documentation (Full Content) > Complete documentation content across all platforms. Locale: ja Generated on: 2026-06-24T14:36:28.770Z --- # ANDROID - Adapty Documentation (Full Content) This file contains the complete content of all documentation pages for this platform. Locale: ja Generated on: 2026-06-24T14:36:28.434Z Total files: 40 --- # File: sdk-installation-android --- --- title: "Android SDKのインストールと設定" description: "サブスクリプションアプリ向けに、Android に Adapty SDK をインストールするステップバイステップのガイドです。" --- Adapty SDK には、モバイルアプリにシームレスに統合するための2つの主要モジュールが含まれています。 - **Core Adapty**: Adapty をアプリで正しく動作させるために必須の SDK です。 - **AdaptyUI**: クロスプラットフォームのペイウォールを簡単に作成できるノーコードツール、[Adapty ペイウォールビルダー](adapty-paywall-builder)を使用する場合に必要なモジュールです。AdaptyUI はコアモジュールと同時に自動的に有効化されます。 :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を確認したい方は、ペイウォールの表示・購入処理・その他の基本機能を含むフルセットアップを示す[サンプルアプリ](https://github.com/adaptyteam/AdaptySDK-Android/tree/master/app)をご覧ください。 ::: ## 要件 \{#requirements\} 最低 SDK 要件: `minSdkVersion 21` :::info Adapty は Google Play Billing Library 8.x まで対応しています。デフォルトでは Google Play Billing Library v7.0.0 で動作しますが、より新しいバージョンを使用したい場合は、手動で[依存関係を追加](https://developer.android.com/google/play/billing/integrate#dependency)できます。 ::: --- no_index: true --- import Callout from '../../../components/Callout.astro'; SDKのインストールは、Adaptyセットアップのステップ5です。アプリ内で課金が機能するようにするには、アプリをストアに接続し、Adapty ダッシュボードでプロダクト、ペイウォール、プレースメントを作成する必要があります。[クイックスタートガイド](quickstart)では、必要なすべての手順を説明しています。 ## Adapty SDK をインストールする \{#install-adapty-sdk\} 依存関係の設定方法を選択してください: - Standard Gradle: **モジュールレベル**の `build.gradle` に依存関係を追加する - プロジェクトで `.gradle.kts` ファイルを使用している場合は、モジュールレベルの `build.gradle.kts` に依存関係を追加する - バージョンカタログを使用している場合は、`libs.versions.toml` ファイルに依存関係を追加し、`build.gradle.kts` で参照する [![Release](https://img.shields.io/github/v/release/adaptyteam/AdaptySDK-Android.svg?style=flat&logo=android)](https://github.com/adaptyteam/AdaptySDK-Android/releases) ```groovy showLineNumbers dependencies { ... implementation platform('io.adapty:adapty-bom:') implementation 'io.adapty:android-sdk' // Only add this line if you plan to use Paywall Builder implementation 'io.adapty:android-ui' } ``` ```kotlin showLineNumbers dependencies { ... implementation(platform("io.adapty:adapty-bom:")) implementation("io.adapty:android-sdk") // Only add this line if you plan to use Paywall Builder: implementation("io.adapty:android-ui") } ``` ```toml showLineNumbers //libs.versions.toml [versions] .. adaptyBom = "" [libraries] .. adapty-bom = { module = "io.adapty:adapty-bom", version.ref = "adaptyBom" } adapty = { module = "io.adapty:android-sdk" } // Only add this line if you plan to use Paywall Builder: adapty-ui = { module = "io.adapty:android-ui" } //module-level build.gradle.kts dependencies { ... implementation(platform(libs.adapty.bom)) implementation(libs.adapty) // Only add this line if you plan to use Paywall Builder: implementation(libs.adapty.ui) } ``` 依存関係が解決されない場合は、Gradle スクリプトに `mavenCentral()` が含まれているか確認してください。
追加方法の手順 プロジェクトの `settings.gradle` に `dependencyResolutionManagement` がない場合は、トップレベルの `build.gradle` のリポジトリの末尾に以下を追加してください: ```groovy showLineNumbers title="top-level build.gradle" allprojects { repositories { ... mavenCentral() } } ``` それ以外の場合は、`settings.gradle` の `dependencyResolutionManagement` セクション内の `repositories` に以下を追加してください: ```groovy showLineNumbers title="settings.gradle" dependencyResolutionManagement { ... repositories { ... mavenCentral() } } ```
## Adapty SDK の Adapty モジュールを有効化する \{#activate-adapty-module-of-adapty-sdk\} ### 基本セットアップ \{#basic-setup\} アプリのコードで Adapty SDK を有効化します。 :::note Adapty SDK はアプリ内で一度だけ有効化すれば十分です。 ::: **Public SDK Key** を取得するには: 1. Adapty ダッシュボードを開き、[**App settings → General**](https://app.adapty.io/settings/general) に移動します。 2. **Api keys** セクションから **Public SDK Key**(Secret Key ではない方)をコピーします。 3. コード内の `"YOUR_PUBLIC_SDK_KEY"` を置き換えます。 :::important - Adapty の初期化には必ず **Public SDK key** を使用してください。**Secret key** は[サーバーサイド API](getting-started-with-server-side-api) 専用です。 - **SDK keys** はアプリごとに固有です。複数のアプリがある場合は、正しいキーを選択してください。 ::: ```kotlin showLineNumbers // In your Application class class MyApplication : Application() { override fun onCreate() { super.onCreate() Adapty.activate( applicationContext, AdaptyConfig.Builder("PUBLIC_SDK_KEY") .build() ) } } ``` ```java showLineNumbers // In your Application class public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); Adapty.activate( getApplicationContext(), new AdaptyConfig.Builder("PUBLIC_SDK_KEY") .build() ); } } ``` :::important `Adapty.activate` が完了するまで待ってから、他の Adapty SDK メソッドを呼び出してください。完全な呼び出し順序については、[Android SDK の呼び出し順序](android-sdk-call-order)を参照してください。 ::: 次に、アプリにペイウォールを設定します: - [Adapty ペイウォールビルダー](adapty-paywall-builder)を使用する場合は、[ペイウォールビルダーのクイックスタート](android-quickstart-paywalls)に従ってください。 - 独自のペイウォール UI を構築する場合は、[カスタムペイウォールのクイックスタート](android-quickstart-manual)を参照してください。 ## Adapty SDK の AdaptyUI モジュールを有効化する \{#activate-adaptyui-module-of-adapty-sdk\} [ペイウォールビルダー](adapty-paywall-builder)を使用する予定の場合、AdaptyUI モジュールが必要です。コアモジュールを有効化すると自動的に有効化されるため、追加の操作は不要です。 ## Proguard を設定する \{#configure-proguard\} 本番環境でアプリを公開する前に、Proguard の設定に `-keep class com.adapty.** { *; }` を追加してください。 ## オプションの設定 \{#optional-setup\} ### ログ \{#logging\} #### ログシステムを設定する \{#set-up-the-logging-system\} Adapty は、何が起きているかを把握するためにエラーやその他の重要な情報をログに記録します。利用可能なレベルは以下のとおりです: | レベル | 説明 | | :----------------------- | :------------------------------------------------------------------------------------------------------------------------ | | `AdaptyLogLevel.NONE` | 何もログに記録されません。デフォルト値 | | `AdaptyLogLevel.ERROR` | エラーのみログに記録されます | | `AdaptyLogLevel.WARN` | エラーと、重大なエラーではないが注意が必要な SDK からのメッセージがログに記録されます。 | | `AdaptyLogLevel.INFO` | エラー、警告、およびさまざまな情報メッセージがログに記録されます。 | | `AdaptyLogLevel.VERBOSE` | 関数呼び出しや API クエリなど、デバッグ時に役立つ追加情報がすべてログに記録されます。 | Adapty を設定する前に、アプリでログレベルを設定できます。 ```kotlin showLineNumbers Adapty.logLevel = AdaptyLogLevel.VERBOSE //recommended for development and the first production release ``` ```java showLineNumbers Adapty.setLogLevel(AdaptyLogLevel.VERBOSE); //recommended for development and the first production release ``` #### ログシステムのメッセージをリダイレクトする \{#redirect-the-logging-system-messages\} 何らかの理由で Adapty からのメッセージを独自のシステムに送信したり、ファイルに保存したりする必要がある場合は、デフォルトの動作をオーバーライドできます: ```kotlin showLineNumbers Adapty.setLogHandler { level, message -> //handle the log } ``` ```java showLineNumbers Adapty.setLogHandler((level, message) -> { //handle the log }); ``` ### データポリシー \{#data-policies\} Adapty は明示的に送信しない限りユーザーの個人データを保存しませんが、ストアや国のガイドラインに準拠するために追加のデータセキュリティポリシーを実装することができます。 #### IP アドレスの収集と共有を無効にする \{#disable-ip-address-collection-and-sharing\} Adapty モジュールを有効化する際に、`ipAddressCollectionDisabled` を `true` に設定すると、ユーザーの IP アドレスの収集と共有を無効にできます。デフォルト値は `false` です。 このパラメータは、ユーザーのプライバシーを強化したり、地域のデータ保護規制(GDPR や CCPA など)に準拠したり、IP ベースの機能がアプリに不要な場合に不必要なデータ収集を削減するために使用します。 ```kotlin showLineNumbers AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withIpAddressCollectionDisabled(true) .build() ``` ```java showLineNumbers new AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withIpAddressCollectionDisabled(true) .build(); ``` #### 広告 ID(Ad ID)の収集と共有を無効にする \{#disable-advertising-id-ad-id-collection-and-sharing\} Adapty モジュールを有効化する際に、`adIdCollectionDisabled` を `true` に設定すると、ユーザーの[広告 ID](https://support.google.com/googleplay/android-developer/answer/6048248) の収集を無効にできます。デフォルト値は `false` です。 このパラメータは、Play Store のポリシーに準拠したり、広告 ID の権限プロンプトの表示を避けたり、Ad ID に基づく広告アトリビューションやアナリティクスがアプリに不要な場合に使用します。 ```kotlin showLineNumbers AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withAdIdCollectionDisabled(true) .build() ``` ```java showLineNumbers new AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withAdIdCollectionDisabled(true) .build(); ``` #### AdaptyUI のメディアキャッシュ設定をセットアップする \{#set-up-media-cache-configuration-for-adaptyui\} デフォルトでは、AdaptyUI はパフォーマンスの向上とネットワーク使用量の削減のために、画像や動画などのメディアをキャッシュします。カスタム設定を指定することでキャッシュの設定をカスタマイズできます。 `AdaptyUI.configureMediaCache` を使用して、デフォルトのキャッシュサイズと有効期間をオーバーライドします。これはオプションです。このメソッドを呼び出さない場合、デフォルト値(ディスクサイズ 100MB、有効期間 7 日)が使用されます。 ```kotlin showLineNumbers val cacheConfig = MediaCacheConfiguration.Builder() .overrideDiskStorageSizeLimit(200L * 1024 * 1024) // 200 MB .overrideDiskCacheValidityTime(3.days) .build() AdaptyUI.configureMediaCache(cacheConfig) ``` ```java showLineNumbers MediaCacheConfiguration cacheConfig = new MediaCacheConfiguration.Builder() .overrideDiskStorageSizeLimit(200L * 1024 * 1024) // 200 MB .overrideDiskCacheValidityTime(TimeInterval.days(3)) .build(); AdaptyUI.configureMediaCache(cacheConfig); ``` **パラメータ:** | パラメータ | 必須/任意 | 説明 | |-------------------------|----------|-----------------------------------------------------------------------------| | diskStorageSizeLimit | 任意 | ディスク上の合計キャッシュサイズ(バイト単位)。デフォルトは 100 MB。 | | diskCacheValidityTime | 任意 | キャッシュされたファイルが有効とみなされる期間。デフォルトは 7 日。 | :::tip `AdaptyUI.clearMediaCache(strategy)` を使用して、実行時にメディアキャッシュをクリアできます。`strategy` には `CLEAR_ALL` または `CLEAR_EXPIRED_ONLY` を指定します。 ::: ### 難読化アカウント ID を設定する \{#set-obfuscated-account-ids\} Google Play では、ユーザーのプライバシーとセキュリティを強化するために、特定のユースケースで難読化アカウント ID が必要です。これらの ID により、Google Play はユーザー情報を匿名に保ちながら購入を識別できます。これは特に不正防止とアナリティクスにおいて重要です。 アプリが機密性の高いユーザーデータを扱う場合や、特定のプライバシー規制に準拠する必要がある場合は、これらの ID を設定する必要があります。難読化された ID により、Google Play は実際のユーザー識別子を公開せずに購入を追跡できます。 ```kotlin showLineNumbers AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withObfuscatedAccountId("YOUR_OBFUSCATED_ACCOUNT_ID") .build() ``` ```java showLineNumbers new AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withObfuscatedAccountId("YOUR_OBFUSCATED_ACCOUNT_ID") .build(); ``` ### カスタムプロセスで Adapty を実行する \{#run-adapty-in-a-custom-process\} デフォルトでは、Adapty はアプリのメインプロセスでのみ実行できます。 アプリが複数のプロセスを使用する場合は、Adapty の初期化を一度だけ行ってください。そうしないと予期しない動作が発生する可能性があります。 別のプロセスで Adapty を実行する必要がある場合は、設定でプロセスを指定してください: ```kotlin showLineNumbers AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withProcessName(":custom") .build() ``` ```java showLineNumbers new AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withProcessName(":custom") .build(); ``` この値を設定せずに別のプロセスで Adapty を有効化しようとすると、SDK は警告をログに記録し、有効化をスキップします。 ### ローカルアクセスレベルを有効にする \{#enable-local-access-levels\} デフォルトでは、Android では[ローカルアクセスレベル](local-access-levels)が無効になっています。有効にするには、`withLocalAccessLevelAllowed` を `true` に設定してください: ```kotlin showLineNumbers AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withLocalAccessLevelAllowed(true) .build() ``` ```java showLineNumbers new AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withLocalAccessLevelAllowed(true) .build(); ``` ## トラブルシューティング \{#troubleshooting\} #### Android バックアップルール(自動バックアップの設定) \{#android-backup-rules-auto-backup-configuration\} 一部の SDK(Adapty を含む)は独自の Android 自動バックアップ設定を同梱しています。バックアップルールを定義する複数の SDK を使用している場合、Android マニフェストマージャーが `android:fullBackupContent`、`android:dataExtractionRules`、または `android:allowBackup` に関するエラーで失敗することがあります。 エラーの典型的な症状: `Manifest merger failed: Attribute application@dataExtractionRules value=(@xml/sample_data_extraction_rules) is also present at [com.other.sdk:library:1.0.0] value=(@xml/other_sdk_data_extraction_rules)` これを解決するには: - マニフェストマージャーにバックアップ関連の属性についてアプリの値を使用するよう指定する。 - Adapty と他の SDK のバックアップルールを単一の XML ファイル(Android 12 以上の場合はファイルのペア)にまとめる。 #### 1. マニフェストに `tools` 名前空間を追加する \{#1-add-the-tools-namespace-to-your-manifest\} まだ存在しない場合は、ルートの `` タグに `tools` 名前空間を追加してください: ```xml ... ``` #### 2. `` でバックアップ属性をオーバーライドする \{#2-override-backup-attributes-in-application\} アプリの `AndroidManifest.xml` で、`` タグを更新して、アプリが最終的な値を提供し、マニフェストマージャーにライブラリの値を置き換えるよう指示します: ```xml ... ``` いずれかの SDK でも `android:allowBackup` が設定されている場合は、`tools:replace` に含めてください: ```xml tools:replace="android:allowBackup,android:fullBackupContent,android:dataExtractionRules" ``` #### 3. マージされたバックアップルールファイルを作成する \{#3-create-merged-backup-rules-files\} `app/src/main/res/xml/` 以下に、Adapty のルールと他の SDK のルールを組み合わせた XML ファイルを作成します。Android は OS バージョンによって異なるバックアップルール形式を使用するため、両方のファイルを作成することでアプリがサポートするすべての Android バージョンとの互換性が確保されます。 :::note 以下の例では、サードパーティ SDK のサンプルとして AppsFlyer を使用しています。アプリで使用している他の SDK のルールに置き換えるか追加してください。 ::: **Android 12 以上向け**(新しいデータ抽出ルール形式を使用): ```xml title="sample_data_extraction_rules.xml" ``` **Android 11 以下向け**(従来のフルバックアップコンテンツ形式を使用): ```xml title="sample_backup_rules.xml" ``` この設定により: - Adapty のバックアップ除外設定(`AdaptySDKPrefs.xml`)が維持されます。 - 他の SDK の除外設定(例: `appsflyer-data`)も適用されます。 - マニフェストマージャーはアプリの設定を使用し、競合するバックアップ属性での失敗がなくなります。 #### 別のアプリから戻った後に購入が失敗する \{#purchases-fail-after-returning-from-another-app\} 購入フローを開始する Activity が非デフォルトの `launchMode` を使用している場合、ユーザーが Google Play、銀行アプリ、またはブラウザから戻ってきたときに Android が誤って Activity を再作成または再利用することがあります。これにより、購入結果が失われたり、キャンセルとして処理されたりする可能性があります。 購入が正しく機能するよう、購入フローを開始する Activity には `standard` または `singleTop` の起動モードのみを使用し、他のモードは避けてください。 `AndroidManifest.xml` で、購入フローを開始する Activity が `standard` または `singleTop` に設定されていることを確認してください: ```xml ``` --- # File: android-quickstart-paywalls --- --- title: "Android SDKのペイウォールを使ってアプリ内課金を有効にする" description: "アプリ内サブスクリプション管理のためのAdaptyセットアップクイックスタートガイド。" --- アプリ内課金を有効にするには、以下の3つの重要な概念を理解する必要があります。 - [**プロダクト**](product) – ユーザーが購入できるもの(サブスクリプション、消耗型アイテム、永続アクセスなど) - [**ペイウォール**](paywalls) – どのプロダクトを提供するかを定義する設定です。Adaptyでは、プロダクトを取得する唯一の方法がペイウォールです。この設計により、アプリのコードを変更せずに、提供内容・価格・プロダクトの組み合わせを変更できます。 - [**プレースメント**](placements) – アプリ内でペイウォールを表示する場所とタイミング(`main`、`onboarding`、`settings` など)。ダッシュボードでプレースメントにペイウォールを設定し、コードでプレースメントIDを指定して取得します。A/B テストの実施や、ユーザーごとに異なるペイウォールを表示するのも簡単です。 Adaptyでは、アプリ内課金を有効にする方法が3つあります。アプリの要件に合わせて選択してください。 | 実装方法 | 複雑さ | 適しているケース | |------------------------|------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Adapty ペイウォールビルダー | ✅ 簡単 | [ノーコードビルダーで完全な購入対応ペイウォールを作成する](quickstart-paywalls)場合。Adaptyが自動的にレンダリングし、複雑な購入フロー・レシート検証・サブスクリプション管理をすべてバックグラウンドで処理します。 | | 手動作成のペイウォール | 🟡 中程度 | アプリのコードでペイウォールUIを実装しつつ、プロダクト提供の柔軟性を維持するためにAdaptyからペイウォールオブジェクトを取得する場合。[ガイド](android-quickstart-manual)を参照してください。 | | オブザーバーモード | 🔴 難しい | 独自の購入処理インフラがすでにあり、そのまま利用したい場合。ただし、オブザーバーモードにはAdaptyでの制限があります。[記事](observer-vs-full-mode)を参照してください。 | :::important **以下の手順は、Adaptyペイウォールビルダーで作成したペイウォールを実装する方法を説明しています。** ペイウォールビルダーを使用しない場合は、[手動作成のペイウォールで購入を処理するガイド](android-making-purchases)を参照してください。 ::: Adaptyペイウォールビルダーで作成したペイウォールを表示するには、アプリのコードで以下の手順を実行するだけです。 1. **ペイウォールを取得する**: AdaptyからペイウォールOBJECTを取得します。 2. **ペイウォールを表示し、Adaptyが購入を処理する**: 取得したペイウォールコンテナをアプリに表示します。 3. **ボタンアクションを処理する**: ペイウォール上のユーザー操作とアプリの反応を関連付けます。例えば、ユーザーがボタンをクリックしたときにリンクを開いたり、ペイウォールを閉じたりします。 ## 始める前に \{#before-you-start\} 始める前に、以下の手順を完了してください。 1. Adapty ダッシュボードで[アプリをGoogle Playに接続する](initial-android)。 2. Adaptyで[プロダクトを作成する](create-product)。 3. [ペイウォールを作成してプロダクトを追加する](create-paywall)。 4. [プレースメントを作成してペイウォールを追加する](create-placement)。 5. アプリのコードに[Adapty SDKをインストールして有効化する](sdk-installation-android)。 :::tip これらの手順を最短で完了するには、[クイックスタートガイド](quickstart)に従うか、[Developer CLI](developer-cli-quickstart)を使ってペイウォールとプレースメントを作成してください。 ::: ## 1. ペイウォールを取得する \{#1-get-the-paywall\} ペイウォールはダッシュボードで設定したプレースメントに関連付けられています。プレースメントを使うと、異なるオーディエンスに異なるペイウォールを表示したり、[A/B テスト](ab-tests)を実施したりできます。 Adaptyペイウォールビルダーで作成したペイウォールを取得するには、以下の手順が必要です。 1. `getPaywall`メソッドを使って[プレースメント](placements)IDで`paywall`オブジェクトを取得し、それがビルダーで作成されたペイウォールかどうかを確認します。 2. `getViewConfiguration`メソッドを使ってペイウォールのビュー設定を取得します。ビュー設定には、ペイウォールを表示するためのUI要素とスタイリング情報が含まれています。 :::important ビュー設定を取得するには、ペイウォールビルダーの **Show on device** トグルをオンにする必要があります。オフのままでは空のビュー設定が返され、ペイウォールが表示されません。 ::: ```kotlin showLineNumbers Adapty.getPaywall("YOUR_PLACEMENT_ID") { result -> if (result is AdaptyResult.Success) { val paywall = result.value if (!paywall.hasViewConfiguration) { return@getPaywall } AdaptyUI.getViewConfiguration(paywall) { configResult -> if (configResult is AdaptyResult.Success) { val viewConfiguration = configResult.value } } } } ``` ```java showLineNumbers Adapty.getPaywall("YOUR_PLACEMENT_ID", result -> { if (result instanceof AdaptyResult.Success) { AdaptyPaywall paywall = ((AdaptyResult.Success) result).getValue(); if (!paywall.hasViewConfiguration()) { return; } AdaptyUI.getViewConfiguration(paywall, configResult -> { if (configResult instanceof AdaptyResult.Success) { AdaptyUI.LocalizedViewConfiguration viewConfiguration = ((AdaptyResult.Success) configResult).getValue(); // use loaded configuration } }); } }); ``` ## 2. ペイウォールを表示する \{#2-display-the-paywall\} ペイウォールの設定が取得できたら、数行のコードを追加するだけでペイウォールを表示できます。 デバイスの画面にビジュアルペイウォールを表示するには、まず設定を行う必要があります。`AdaptyUI.getPaywallView()`メソッドを呼び出すか、`AdaptyPaywallView`を直接作成してください。 ```kotlin showLineNumbers val paywallView = AdaptyUI.getPaywallView( activity, viewConfiguration, null, // products = null means auto-fetch eventListener, ) ``` ```kotlin showLineNumbers val paywallView = AdaptyPaywallView(activity) // or retrieve it from xml ... with(paywallView) { showPaywall( viewConfiguration, null, // products = null means auto-fetch eventListener, ) } ``` ```java showLineNumbers AdaptyPaywallView paywallView = AdaptyUI.getPaywallView( activity, viewConfiguration, null, // products = null means auto-fetch eventListener, ); ``` ```java showLineNumbers AdaptyPaywallView paywallView = new AdaptyPaywallView(activity); //add to the view hierarchy if needed, or you receive it from xml ... paywallView.showPaywall(viewConfiguration, products, eventListener); ``` ```xml showLineNumbers ``` ビューが正常に作成されたら、ビュー階層に追加してデバイスの画面に表示できます。 :::tip ペイウォールの表示方法の詳細については、[ガイド](android-present-paywalls)を参照してください。 ::: ## 3. ボタンアクションを処理する \{#3-handle-button-actions\} ユーザーがペイウォールのボタンをクリックすると、Android SDKは購入・復元・ペイウォールのクローズ・リンクのオープンを自動的に処理します。 ただし、カスタムまたは事前定義されたIDを持つボタンは、コード内でアクションを処理する必要があります。または、デフォルトの動作をオーバーライドしたい場合もあります。 例えば、以下はクローズボタンのデフォルト動作です。コードに追加する必要はありませんが、必要な場合の実装方法を確認できます。 :::tip ボタンの[アクション](android-handle-paywall-actions)と[イベント](android-handling-events)の処理方法については、ガイドを参照してください。 ::: ```kotlin showLineNumbers title="Kotlin" override fun onActionPerformed(action: AdaptyUI.Action, context: Context) { when (action) { AdaptyUI.Action.Close -> (context as? Activity)?.onBackPressed() // default behavior } } ``` ```java showLineNumbers @Override public void onActionPerformed(@NonNull AdaptyUI.Action action, @NonNull Context context) { if (action instanceof AdaptyUI.Action.Close) { if (context instanceof Activity) { ((Activity) context).onBackPressed(); } } } ``` ## 次のステップ \{#next-steps\} --- no_index: true --- import Callout from '../../../components/Callout.astro'; ご質問やお困りのことがあれば、[サポートフォーラム](https://adapty.featurebase.app/)をご覧ください。よくある質問への回答を見つけたり、ご自身の質問を投稿することができます。チームとコミュニティがサポートいたします! ペイウォールをアプリに表示する準備が整いました。[Google Play Storeでのテスト購入](testing-on-android)を行い、ペイウォールからテスト購入を完了できることを確認してください。 次に、適切なユーザーにペイウォールを表示したり有料機能へのアクセスを付与したりするために、[ユーザーのアクセスレベルを確認する](android-check-subscription-status)必要があります。 ## 完全な実装例 \{#full-example\} 以下は、これらのすべての手順をアプリに統合した例です。 ```kotlin showLineNumbers title="Kotlin" class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) Adapty.getPaywall("YOUR_PLACEMENT_ID") { paywallResult -> if (paywallResult is AdaptyResult.Success) { val paywall = paywallResult.value if (!paywall.hasViewConfiguration) { // Use custom logic return@getPaywall } AdaptyUI.getViewConfiguration(paywall) { configResult -> if (configResult is AdaptyResult.Success) { val viewConfiguration = configResult.value val paywallView = AdaptyUI.getPaywallView( this, viewConfiguration, null, // products = null means auto-fetch object : AdaptyUIEventListener { override fun onActionPerformed(action: AdaptyUI.Action, context: Context) { when (action) { is AdaptyUI.Action.Close -> { (context as? Activity)?.onBackPressed() } } } } ) setContentView(paywallView) } } } } } } ``` ```java showLineNumbers public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Adapty.getPaywall("YOUR_PLACEMENT_ID", paywallResult -> { if (paywallResult instanceof AdaptyResult.Success) { AdaptyPaywall paywall = ((AdaptyResult.Success) paywallResult).getValue(); if (!paywall.hasViewConfiguration()) { // Use custom logic return; } AdaptyUI.getViewConfiguration(paywall, configResult -> { if (configResult instanceof AdaptyResult.Success) { AdaptyUI.LocalizedViewConfiguration viewConfiguration = ((AdaptyResult.Success) configResult).getValue(); AdaptyPaywallView paywallView = AdaptyUI.getPaywallView( this, viewConfiguration, null, // products = null means auto-fetch new AdaptyUIEventListener() { @Override public void onActionPerformed(@NonNull AdaptyUI.Action action, @NonNull Context context) { if (action instanceof AdaptyUI.Action.Close) { if (context instanceof Activity) { ((Activity) context).onBackPressed(); } } } } ); setContentView(paywallView); } }); } }); } } ``` --- # File: android-check-subscription-status --- --- title: "Android SDKでサブスクリプションステータスを確認する" description: "AdaptyでAndroidアプリのサブスクリプションステータスを確認する方法を学びましょう。" --- 有料コンテンツへのアクセス許可やペイウォールの表示を判断するには、プロファイル内の[アクセスレベル](access-level)を確認する必要があります。 この記事では、プロファイルの状態にアクセスして、ペイウォールを表示するか有料機能へのアクセスを許可するかを決める方法を説明します。 ## サブスクリプションステータスを取得する \{#get-subscription-status\} ペイウォールを表示するか有料コンテンツを見せるかを判断するとき、プロファイルの[アクセスレベル](access-level)を確認します。方法は2つあります: - 最新のプロファイルデータがすぐに必要な場合(アプリ起動時など)や強制更新したい場合は、`getProfile` を呼び出す。 - **プロファイルの自動更新**を設定して、サブスクリプションステータスが変わるたびに自動でリフレッシュされるローカルコピーを保持する。 ### プロファイルを取得する \{#get-profile\} サブスクリプションステータスを取得する最もシンプルな方法は、`getProfile` メソッドを使ってプロファイルにアクセスすることです: ```kotlin showLineNumbers Adapty.getProfile { result -> when (result) { is AdaptyResult.Success -> { val profile = result.value // check the access } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` ```java showLineNumbers Adapty.getProfile(result -> { if (result instanceof AdaptyResult.Success) { AdaptyProfile profile = ((AdaptyResult.Success) result).getValue(); // check the access } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // handle the error } }); ``` ### サブスクリプション更新を監視する \{#listen-to-subscription-updates\} アプリでプロファイルの更新を自動的に受け取るには: 1. `Adapty.setOnProfileUpdatedListener()` を使ってプロファイルの変更を監視する。ユーザーのサブスクリプションステータスが変わると、Adaptyが自動でこのメソッドを呼び出します。 2. このメソッドが呼び出されたら更新されたプロファイルデータを保存し、追加のネットワークリクエストなしにアプリ全体で利用できるようにする。 ```kotlin class SubscriptionManager { private var currentProfile: AdaptyProfile? = null init { // Listen for profile updates Adapty.setOnProfileUpdatedListener { profile -> currentProfile = profile // Update UI, unlock content, etc. } } // Use stored profile instead of calling getProfile() fun hasAccess(): Boolean { return currentProfile?.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive == true } } ``` ```java public class SubscriptionManager { private AdaptyProfile currentProfile; public SubscriptionManager() { // Listen for profile updates Adapty.setOnProfileUpdatedListener(profile -> { this.currentProfile = profile; // Update UI, unlock content, etc. }); } // Use stored profile instead of calling getProfile() public boolean hasAccess() { if (currentProfile == null) { return false; } AdaptyAccessLevel premiumAccess = currentProfile.getAccessLevels().get("YOUR_ACCESS_LEVEL"); return premiumAccess != null && premiumAccess.isActive(); } } ``` :::note Adaptyはアプリ起動時にプロファイル更新リスナーを自動で呼び出し、デバイスがオフラインでもキャッシュされたサブスクリプションデータを提供します。 ::: ## プロファイルとペイウォールのロジックを連携させる \{#connect-profile-with-paywall-logic\} ペイウォールの表示や有料機能へのアクセス許可をすぐに判断する必要がある場合、ユーザーのプロファイルを直接確認できます。このアプローチは、アプリ起動時、プレミアムセクションへの遷移時、特定コンテンツの表示前など、さまざまなシナリオで役立ちます。 ```kotlin private fun initializePaywall() { loadPaywall { paywallView -> checkAccessLevel { result -> when (result) { is AdaptyResult.Success -> { if (!result.value && paywallView != null) { setContentView(paywallView) // Show paywall if no access } } is AdaptyResult.Error -> { if (paywallView != null) { setContentView(paywallView) // Show paywall if access check fails } } } } } } private fun checkAccessLevel(callback: ResultCallback) { Adapty.getProfile { result -> when (result) { is AdaptyResult.Success -> { val hasAccess = result.value.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive == true callback.onResult(AdaptyResult.Success(hasAccess)) } is AdaptyResult.Error -> { callback.onResult(AdaptyResult.Error(result.error)) } } } } ``` ```java private void initializePaywall() { loadPaywall(paywallView -> { checkAccessLevel(result -> { if (result instanceof AdaptyResult.Success) { boolean hasAccess = ((AdaptyResult.Success) result).getValue(); if (!hasAccess && paywallView != null) { setContentView(paywallView); // Show paywall if no access } } else if (result instanceof AdaptyResult.Error) { if (paywallView != null) { setContentView(paywallView); // Show paywall if access check fails } } }); }); } private void checkAccessLevel(ResultCallback callback) { Adapty.getProfile(result -> { if (result instanceof AdaptyResult.Success) { AdaptyProfile profile = ((AdaptyResult.Success) result).getValue(); AdaptyAccessLevel premiumAccess = profile.getAccessLevels().get("YOUR_ACCESS_LEVEL"); boolean hasAccess = premiumAccess != null && premiumAccess.isActive(); callback.onResult(AdaptyResult.success(hasAccess)); } else if (result instanceof AdaptyResult.Error) { callback.onResult(AdaptyResult.error(((AdaptyResult.Error) result).getError())); } }); } ``` ## 次のステップ \{#next-steps\} サブスクリプションステータスの確認方法を習得したら、次は[ユーザープロファイルの操作](android-quickstart-identify)を学び、ユーザーが購入済みのコンテンツにアクセスできるようにしましょう。 --- # File: android-quickstart-identify --- --- title: "Android SDKでのユーザー識別" description: "AndroidアプリにおけるAdaptyのアプリ内サブスクリプション管理のクイックスタートガイド。" --- :::important このガイドは、独自の認証システムを持つ方を対象としています。ここでは、既存の認証システムと連携させるために、Adaptyのユーザープロファイルを操作する方法を説明します。 ::: ユーザーの購入履歴の管理方法は、アプリの認証モデルによって異なります。 - アプリにバックエンド認証がなく、ユーザーデータを保存しない場合は、[匿名ユーザーに関するセクション](#anonymous-users)を参照してください。 - アプリにバックエンド認証がある(または今後追加する予定の)場合は、[識別済みユーザーに関するセクション](#identified-users)を参照してください。 **主要な概念**: - **プロファイル**はSDKが動作するために必要なエンティティです。Adaptyが自動的に作成します。 - プロファイルは匿名(**カスタマーユーザーIDなし**)または識別済み(**カスタマーユーザーIDあり**)のいずれかです。 - **カスタマーユーザーID**を提供することで、Adaptyのプロファイルと内部認証システムを相互参照できます。 匿名ユーザーと識別済みユーザーの違いは以下の通りです。 | | 匿名ユーザー | 識別済みユーザー | |-------------------------|---------------------------------------------------|-------------------------------------------------------------------------| | **購入の管理** | ストアレベルでの購入履歴の復元 | カスタマーユーザーIDを通じて端末をまたいで購入履歴を維持 | | **プロファイルの管理** | 再インストールのたびに新しいプロファイルが作成される | セッションや端末をまたいで同一プロファイルが使われる | | **データの永続性** | 匿名ユーザーのデータはアプリのインストールに紐づく | 識別済みユーザーのデータはアプリの再インストール後も維持される | ## 匿名ユーザー \{#anonymous-users\} バックエンド認証を使用しない場合、**アプリのコードで認証処理を実装する必要はありません**。 1. アプリの初回起動時にSDKが有効化されると、Adaptyは**ユーザーの新しいプロファイルを作成します**。 2. ユーザーがアプリ内で何かを購入すると、その購入は**Adaptyプロファイルとストアアカウントに関連付けられます**。 3. ユーザーがアプリを**再インストール**したり、**新しい端末**にインストールしたりすると、Adaptyは**有効化時に新しい匿名プロファイルを作成します**。 4. ユーザーが過去にアプリで購入を行っている場合、デフォルトではSDKの有効化時にApp Storeから購入履歴が自動的に同期されます。 匿名ユーザーの場合、インストールのたびに新しいプロファイルが作成されますが、Adaptyのアナリティクスでは[新規インストールとみなす条件を設定](general#4-installs-definition-for-analytics)できるため、これは問題になりません。 匿名ユーザーの場合、**デバイスID**でインストールをカウントする必要があります。この場合、端末への各アプリインストール(再インストールを含む)が1回のインストールとしてカウントされます。 ## 識別済みユーザー \{#identified-users\} アプリでユーザーを識別するには、2つの方法があります。 - [**ログイン/サインアップ時:**](#during-loginsignup) ユーザーがアプリ起動後にサインインする場合、認証時にカスタマーユーザーIDを指定して`identify()`を呼び出します。 - [**SDK有効化時:**](#during-the-sdk-activation) アプリ起動時にすでにカスタマーユーザーIDが保存されている場合、`activate()`を呼び出す際に一緒に送信します。 :::important デフォルトでは、Adaptyが別のカスタマーユーザーIDに現在関連付けられているカスタマーユーザーIDからの購入を受け取った場合、アクセスレベルは共有され、両方のプロファイルが有料アクセスを持ちます。この設定を変更して、有料アクセスを一方のプロファイルから別のプロファイルに移行したり、共有を完全に無効にしたりすることができます。詳細は[こちらの記事](general#6-sharing-paid-access-between-user-accounts)をご覧ください。 ::: ### ログイン/サインアップ時 \{#during-loginsignup\} アプリ起動後にユーザーを識別する場合(例:ログインまたはサインアップ後)、`identify`メソッドを使用してカスタマーユーザーIDを設定します。 - このカスタマーユーザーIDを**まだ使用したことがない場合**、Adaptyは自動的に現在のプロファイルにリンクします。 - このカスタマーユーザーIDを**以前にユーザーの識別に使用したことがある場合**、Adaptyはそのカスタマーユーザーに紐づくプロファイルに切り替えます。 :::important カスタマーユーザーIDは各ユーザーに対して一意である必要があります。パラメータの値をハードコードすると、すべてのユーザーが同一人物とみなされます。 ::: 他のSDKメソッドを呼び出す前に、`identify`の完了コールバックが呼ばれるまで待機してください。同時に呼び出すと、識別済みプロファイルではなく匿名プロファイルに処理が紐づく場合があります。詳細は[Android SDKの呼び出し順序](android-sdk-call-order)をご覧ください。 ```kotlin showLineNumbers Adapty.identify("YOUR_USER_ID") { error -> // Unique for each user if (error == null) { // successful identify } } ``` ```java showLineNumbers // User IDs must be unique for each user Adapty.identify("YOUR_USER_ID", error -> { if (error == null) { // successful identify } }); ``` ### SDK有効化時 \{#during-the-sdk-activation\} SDKを有効化する時点でカスタマーユーザーIDが分かっている場合、`identify`を別途呼び出す代わりに、`activate`メソッドに含めて送信できます。 カスタマーユーザーIDが分かっていても有効化後に設定する場合、有効化時にAdaptyは新しい匿名プロファイルを作成し、`identify`を呼び出した後にのみ既存のプロファイルに切り替えます。 既存のカスタマーユーザーID(以前に使用したもの)でも新しいものでも渡すことができます。新しいカスタマーユーザーIDを渡した場合、有効化時に作成された新しいプロファイルが自動的にそのカスタマーユーザーIDにリンクされます。 :::note デフォルトでは、匿名プロファイルの作成はアナリティクスのダッシュボードに影響しません。インストールはデバイスIDに基づいてカウントされるためです。 デバイスIDはストアからの端末へのアプリの単一インストールを表し、アプリを再インストールした場合にのみ再生成されます。 初回インストールか再インストールか、または既存のカスタマーユーザーIDが使用されているかどうかは関係ありません。 プロファイルの作成(SDKの有効化またはログアウト時)、ログイン、アプリの再インストールを伴わないアップグレードでは、追加のインストールイベントは発生しません。 デバイスではなく一意のユーザーに基づいてインストールをカウントしたい場合は、**App settings**から[**Installs definition for analytics**](general#4-installs-definition-for-analytics)を設定してください。 ::: ```kotlin showLineNumbers AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withCustomerUserId("user123") // Customer user IDs must be unique for each user. If you hardcode the parameter value, all users will be considered as one. .build() ``` ```java showLineNumbers new AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withCustomerUserId("user123") // Customer user IDs must be unique for each user. If you hardcode the parameter value, all users will be considered as one. .build(); ``` ### ユーザーのログアウト \{#log-users-out\} ユーザーをログアウトさせるボタンがある場合は、`logout`メソッドを使用してください。 :::important ユーザーをログアウトすると、そのユーザー用に新しい匿名プロファイルが作成されます。 ::: ```kotlin showLineNumbers Adapty.logout { error -> if (error == null) { // successful logout } } ``` ```java showLineNumbers Adapty.logout(error -> { if (error == null) { // successful logout } }); ``` :::info ユーザーをアプリに再ログインさせるには、`identify`メソッドを使用してください。 ::: ### ログインなしでの購入を許可する \{#allow-purchases-without-login\} ユーザーがアプリへのログイン前後どちらでも購入できる場合、ログイン後もアクセスが維持されるようにする必要があります。 1. ログアウト状態のユーザーが購入を行うと、Adaptyはその購入を匿名プロファイルIDに紐付けます。 2. ユーザーがアカウントにログインすると、Adaptyは識別済みプロファイルへの切り替えを行います。 - 新しいカスタマーユーザーIDの場合(例:登録前に購入が行われた場合)、Adaptyは現在のプロファイルにカスタマーユーザーIDを割り当てるため、すべての購入履歴が維持されます。 - 既存のカスタマーユーザーIDの場合(そのカスタマーユーザーIDがすでにプロファイルにリンクされている場合)、プロファイル切り替え後に実際のアクセスレベルを取得する必要があります。識別後すぐに[`getProfile`](android-check-subscription-status)を呼び出すか、[プロファイルの更新をリッスン](android-check-subscription-status)してデータが自動的に同期されるようにすることができます。 ## 次のステップ \{#next-steps\} おめでとうございます!アプリにアプリ内課金のロジックを実装できました!アプリのマネタイズが順調に進むことを願っています! Adaptyをさらに活用するために、以下のトピックもご覧ください。 - [**テスト**](troubleshooting-test-purchases): すべてが期待通りに動作することを確認する - [**オンボーディング**](android-onboardings): オンボーディングでユーザーを引き付け、リテンションを高める - [**インテグレーション**](configuration): マーケティングアトリビューションや分析サービスとたった1行のコードで連携する - [**カスタムプロファイル属性の設定**](android-setting-user-attributes): ユーザープロファイルにカスタム属性を追加してセグメントを作成し、A/Bテストを実施したり、ユーザーごとに異なるペイウォールを表示したりする --- # File: adapty-sdk-integration-skill-android --- --- title: "SDKインテグレーションスキルを使ってAdaptyをAndroidアプリに統合する" description: "adapty-sdk-integrationスキルを使って、AIコーディングツールでAdapty SDKをAndroidアプリにエンドツーエンドで統合しましょう。" --- :::important このスキルはベータ版です。処理が止まったり予期しない動作をした場合は、代わりに[ステップバイステップの統合ガイド](adapty-cursor-android)をご利用ください。AIツールが各ステップを適切なドキュメントとともに進められるようになっています。 ::: --- no_index: true --- [adapty-sdk-integration スキル](https://github.com/adaptyteam/adapty-sdk-integration-skill)は、Adapty のインテグレーションをエンドツーエンドで自動化します。ダッシュボードのセットアップ、SDK のインストール、ペイウォール、各ステージの検証まで対応しています。プラットフォームを自動検出し、各ステージで関連する Adapty ドキュメントを取得します。 **対応ツール**: Claude Code、GitHub Copilot CLI、OpenAI Codex、Gemini CLI。 インストールするには、お使いのツール向けのフォームを選択してください。完全なリストは[スキルの README](https://github.com/adaptyteam/adapty-sdk-integration-skill) をご覧ください。 **Claude Code** ``` claude plugin marketplace add adaptyteam/adapty-sdk-integration-skill claude plugin install adapty-sdk-integration@adapty ``` **GitHub Copilot CLI** ``` gh skill install adaptyteam/adapty-sdk-integration-skill ``` **Gemini CLI** ``` gemini skills install https://github.com/adaptyteam/adapty-sdk-integration-skill ``` **OpenAI Codex またはその他のツール**: リポジトリをクローンし、`plugins/adapty-sdk-integration/skills/adapty-sdk-integration/` をツールのスキルディレクトリにコピーしてください。 インストール後、プロジェクト内でスキルを実行します: ``` /adapty-sdk-integration ``` スキルがいくつかのセットアップ質問を行い、その後ダッシュボードのセットアップ、SDK のインストール、ペイウォール、検証の手順を案内します。 --- # File: adapty-cursor-android --- --- title: "AIを使ってAndroidアプリにAdaptyを統合する" description: "Cursor、Context7、ChatGPT、Claude、その他のAIツールを使って、AndroidアプリにAdaptyをステップバイステップで統合するガイド。" --- このガイドでは、AIコーディングツールを使って、AdaptyをAndroidアプリへ段階的に統合していきます。適切なAdaptyドキュメントを正しい順番でAIに渡すのがポイントです。 For a fully automated integration, use the [adapty-sdk-integration skill](https://github.com/adaptyteam/adapty-sdk-integration-skill): it runs the whole integration from your AI coding tool in one command. ## 始める前に:ダッシュボードの設定 \{#before-you-start-dashboard-setup\} AdaptyはSDKコードを書く前に、ダッシュボードで一定の設定が必要です。インタラクティブなLLMスキルを使う方法と、ダッシュボードから手動で行う方法があります。 ### スキルを使う方法(推奨) \{#skill-approach-recommended\} Adapty CLIスキルを使えば、LLMがアプリ、プロダクト、アクセスレベル、ペイウォール、プレースメントを直接設定できます。各ステップでダッシュボードを開く必要がなく、[ストアの接続](integrate-payments)だけダッシュボードで行えば十分です。 ``` npx skills add adaptyteam/adapty-cli --skill adapty-cli ``` スキルを追加したら、エージェント内で `/adapty-cli` を実行してください。ストアに接続するためにダッシュボードを開くタイミングも含め、各ステップを案内してくれます。 ### ダッシュボードを使う方法 \{#dashboard-approach\} 手動ですべてを設定したい場合は、コードを書き始める前に以下の準備が必要です。ダッシュボードの値はLLMが調べることができないため、自分で用意する必要があります。 1. **アプリストアを接続する**: Adapty ダッシュボードで **App settings → General** へ移動します。購入機能を動かすには必須です。 [Google Playを接続する](integrate-payments) 2. **Public SDKキーをコピーする**: Adapty ダッシュボードで **App settings → General** へ移動し、**API keys** セクションを確認します。コード内では、Adaptyの設定ビルダーに渡す文字列として使用します。 3. **プロダクトを1つ以上作成する**: Adapty ダッシュボードの **Products** ページへ移動します。プロダクトはコード内で直接参照しません — Adatyはペイウォールを通じてプロダクトを届けます。 [プロダクトを追加する](quickstart-products) 4. **ペイウォールとプレースメントを作成する**: Adapty ダッシュボードで **Paywalls** ページにペイウォールを作成し、**Placements** ページでプレースメントに割り当てます。コード内では、`Adapty.getPaywall("YOUR_PLACEMENT_ID")` に渡す文字列がプレースメントIDです。 [ペイウォールを作成する](quickstart-paywalls) 5. **アクセスレベルを設定する**: Adapty ダッシュボードで **Products** ページのプロダクトごとに設定します。コード内では `profile.accessLevels["premium"]?.isActive` でチェックする文字列です。デフォルトの `premium` アクセスレベルはほとんどのアプリで機能します。プロダクトによって(例:`basic` プランと `pro` プランなど)ユーザーがアクセスできる機能が異なる場合は、コーディングを始める前に[アクセスレベルを追加作成](assigning-access-level-to-a-product)してください。 :::tip 以上の5つが揃ったら、コードを書く準備完了です。「Public SDKキーはX、プレースメントIDはY」とLLMに伝えると、正しい初期化コードとペイウォール取得コードを生成してもらえます。 ::: ### 準備ができたら設定するもの \{#set-up-when-ready\} コーディング開始に必須ではありませんが、統合が進んだ段階で必要になります。 - **A/Bテスト**: **Placements** ページで設定します。コードの変更は不要です。 [A/Bテスト](ab-tests) - **追加のペイウォールとプレースメント**: 異なるプレースメントIDで `getPaywall` 呼び出しを追加します。 - **アナリティクス連携**: **Integrations** ページで設定します。連携先によって手順が異なります。[アナリティクス連携](analytics-integration)・[アトリビューション連携](attribution-integration)を参照してください。 ## LLMにAdaptyドキュメントを渡す \{#feed-adapty-docs-to-your-llm\} ### Context7を使う(推奨) \{#use-context7-recommended\} [Context7](https://context7.com) は、LLMに最新のAdaptyドキュメントへの直接アクセスを提供するMCPサーバーです。質問内容に基づいて適切なドキュメントを自動的に取得するため、URLを手動で貼り付ける必要がありません。 Context7は **Cursor**、**Claude Code**、**Windsurf**、その他MCP対応ツールで動作します。セットアップするには以下を実行してください: ``` npx ctx7 setup ``` エディタを自動検出してContext7サーバーを設定します。手動セットアップの方法は [Context7 GitHubリポジトリ](https://github.com/upstash/context7)をご覧ください。 設定完了後、プロンプトでAdaptyライブラリを参照できます: ``` Use the adaptyteam/adapty-docs library to look up how to install the Android SDK ``` :::warning Context7を使えばドキュメントのリンクを手動で貼り付ける必要はなくなりますが、実装の順序は重要です。すべてが正しく動作するよう、以下の[実装ウォークスルー](#implementation-walkthrough)をステップごとに進めてください。 ::: ### プレーンテキストドキュメントを使う \{#use-plain-text-docs\} AdaptyのドキュメントはプレーンテキストのMarkdownとして取得できます。URLの末尾に `.md` を追加するか、記事タイトル下の **Copy for LLM** をクリックしてください。例:[adapty-cursor-android.md](https://adapty.io/docs/ja/adapty-cursor-android.md) 以下の[実装ウォークスルー](#implementation-walkthrough)の各ステップには、貼り付けるための `.md` リンクが入った「LLMへ送るプロンプト」ブロックがあります。 まとめて多くのドキュメントを取得する場合は、以下の[インデックスファイルとプラットフォーム別サブセット](#plain-text-doc-index-files)を参照してください。 ## 実装ウォークスルー \{#implementation-walkthrough\} ここからは、実装順にAdaptyの統合を進めます。各ステージには、LLMに送るドキュメント、完了時に確認すべき内容、よくある問題が含まれています。 ### 統合計画を立てる \{#plan-your-integration\} コードを書き始める前に、LLMにプロジェクトを分析させ、実装計画を作成してもらいましょう。AIツールに計画モード(CursorやClaude Codeのプランモードなど)がある場合は、LLMがコードを書く前にプロジェクト構造とAdaptyドキュメントの両方を読めるよう活用してください。 購入に使うアプローチをLLMに伝えてください — これにより、参照すべきガイドが変わります。 - [**Adaptyペイウォールビルダー**](adapty-paywall-builder): Adaptのノーコードビルダーでペイウォールを作成し、SDKが自動でレンダリングします。 - [**手動作成のペイウォール**](android-making-purchases): 自分でペイウォールUIをコードで構築しつつ、プロダクトの取得と購入処理はAdaptyを使います。 - [**オブザーバーモード**](observer-vs-full-mode): 既存の購入インフラを維持したまま、アナリティクスと連携にのみAdaptyを使います。 どれを選べばいいかわからない場合は、[クイックスタートの比較表](android-quickstart-paywalls)をご覧ください。 ### SDKのインストールと設定 \{#install-and-configure-the-sdk\} Android StudioでGradleを使ってAdapty SDKの依存関係を追加し、Public SDKキーで有効化します。これが基盤となるため、他の機能はすべてこのステップが完了しないと動きません。 **ガイド:** [Adapty SDKのインストールと設定](sdk-installation-android) LLMへ送るプロンプト: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/sdk-installation-android.md ``` :::tip[チェックポイント] - **期待される結果:** アプリがビルド・実行され、LogcatにAdaptyのアクティベーションログが表示される。 - **注意点:** 「Public API key is missing」エラーが出た場合 → プレースホルダーをApp settingsで確認した実際のキーに置き換えたか確認してください。 ::: ### ペイウォールの表示と購入処理 \{#show-paywalls-and-handle-purchases\} プレースメントIDでペイウォールを取得し、表示して、購入イベントを処理します。必要なガイドは購入処理の方法によって異なります。 進めながらサンドボックスで各購入をテストしてください。最後まで待たないようにしましょう。セットアップ方法は[サンドボックスでの購入テスト](test-purchases-in-sandbox)をご覧ください。 **ガイド:** - [ペイウォールを使って購入を有効にする(クイックスタート)](android-quickstart-paywalls) - [ペイウォールビルダーのペイウォールと設定の取得](android-get-pb-paywalls) - [ペイウォールの表示](android-present-paywalls) - [ペイウォールイベントの処理](android-handling-events) - [ボタンアクションへの対応](android-handle-paywall-actions) LLMへ送るプロンプト: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/android-quickstart-paywalls.md - https://adapty.io/docs/ja/android-get-pb-paywalls.md - https://adapty.io/docs/ja/android-present-paywalls.md - https://adapty.io/docs/ja/android-handling-events.md - https://adapty.io/docs/ja/android-handle-paywall-actions.md ``` :::tip[チェックポイント] - **期待される結果:** 設定したプロダクトとともにペイウォールが表示され、プロダクトをタップするとサンドボックスの購入ダイアログが起動する。 - **注意点:** ペイウォールが空、または `getPaywall` エラーが出る場合 → プレースメントIDがダッシュボードと完全に一致しているか、プレースメントにオーディエンスが割り当てられているかを確認してください。 ::: **ガイド:** - [カスタムペイウォールで購入を有効にする(クイックスタート)](android-quickstart-manual) - [ペイウォールとプロダクトの取得](fetch-paywalls-and-products-android) - [リモートコンフィグで設計したペイウォールのレンダリング](present-remote-config-paywalls-android) - [購入処理](android-making-purchases) - [購入の復元](android-restore-purchase) LLMへ送るプロンプト: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/android-quickstart-manual.md - https://adapty.io/docs/ja/fetch-paywalls-and-products-android.md - https://adapty.io/docs/ja/present-remote-config-paywalls-android.md - https://adapty.io/docs/ja/android-making-purchases.md - https://adapty.io/docs/ja/android-restore-purchase.md ``` :::tip[チェックポイント] - **期待される結果:** カスタムペイウォールにAdaptyから取得したプロダクトが表示され、プロダクトをタップするとサンドボックスの購入ダイアログが起動する。 - **注意点:** プロダクト配列が空の場合 → ダッシュボードでペイウォールにプロダクトが割り当てられているか、プレースメントにオーディエンスがあるかを確認してください。 ::: **ガイド:** - [オブザーバーモードの概要](observer-vs-full-mode) - [オブザーバーモードの実装](implement-observer-mode-android) - [オブザーバーモードでのトランザクション報告](report-transactions-observer-mode-android) LLMへ送るプロンプト: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/observer-vs-full-mode.md - https://adapty.io/docs/ja/implement-observer-mode-android.md - https://adapty.io/docs/ja/report-transactions-observer-mode-android.md ``` :::tip[チェックポイント] - **期待される結果:** 既存の購入フローでサンドボックス購入を行った後、Adapty ダッシュボードの **Event Feed** にトランザクションが表示される。 - **注意点:** イベントが表示されない場合 → Adaptyへのトランザクション報告が設定されているか、Google Play リアルタイム デベロッパー通知が設定されているかを確認してください。 ::: ### サブスクリプションのステータス確認 \{#check-subscription-status\} 購入後、ユーザープロファイルでアクティブなアクセスレベルを確認し、プレミアムコンテンツへのアクセスを制御します。 **ガイド:** [サブスクリプションのステータス確認](android-check-subscription-status) LLMへ送るプロンプト: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/android-check-subscription-status.md ``` :::tip[チェックポイント] - **期待される結果:** サンドボックスで購入後、`profile.accessLevels["premium"]?.isActive` が `true` を返す。 - **注意点:** 購入後に `accessLevels` が空の場合 → ダッシュボードでプロダクトにアクセスレベルが割り当てられているかを確認してください。 ::: ### ユーザーの識別 \{#identify-users\} アプリのユーザーアカウントとAdaptyプロファイルを紐付けることで、デバイスをまたいで購入情報が維持されます。 :::important アプリに認証機能がない場合はこのステップをスキップしてください。 ::: **ガイド:** [ユーザーの識別](android-quickstart-identify) LLMへ送るプロンプト: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/android-quickstart-identify.md ``` :::tip[チェックポイント] - **期待される結果:** `Adapty.identify("your-user-id")` を呼び出した後、ダッシュボードの **Profiles** セクションにカスタムユーザーIDが表示される。 - **注意点:** アクティベーション後・ペイウォール取得前に `identify` を呼び出すことで、匿名プロファイルへのアトリビューションを防げます。 ::: ### リリース準備 \{#prepare-for-release\} サンドボックスでの統合確認が完了したら、リリースチェックリストに沿ってプロダクション対応を確認しましょう。 **ガイド:** [リリースチェックリスト](release-checklist) LLMへ送るプロンプト: ``` Read these Adapty docs before releasing: - https://adapty.io/docs/ja/release-checklist.md ``` :::tip[チェックポイント] - **期待される結果:** チェックリストの全項目を確認済み:ストア接続、サーバー通知、購入フロー、アクセスレベルの確認、プライバシー要件。 - **注意点:** Google Play リアルタイム デベロッパー通知が未設定の場合 → **App settings → Android SDK** で設定してください。設定しないとダッシュボードにイベントが表示されません。 ::: ## プレーンテキストドキュメントのインデックスファイル \{#plain-text-doc-index-files\} 個別ページを超えた幅広いコンテキストをLLMに提供したい場合は、Adaptyドキュメント全体をまとめたインデックスファイルを用意しています: - [`llms.txt`](https://adapty.io/docs/ja/llms.txt): すべてのページを `.md` リンク付きで一覧表示。LLMがウェブサイトにアクセスしやすくするための[新興標準](https://llmstxt.org/)です。一部のAIエージェント(ChatGPTなど)では、`llms.txt` をダウンロードしてチャットにファイルとしてアップロードする必要があります。 - [`llms-full.txt`](https://adapty.io/docs/ja/llms-full.txt): Adaptyドキュメントサイト全体を1つのファイルにまとめたもの。非常に大きなファイルのため、全体像が必要なときのみ使用してください。 - Android専用の [`android-llms.txt`](https://adapty.io/docs/ja/android-llms.txt) と [`android-llms-full.txt`](https://adapty.io/docs/ja/android-llms-full.txt): サイト全体と比べてトークン数を節約できるプラットフォーム別サブセットです。 --- # File: android-get-pb-paywalls --- --- title: "Android SDKでペイウォールビルダーのペイウォールとその設定を取得する" description: "Android アプリのサブスクリプション管理を改善するために、Adapty で PB ペイウォールを取得する方法をご紹介します。" --- Adapty ダッシュボードの新しいペイウォールビルダーで[ペイウォールのビジュアル部分をデザイン](adapty-paywall-builder)したら、モバイルアプリにそれを表示できます。まず最初に、プレースメントに紐づくペイウォールとそのビュー設定を以下の手順で取得します。 :::warning 新しいペイウォールビルダーは Android SDK バージョン 3.0 以上で動作します。 ::: このトピックはペイウォールビルダーでカスタマイズしたペイウォールに関するものです。ペイウォールを手動で実装する場合は、[モバイルアプリでリモートコンフィグペイウォールのペイウォールとプロダクトを取得する](fetch-paywalls-and-products-android)をご参照ください。 :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 :::
モバイルアプリでペイウォールを表示する前に(クリックして展開) 1. Adapty ダッシュボードで[プロダクトを作成](create-product)する。 2. Adapty ダッシュボードで[ペイウォールを作成し、プロダクトを組み込む](create-paywall)。 3. Adapty ダッシュボードで[プレースメントを作成し、ペイウォールを組み込む](create-placement)。 4. モバイルアプリに [Adapty SDK](sdk-installation-android) をインストールする。
## ペイウォールビルダーでデザインしたペイウォールを取得する \{#fetch-paywall-designed-with-paywall-builder\} [ペイウォールビルダーでペイウォールをデザイン](adapty-paywall-builder)した場合、モバイルアプリのコードでそれをレンダリングしてユーザーに表示する必要はありません。このようなペイウォールには、表示する内容と表示方法の両方が含まれています。ただし、プレースメントを通じてそのIDを取得し、ビュー設定を取得した上でモバイルアプリに表示する必要があります。 最適なパフォーマンスを確保するには、ペイウォールとその[ビュー設定](android-get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder)をできるだけ早く取得し、ユーザーに表示する前に画像のダウンロードが完了するよう十分な時間を確保することが重要です。 ペイウォールを取得するには、`getPaywall` メソッドを使用します。 ```kotlin showLineNumbers ... Adapty.getPaywall("YOUR_PLACEMENT_ID", locale = "en", loadTimeout = 10.seconds) { result -> when (result) { is AdaptyResult.Success -> { val paywall = result.value // the requested paywall } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` ```java showLineNumbers ... Adapty.getPaywall("YOUR_PLACEMENT_ID", "en", TimeInterval.seconds(10), result -> { if (result instanceof AdaptyResult.Success) { AdaptyPaywall paywall = ((AdaptyResult.Success) result).getValue(); // the requested paywall } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // handle the error } }); ``` パラメータ: | パラメータ | 必須/任意 | 説明 | |---------|--------|-----------| | **placementId** | 必須 | 取得したい[プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** |

任意

デフォルト: `en`

|

[ペイウォールのローカライズ](add-paywall-locale-in-adapty-paywall-builder)の識別子。このパラメータは、マイナス(**-**)で区切られた 1 つまたは 2 つのサブタグで構成される言語コードです。最初のサブタグは言語、2 番目はリージョンを表します。

例:`en` は英語、`pt-br` はブラジルポルトガル語を表します。

ロケールコードとその推奨される使用方法については、[ローカライズとロケールコード](localizations-and-locale-codes)をご参照ください。

| | **fetchPolicy** | デフォルト: `.reloadRevalidatingCacheData` |

デフォルトでは、SDK はサーバーからデータの読み込みを試み、失敗した場合はキャッシュされたデータを返します。ユーザーが常に最新のデータを取得できるため、この設定を推奨します。

ただし、インターネット接続が不安定なユーザーが多い場合は、`.returnCacheDataElseLoad` を使用してキャッシュが存在する場合はそれを返すことを検討してください。この場合、ユーザーは最新のデータを取得できない可能性がありますが、接続状況に関わらず読み込みが速くなります。キャッシュは定期的に更新されるため、セッション中にネットワークリクエストを避けるために使用しても問題ありません。

キャッシュはアプリの再起動後も保持され、アプリを再インストールするか手動でクリアした場合のみ削除されます。

Adapty SDK はペイウォールを 2 層でローカルに保存します。上記の定期更新キャッシュと[フォールバックペイウォール](fallback-paywalls)です。また、CDN を使用してペイウォールを高速に取得し、CDN に到達できない場合はスタンドアロンのフォールバックサーバーも使用します。このシステムは、インターネット接続が不安定な場合でも、常に最新バージョンのペイウォールを確実に取得できるよう設計されています。

| | **loadTimeout** | デフォルト: 5 秒 |

このメソッドのタイムアウト制限を設定する値。タイムアウトに達した場合、キャッシュされたデータまたはローカルフォールバックが返されます。

内部で複数のリクエストが実行される場合があるため、まれに `loadTimeout` で指定した時間よりもわずかに遅れてタイムアウトになることがあります。

Android の場合:拡張関数(`import com.adapty.utils.seconds` の `.seconds` など)を使って `TimeInterval` を作成するか、`TimeInterval.seconds(5)` を使用します。制限なしに設定するには `TimeInterval.INFINITE` を使用します。

| レスポンスパラメータ: | パラメータ | 説明 | | :-------- |:----------------------------------------------------------------------------------------------------------------------------------------------------------------| | Paywall | プロダクト ID のリスト、ペイウォール識別子、リモートコンフィグ、その他いくつかのプロパティを含む [`AdaptyPaywall`](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall/) オブジェクト。 | ## ペイウォールビルダーでデザインしたペイウォールのビュー設定を取得する \{#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder\} :::important ペイウォールビルダーで **Show on device** トグルが有効になっていることを確認してください。このオプションが有効でない場合、ビュー設定は取得できません。 ::: ペイウォールを取得したら、`ViewConfiguration` が含まれているか確認します。これはペイウォールビルダーで作成されたことを示します。`ViewConfiguration` がある場合はペイウォールビルダーのペイウォールとして扱い、ない場合は[リモートコンフィグペイウォールとして処理](present-remote-config-paywalls)してください。 ビュー設定を読み込むには `getViewConfiguration` メソッドを使用します。 ```kotlin showLineNumbers if (!paywall.hasViewConfiguration) { // use your custom logic return } AdaptyUI.getViewConfiguration(paywall, loadTimeout = 10.seconds) { result -> when(result) { is AdaptyResult.Success -> { val viewConfiguration = result.value // use loaded configuration } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` | パラメータ | 必須/任意 | 説明 | | :-------------- | :------------- | :----------------------------------------------------------- | | **paywall** | 必須 | 目的のペイウォールのコントローラーを取得するための `AdaptyPaywall` オブジェクト。 | | **loadTimeout** | デフォルト: 5 秒 | このメソッドのタイムアウト制限を設定する値。タイムアウトに達した場合、キャッシュされたデータまたはローカルフォールバックが返されます。内部で複数のリクエストが実行される場合があるため、まれに `loadTimeout` で指定した時間よりもわずかに遅れてタイムアウトになることがあります。 | ビュー設定を読み込むには `getViewConfiguration` メソッドを使用します。 ```java showLineNumbers if (!paywall.hasViewConfiguration()) { // use your custom logic return; } AdaptyUI.getViewConfiguration(paywall, TimeInterval.seconds(10), result -> { if (result instanceof AdaptyResult.Success) { AdaptyUI.LocalizedViewConfiguration viewConfiguration = ((AdaptyResult.Success) result).getValue(); // use loaded configuration } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // handle the error } }); ``` | パラメータ | 必須/任意 | 説明 | | :----------------------- | :------------- | :----------------------------------------------------------- | | **paywall** | 必須 | 目的のペイウォールのコントローラーを取得するための `AdaptyPaywall` オブジェクト。 | | **loadTimeout** | デフォルト: 5 秒 | このメソッドのタイムアウト制限を設定する値。タイムアウトに達した場合、キャッシュされたデータまたはローカルフォールバックが返されます。内部で複数のリクエストが実行される場合があるため、まれに `loadTimeout` で指定した時間よりもわずかに遅れてタイムアウトになることがあります。 | :::note 複数の言語を使用している場合は、[ペイウォールビルダーのローカライズ](add-paywall-locale-in-adapty-paywall-builder)の追加方法と、ロケールコードの正しい使い方を[こちら](android-localizations-and-locale-codes)でご確認ください。 ::: 読み込みが完了したら、[ペイウォールを表示](android-present-paywalls)します。 ## デフォルトオーディエンス向けのペイウォールを高速取得する \{#get-a-paywall-for-a-default-audience-to-fetch-it-faster\} 通常、ペイウォールはほぼ即座に取得できるため、速度を気にする必要はありません。ただし、オーディエンスやペイウォールが多数あり、ユーザーのインターネット接続が弱い場合は、取得に時間がかかることがあります。そのような場合、ペイウォールをまったく表示しないよりも、デフォルトのペイウォールを表示してスムーズなユーザー体験を確保したいことがあるかもしれません。 この問題に対応するため、`getPaywallForDefaultAudience` メソッドを使用できます。このメソッドは、**All Users** オーディエンス向けに指定したプレースメントのペイウォールを取得します。ただし、推奨されるアプローチは上記の[ペイウォール情報の取得](#fetch-paywall-designed-with-paywall-builder)セクションで説明した `getPaywall` メソッドによる取得です。 :::warning `getPaywall` を推奨する理由 `getPaywallForDefaultAudience` メソッドにはいくつかの重要な欠点があります。 - **後方互換性の問題が生じる可能性**:現在および将来のアプリバージョンで異なるペイウォールを表示する必要がある場合、課題が生じることがあります。現在(レガシー)バージョンをサポートするペイウォールを設計するか、現在(レガシー)バージョンのユーザーがレンダリングされないペイウォールに遭遇するリスクを受け入れるかのいずれかになります。 - **ターゲティングの喪失**:すべてのユーザーが **All Users** オーディエンス向けに設計された同じペイウォールを見ることになり、国別、マーケティングアトリビューション、またはカスタム属性に基づくパーソナライズドターゲティングが失われます。 これらの欠点を受け入れてでもペイウォールの高速取得のメリットを得たい場合は、以下のように `getPaywallForDefaultAudience` メソッドを使用してください。そうでない場合は、[上記](#fetch-paywall-designed-with-paywall-builder)で説明した `getPaywall` を使い続けてください。 ::: ```kotlin showLineNumbers Adapty.getPaywallForDefaultAudience("YOUR_PLACEMENT_ID", locale = "en") { result -> when (result) { is AdaptyResult.Success -> { val paywall = result.value // the requested paywall } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` ```java showLineNumbers Adapty.getPaywallForDefaultAudience("YOUR_PLACEMENT_ID", "en", result -> { if (result instanceof AdaptyResult.Success) { AdaptyPaywall paywall = ((AdaptyResult.Success) result).getValue(); // the requested paywall } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // handle the error } }); ``` :::note `getPaywallForDefaultAudience` メソッドは Android SDK 2.11.3 以降で利用可能です。 ::: | パラメータ | 必須/任意 | 説明 | |---------|--------|-----------| | **placementId** | 必須 | [プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** |

任意

デフォルト: `en`

|

[ペイウォールのローカライズ](add-remote-config-locale)の識別子。このパラメータは、マイナス(**-**)で区切られた 1 つ以上のサブタグで構成される言語コードです。最初のサブタグは言語、2 番目はリージョンを表します。

例:`en` は英語、`pt-br` はブラジルポルトガル語を表します。

ロケールコードとその推奨される使用方法については、[ローカライズとロケールコード](localizations-and-locale-codes)をご参照ください。

| | **fetchPolicy** | デフォルト: `.reloadRevalidatingCacheData` |

デフォルトでは、SDK はサーバーからデータの読み込みを試み、失敗した場合はキャッシュされたデータを返します。ユーザーが常に最新のデータを取得できるため、この設定を推奨します。

ただし、インターネット接続が不安定なユーザーが多い場合は、`.returnCacheDataElseLoad` を使用してキャッシュが存在する場合はそれを返すことを検討してください。この場合、ユーザーは最新のデータを取得できない可能性がありますが、接続状況に関わらず読み込みが速くなります。キャッシュは定期的に更新されるため、セッション中にネットワークリクエストを避けるために使用しても問題ありません。

キャッシュはアプリの再起動後も保持され、アプリを再インストールするか手動でクリアした場合のみ削除されます。

| ## アセットのカスタマイズ \{#customize-assets\} ペイウォール内の画像や動画をカスタマイズするには、カスタムアセットを実装します。 ヒーロー画像と動画には定義済みの ID(`hero_image` と `hero_video`)があります。カスタムアセットバンドルでは、これらの ID でそれぞれの要素を指定し、動作をカスタマイズします。 その他の画像や動画については、Adapty ダッシュボードで[カスタム ID を設定](custom-media)する必要があります。 たとえば、以下のようなことができます。 - 一部のユーザーに別の画像や動画を表示する。 - リモートのメイン画像を読み込んでいる間、ローカルのプレビュー画像を表示する。 - 動画を再生する前にプレビュー画像を表示する。 :::important この機能を使用するには、Adapty Android SDK をバージョン 3.7.0 以上にアップデートしてください。 ::: カスタムアセットをシンプルな辞書形式で提供する例を次に示します。 ```kotlin showLineNumbers val customAssets = AdaptyCustomAssets.of( "hero_image" to AdaptyCustomImageAsset.remote( url = "https://example.com/image.jpg", preview = AdaptyCustomImageAsset.file( FileLocation.fromAsset("images/hero_image_preview.png"), ) ), "hero_video" to AdaptyCustomVideoAsset.file( FileLocation.fromResId(requireContext(), R.raw.custom_video), preview = AdaptyCustomImageAsset.file( FileLocation.fromResId(requireContext(), R.drawable.video_preview), ), ), ) val paywallView = AdaptyUI.getPaywallView( activity, viewConfiguration, products, eventListener, insets, customAssets, ) ``` :::note アセットが見つからない場合、ペイウォールはデフォルトの表示にフォールバックします。 ::: --- # File: android-present-paywalls --- --- title: "Android - 新しいペイウォールビルダーのペイウォールを表示する" description: "Androidで効果的なマネタイズのためのペイウォール表示方法を学びましょう。" --- ペイウォールビルダーを使ってペイウォールをカスタマイズした場合、ユーザーに表示するためのレンダリングコードをモバイルアプリに書く必要はありません。このようなペイウォールには、表示内容と表示方法の両方が含まれています。 :::warning このガイドは、SDK v3.0 が必要な**新しいペイウォールビルダーのペイウォール**専用です。ペイウォールの表示方法は、異なるバージョンのペイウォールビルダーで設計されたペイウォール、リモートコンフィグペイウォール、[Observer モード](observer-vs-full-mode)によって異なります。 - **リモートコンフィグペイウォール**の表示については、[リモートコンフィグで設計されたペイウォールのレンダリング](present-remote-config-paywalls)をご覧ください。 - **Observer モードペイウォール**の表示については、[Android - Observer モードでペイウォールビルダーのペイウォールを表示する](android-present-paywall-builder-paywalls-in-observer-mode)をご覧ください。 ::: 以下で使用する `viewConfiguration` オブジェクトの取得方法については、[ペイウォールビルダーのペイウォールと設定を取得する](android-get-pb-paywalls)をご覧ください。 デバイス画面にビジュアルペイウォールを表示するには、まず設定が必要です。`AdaptyUI.getPaywallView()` メソッドを呼び出すか、`AdaptyPaywallView` を直接作成してください: ```kotlin showLineNumbers val paywallView = AdaptyUI.getPaywallView( activity, viewConfiguration, products, eventListener, insets, personalizedOfferResolver, tagResolver, timerResolver, ) ``` ```kotlin showLineNumbers val paywallView = AdaptyPaywallView(activity) // or retrieve it from xml ... with(paywallView) { showPaywall( viewConfiguration, products, eventListener, insets, personalizedOfferResolver, tagResolver, timerResolver, ) } ``` ```java showLineNumbers AdaptyPaywallView paywallView = AdaptyUI.getPaywallView( activity, viewConfiguration, products, eventListener, insets, personalizedOfferResolver, tagResolver, timerResolver ); ``` ```java showLineNumbers AdaptyPaywallView paywallView = new AdaptyPaywallView(activity); //add to the view hierarchy if needed, or you receive it from xml ... paywallView.showPaywall(viewConfiguration, products, eventListener, insets, personalizedOfferResolver, tagResolver, timerResolver); ``` ```xml showLineNumbers ``` ビューが正常に作成されたら、ビュー階層に追加してデバイス画面に表示できます。 `AdaptyUI.getPaywallView()` を呼び出さずに `AdaptyPaywallView` を取得した場合は、`.showPaywall()` メソッドも呼び出す必要があります。 デバイス画面にビジュアルペイウォールを表示するには、まず設定が必要です。次のコンポーザブル関数を使用してください: ```kotlin showLineNumbers AdaptyPaywallScreen( viewConfiguration, products, eventListener, insets, personalizedOfferResolver, tagResolver, timerResolver, ) ``` リクエストパラメータ: | パラメータ | 必須/任意 | 説明 | | :---------------------------- | :------- |:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **viewConfiguration** | 必須 | ペイウォールのビジュアル詳細を含む `AdaptyUI.LocalizedViewConfiguration` オブジェクトを指定します。`Adapty.getViewConfiguration(paywall)` メソッドで読み込んでください。詳細は[ペイウォールのビジュアル設定を取得する](android-get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder)をご覧ください。 | | **products** | 任意 | 画面上のプロダクト表示タイミングを最適化するために `AdaptyPaywallProduct` の配列を指定します。`null` を渡すと、AdaptyUI が必要なプロダクトを自動的に取得します。 | | **eventListener** | 任意 | ペイウォールイベントを監視するために `AdaptyUiEventListener` を指定します。使いやすさのために `AdaptyUiDefaultEventListener` の拡張を推奨します。詳細は[ペイウォールイベントの処理](android-handling-events)をご覧ください。 | | **insets** | 任意 |

インセットは、システムバーの後ろにタップ可能な要素が隠れないようにするためのペイウォール周囲のスペースです。

デフォルト: `UNSPECIFIED`(Adapty がインセットを自動調整します。エッジ・ツー・エッジのペイウォールに適しています)

ペイウォールがエッジ・ツー・エッジでない場合は、カスタムインセットを設定することをお勧めします。設定方法は下記の[ペイウォールインセットの変更](#change-paywall-insets)セクションをご覧ください。

| | **personalizedOfferResolver** | 任意 | パーソナライズされた価格設定([詳細はこちら](https://developer.android.com/google/play/billing/integrate#personalized-price))を指定するには、`AdaptyUiPersonalizedOfferResolver` を実装し、`AdaptyPaywallProduct` が個人化された価格かどうかを true/false で返す独自のロジックを渡してください。 | | **tagResolver** | 任意 | ペイウォールテキスト内のカスタムタグを解決するために `AdaptyUiTagResolver` を使用します。このリゾルバーはタグパラメータを受け取り、対応する文字列に解決します。詳細はペイウォールビルダーのカスタムタグのトピックをご覧ください。 | | **timerResolver** | 任意 | カスタムタイマー機能を使用する場合は、ここにリゾルバーを渡してください。 | :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: ## ペイウォールインセットの変更 \{#change-paywall-insets\} インセットは、システムバーの後ろにタップ可能な要素が隠れないようにするためのペイウォール周囲のスペースです。デフォルトでは、Adapty がインセットを自動調整します。これはエッジ・ツー・エッジのペイウォールに適しています。 ペイウォールがエッジ・ツー・エッジでない場合は、カスタムインセットの設定をお勧めします: - ステータスバーとナビゲーションバーのどちらも `AdaptyPaywallView` と重なっていない場合は `AdaptyPaywallInsets.NONE` を使用してください。 - ペイウォールが上部のステータスバーとは重なっているが下部とは重なっていない場合など、より詳細な設定が必要な場合は、以下の例のように `bottomInset` のみを `0` に設定できます: ```kotlin showLineNumbers //create extension function fun View.onReceiveSystemBarsInsets(action: (insets: Insets) -> Unit) { ViewCompat.setOnApplyWindowInsetsListener(this) { _, insets -> val systemBarInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars()) ViewCompat.setOnApplyWindowInsetsListener(this, null) action(systemBarInsets) insets } } //and then use it with the view paywallView.onReceiveSystemBarsInsets { insets -> val paywallInsets = AdaptyPaywallInsets.vertical(insets.top, 0) paywallView.showPaywall( viewConfiguration, products, eventListener, paywallInsets, personalizedOfferResolver, tagResolver, timerResolver, ) } ``` ```java showLineNumbers ... ViewCompat.setOnApplyWindowInsetsListener(paywallView, (view, insets) -> { Insets systemBarInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars()); ViewCompat.setOnApplyWindowInsetsListener(paywallView, null); AdaptyPaywallInsets paywallInsets = AdaptyPaywallInsets.of(systemBarInsets.top, 0); paywallView.showPaywall(paywall, products, viewConfiguration, paywallInsets, productTitleResolver); return insets; }); ``` ## 開発者定義タイマーの使用 \{#use-developer-defined-timer\} モバイルアプリで開発者定義タイマーを使用するには、カスタムタイマーとペイウォールのレンダリング時に置き換えられる文字列値をペアにしたディクショナリまたはマップである `timerResolver` オブジェクトを作成します。以下に例を示します: ```kotlin showLineNumbers ... val customTimers = mapOf( "CUSTOM_TIMER_NY" to Calendar.getInstance(TimeZone.getDefault()).apply { set(2025, 0, 1) }.time, // New Year 2025 ) val timerResolver = AdaptyUiTimerResolver { timerId -> customTimers.getOrElse(timerId, { Date(System.currentTimeMillis() + 3600 * 1000L) /* in 1 hour */ } ) } ``` ```java showLineNumbers ... Map customTimers = new HashMap<>(); customTimers.put( "CUSTOM_TIMER_NY", new Calendar.Builder().setTimeZone(TimeZone.getDefault()).setDate(2025, 0, 1).build().getTime() ); AdaptyUiTimerResolver timerResolver = new AdaptyUiTimerResolver() { @NonNull @Override public Date timerEndAtDate(@NonNull String timerId) { Date date = customTimers.get(timerId); return date != null ? date : new Date(System.currentTimeMillis() + 3600 * 1000L); /* in 1 hour */ } }; ``` この例では、`CUSTOM_TIMER_NY` は Adapty ダッシュボードで設定した開発者定義タイマーの **Timer ID** です。`timerResolver` により、アプリはタイマーの終了時刻(元日など)から現在時刻を引いて計算した `13d 09h 03m 34s` のような正確な値でタイマーを動的に更新します。 ## カスタムタグの使用 \{#use-custom-tags\} モバイルアプリでカスタムタグを使用するには、カスタムタグとペイウォールのレンダリング時に置き換えられる文字列値をペアにしたディクショナリまたはマップである `tagResolver` オブジェクトを作成します。以下に例を示します: ```kotlin showLineNumbers val customTags = mapOf("USERNAME" to "John") val tagResolver = AdaptyUiTagResolver { tag -> customTags[tag] } ``` ```java showLineNumbers Map customTags = new HashMap<>(); customTags.put("USERNAME", "John"); AdaptyUiTagResolver tagResolver = customTags::get; ``` この例では、`USERNAME` は Adapty ダッシュボードで `` として入力したカスタムタグです。`tagResolver` により、アプリはこのカスタムタグを `John` のような指定された値に動的に置き換えます。 `tagResolver` はペイウォールを表示する直前に作成・設定することをお勧めします。準備ができたら、ペイウォール表示に使用する AdaptyUI メソッドに渡してください。 ## ペイウォールのローディングインジケーターの色を変更する \{#change-paywall-loading-indicator-color\} ローディングインジケーターのデフォルトカラーは、次の方法でオーバーライドできます: ```xml showLineNumbers title = "XML" ``` --- # File: android-handle-paywall-actions --- --- title: "Android SDKでボタンアクションに対応する" description: "AdaptyのAndroidでペイウォールのボタンアクションを処理し、アプリの収益化を改善する方法。" --- Adaptyのペイウォールビルダーを使ってペイウォールを構築する場合、ボタンを適切に設定することが重要です。 1. [ペイウォールビルダーにボタンを追加](paywall-buttons)し、既存のアクションを割り当てるか、カスタムアクションIDを作成します。 2. 割り当てた各アクションを処理するコードをアプリに記述します。 このガイドでは、コード内でカスタムアクションおよび既存アクションを処理する方法を説明します。 :::warning **購入、復元、ペイウォールのクローズ、URLの開封のみが自動的に処理されます。** それ以外のボタンアクションはすべて、アプリコード内で適切なレスポンスの実装が必要です。 ::: ## ペイウォールを閉じる \{#close-paywalls\} ペイウォールを閉じるボタンを追加するには: 1. ペイウォールビルダーでボタンを追加し、**Close** アクションを割り当てます。 2. アプリコードで、ペイウォールを閉じる `close` アクションのハンドラーを実装します。 :::info Android SDKでは、`close` アクションはデフォルトでペイウォールを閉じる動作をします。ただし、必要に応じてコードでこの動作を上書きすることもできます。たとえば、1つのペイウォールを閉じると別のペイウォールが開くようにする場合などです。 ::: ```kotlin override fun onActionPerformed(action: AdaptyUI.Action, context: Context) { when (action) { AdaptyUI.Action.Close -> (context as? Activity)?.onBackPressed() // default behavior } } ``` ## ペイウォールからURLを開く \{#open-urls-from-paywalls\} :::tip リンクのグループ(利用規約や購入の復元など)を追加したい場合は、ペイウォールビルダーで **Link** 要素を追加し、**Open URL** アクションが割り当てられたボタンと同じ方法で処理します。 ::: ペイウォールからリンクを開くボタンを追加するには(**Terms of use** や **Privacy policy** など): 1. ペイウォールビルダーでボタンを追加し、**Open URL** アクションを割り当て、開きたいURLを入力します。 2. アプリコードで、受け取ったURLをブラウザで開く `openUrl` アクションのハンドラーを実装します。 :::info Android SDKでは、`openUrl` アクションはデフォルトでURLを開く動作をします。ただし、必要に応じてコードでこの動作を上書きすることもできます。 ::: ```kotlin override fun onActionPerformed(action: AdaptyUI.Action, context: Context) { when (action) { is AdaptyUI.Action.OpenUrl -> { val intent = Intent(Intent.ACTION_VIEW, Uri.parse(action.url)) // default behavior context.startActivity(intent) } } } ``` ## アプリへのログイン \{#log-into-the-app\} ユーザーをアプリにログインさせるボタンを追加するには: 1. ペイウォールビルダーでボタンを追加し、**Login** アクションを割り当てます。 2. アプリコードで、ユーザーを識別する `login` アクションのハンドラーを実装します。 ```kotlin override fun onActionPerformed(action: AdaptyUI.Action, context: Context) { when (action) { AdaptyUI.Action.Login -> { val intent = Intent(context, LoginActivity::class.java) context.startActivity(intent) } } } ``` ## カスタムアクションの処理 \{#handle-custom-actions\} その他のアクションを処理するボタンを追加するには: 1. ペイウォールビルダーでボタンを追加し、**Custom** アクションを割り当て、IDを設定します。 2. アプリコードで、作成したアクションIDのハンドラーを実装します。 たとえば、別のサブスクリプションオファーや買い切り購入のセットがある場合、別のペイウォールを表示するボタンを追加できます。 ```kotlin override fun onActionPerformed(action: AdaptyUI.Action, context: Context) { when (action) { is AdaptyUI.Action.Custom -> { if (action.customId == "openNewPaywall") { // Display another paywall } } } } ``` --- # File: android-handling-events --- --- title: "Android - ペイウォールイベントの処理" description: "AdaptyのイベントトラッキングツールでAndroidのサブスクリプションイベントを効率的に処理しましょう。" --- :::important このガイドでは、購入・復元・プロダクト選択・ペイウォールレンダリングに関するイベント処理について説明します。ボタン操作(ペイウォールのクローズ、リンクを開くなど)も別途実装が必要です。詳しくは[ボタンアクションの処理ガイド](android-handle-paywall-actions)を参照してください。 ::: [ペイウォールビルダー](adapty-paywall-builder)で設定したペイウォールは、購入や復元のために追加のコードは不要です。ただし、アプリが対応できるいくつかのイベントが発生します。これらのイベントには、ボタン操作(閉じるボタン、URL、プロダクト選択など)や、ペイウォール上の購入関連アクションの通知が含まれます。以下でこれらのイベントへの対応方法を確認してください。 :::warning このガイドは、Adapty SDK v3.0以降が必要な**新しいペイウォールビルダーのペイウォール**専用です。 ::: :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: 購入画面で発生する処理を制御・監視したい場合は、`AdaptyUiEventListener` のメソッドを実装してください。 一部のケースでデフォルトの動作を維持したい場合は、`AdaptyUiDefaultEventListener` を継承して、変更したいメソッドだけをオーバーライドできます。 以下は `AdaptyUiDefaultEventListener` のデフォルト実装です。 ### ユーザー起因のイベント \{#user-generated-events\} #### プロダクト選択 \{#product-selection\} プロダクトが購入のために選択された場合(ユーザーまたはシステムによる)、このメソッドが呼び出されます: ```kotlin showLineNumbers title="Kotlin" public override fun onProductSelected( product: AdaptyPaywallProduct, context: Context, ) {} ```
イベント例(クリックして展開) ```javascript { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" } } ```
#### 購入開始 \{#started-purchase\} ユーザーが購入プロセスを開始すると、このメソッドが呼び出されます: ```kotlin showLineNumbers title="Kotlin" public override fun onPurchaseStarted( product: AdaptyPaywallProduct, context: Context, ) {} ```
イベント例(クリックして展開) ```javascript { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" } } ```
このメソッドはObserverモードでは呼び出されません。詳しくは[Android - ObserverモードでのペイウォールビルダーペイウォールのPresent](android-present-paywall-builder-paywalls-in-observer-mode)を参照してください。 #### 購入成功・キャンセル・保留 \{#successful-canceled-or-pending-purchase\} 購入が成功すると、このメソッドが呼び出されます: ```kotlin showLineNumbers title="Kotlin" public override fun onPurchaseFinished( purchaseResult: AdaptyPurchaseResult, product: AdaptyPaywallProduct, context: Context, ) { if (purchaseResult !is AdaptyPurchaseResult.UserCanceled) context.getActivityOrNull()?.onBackPressed() } ```
イベント例(クリックして展開) ```javascript // Successful purchase { "purchaseResult": { "type": "Success", "profile": { "accessLevels": { "premium": { "id": "premium", "isActive": true, "expiresAt": "2024-02-15T10:30:00Z" } } } }, "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" } } // Cancelled purchase { "purchaseResult": { "type": "UserCanceled" }, "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" } } // Pending purchase { "purchaseResult": { "type": "Pending" }, "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" } } ```
この場合は画面を閉じることをお勧めします。 このメソッドはObserverモードでは呼び出されません。詳しくは[Android - ObserverモードでのペイウォールビルダーペイウォールのPresent](android-present-paywall-builder-paywalls-in-observer-mode)を参照してください。 #### 購入失敗 \{#failed-purchase\} エラーにより購入が失敗した場合、このメソッドが呼び出されます。対象はGoogle Play Billing のエラー(支払い制限、無効なプロダクト、ネットワーク障害)、トランザクション検証失敗、システムエラーです。なお、ユーザーによるキャンセルはこのメソッドではなく `onPurchaseFinished` がキャンセル結果付きで呼び出され、保留中の支払いもこのメソッドは呼び出されません。 ```kotlin showLineNumbers title="Kotlin" public override fun onPurchaseFailure( error: AdaptyError, product: AdaptyPaywallProduct, context: Context, ) {} ```
イベント例(クリックして展開) ```javascript { "error": { "code": "purchase_failed", "message": "Purchase failed due to insufficient funds", "details": { "underlyingError": "Insufficient funds in account" } }, "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" } } ```
このメソッドはObserverモードでは呼び出されません。詳しくは[Android - ObserverモードでのペイウォールビルダーペイウォールのPresent](android-present-paywall-builder-paywalls-in-observer-mode)を参照してください。 #### Webペイメントナビゲーション完了 \{#finished-web-payment-navigation\} 特定のプロダクトに対して[Webペイウォール](web-paywall)を開こうとした後にこのメソッドが呼び出されます。ナビゲーションの成功・失敗どちらの場合も対象です: ```kotlin showLineNumbers title="Kotlin" public override fun onFinishWebPaymentNavigation( product: AdaptyPaywallProduct?, error: AdaptyError?, context: Context, ) {} ``` **パラメーター:** | パラメーター | 説明 | |:------------|:-----| | **product** | Webペイウォールが開かれた `AdaptyPaywallProduct`。`null` の場合があります。 | | **error** | Webペイウォールのナビゲーションが失敗した場合の `AdaptyError` オブジェクト。成功した場合は `null`。 |
イベント例(クリックして展開) ```javascript // Successful navigation { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "error": null } // Failed navigation { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "error": { "code": "web_navigation_failed", "message": "Failed to open web paywall", "details": { "underlyingError": "Browser unavailable" } } } ```
#### 購入復元成功 \{#successful-restore\} 購入の復元が成功すると、このメソッドが呼び出されます: ```kotlin showLineNumbers title="Kotlin" public override fun onRestoreSuccess( profile: AdaptyProfile, context: Context, ) {} ```
イベント例(クリックして展開) ```javascript { "profile": { "accessLevels": { "premium": { "id": "premium", "isActive": true, "expiresAt": "2024-02-15T10:30:00Z" } }, "subscriptions": [ { "vendorProductId": "premium_monthly", "isActive": true, "expiresAt": "2024-02-15T10:30:00Z" } ] } } ```
ユーザーが必要な `accessLevel` を持っている場合は、画面を閉じることをお勧めします。確認方法については[サブスクリプションのステータス](android-listen-subscription-changes)を参照してください。 #### 購入復元失敗 \{#failed-restore\} `Adapty.restorePurchases()` が失敗した場合、このメソッドが呼び出されます: ```kotlin showLineNumbers title="Kotlin" public override fun onRestoreFailure( error: AdaptyError, context: Context, ) {} ```
イベント例(クリックして展開) ```javascript { "error": { "code": "restore_failed", "message": "Purchase restoration failed", "details": { "underlyingError": "No previous purchases found" } } } ```
#### サブスクリプションのアップグレード \{#upgrade-subscription\} ユーザーが別のサブスクリプションがアクティブな状態で新しいサブスクリプションを購入しようとした場合、このメソッドをオーバーライドして新しい購入の処理方法を制御できます。2つの選択肢があります: 1. **現在のサブスクリプションを新しいものに置き換える**: ```kotlin showLineNumbers title="Kotlin" public override fun onAwaitingPurchaseParams( product: AdaptyPaywallProduct, context: Context, onPurchaseParamsReceived: AdaptyUiEventListener.PurchaseParamsCallback, ): AdaptyUiEventListener.PurchaseParamsCallback.IveBeenInvoked { onPurchaseParamsReceived( AdaptyPurchaseParameters.Builder() .withSubscriptionUpdateParams(AdaptySubscriptionUpdateParameters(...)) .build() ) return AdaptyUiEventListener.PurchaseParamsCallback.IveBeenInvoked } ``` 2. **両方のサブスクリプションを維持する**(新しいものを別途追加する): ```kotlin showLineNumbers title="Kotlin" public override fun onAwaitingPurchaseParams( product: AdaptyPaywallProduct, context: Context, onPurchaseParamsReceived: AdaptyUiEventListener.PurchaseParamsCallback, ): AdaptyUiEventListener.PurchaseParamsCallback.IveBeenInvoked { onPurchaseParamsReceived(AdaptyPurchaseParameters.Empty) return AdaptyUiEventListener.PurchaseParamsCallback.IveBeenInvoked } ``` :::note このメソッドをオーバーライドしない場合、デフォルトの動作は両方のサブスクリプションをアクティブに維持します(`AdaptyPurchaseParameters.Empty` を使用した場合と同等です)。 ::: 必要に応じて追加の購入パラメーターを設定することもできます: ```kotlin AdaptyPurchaseParameters.Builder() .withSubscriptionUpdateParams(AdaptySubscriptionUpdateParameters(...)) // 任意 - 現在のサブスクリプションを置き換える場合 .withOfferPersonalized(true) // 任意 - パーソナライズされた価格設定を使用する場合 .build() ``` 別のサブスクリプションがアクティブな状態で新しいサブスクリプションが購入された場合、このメソッドをオーバーライドして現在のサブスクリプションを新しいものに置き換えます。アクティブなサブスクリプションをそのままにして新しいものを別途追加する場合は、`onSubscriptionUpdateParamsReceived(null)` を呼び出してください: ```kotlin showLineNumbers title="Kotlin" public override fun onAwaitingSubscriptionUpdateParams( product: AdaptyPaywallProduct, context: Context, onSubscriptionUpdateParamsReceived: SubscriptionUpdateParamsCallback, ) { onSubscriptionUpdateParamsReceived(AdaptySubscriptionUpdateParameters(...)) } ```
イベント例(クリックして展開) ```javascript { "product": { "vendorProductId": "premium_yearly", "localizedTitle": "Premium Yearly", "localizedDescription": "Premium subscription for 1 year", "localizedPrice": "$99.99", "price": 99.99, "currencyCode": "USD" }, "subscriptionUpdateParams": { "replacementMode": "with_time_proration" } } ```
### データ取得とレンダリング \{#data-fetching-and-rendering\} #### プロダクト読み込みエラー \{#product-loading-errors\} 初期化時にプロダクトを渡さない場合、AdaptyUI はサーバーから必要なオブジェクトを自動的に取得します。この操作が失敗した場合、AdaptyUI はこのメソッドを呼び出してエラーを通知します: ```kotlin showLineNumbers title="Kotlin" public override fun onLoadingProductsFailure( error: AdaptyError, context: Context, ): Boolean = false ```
イベント例(クリックして展開) ```javascript { "error": { "code": "products_loading_failed", "message": "Failed to load products from the server", "details": { "underlyingError": "Network timeout" } } } ```
`true` を返すと、AdaptyUI は2秒後にリクエストを再試行します。 #### レンダリングエラー \{#rendering-errors\} インターフェースのレンダリング中にエラーが発生した場合、このメソッドを呼び出して報告されます: ```kotlin showLineNumbers title="Kotlin" public override fun onRenderingError( error: AdaptyError, context: Context, ) {} ```
イベント例(クリックして展開) ```javascript { "error": { "code": "rendering_failed", "message": "Failed to render paywall interface", "details": { "underlyingError": "Invalid paywall configuration" } } } ```
通常の状況ではこのようなエラーは発生しないため、遭遇した場合はお知らせください。 --- # File: android-use-fallback-paywalls --- --- title: "Android - フォールバックペイウォールを使用する" description: "ユーザーがオフラインのとき、またはAdaptyサーバーが利用できないときのケースを処理します。" --- :::warning フォールバックペイウォールは Android SDK v2.11 以降でサポートされています。 ::: スムーズなユーザー体験を維持するために、フロー、[ペイウォール](paywalls)、[オンボーディング](onboardings)に[フォールバック](/fallback-paywalls)を設定することが重要です。この対策により、インターネット接続が部分的または完全に失われた場合でも、アプリケーションの機能を維持できます。 * **アプリケーションが Adapty サーバーにアクセスできない場合:** フォールバックのフローまたはペイウォールを表示し、ローカルのオンボーディング設定にアクセスできます。 * **アプリケーションがインターネットにアクセスできない場合:** フォールバックのフローまたはペイウォールを表示できます。オンボーディングはリモートコンテンツを含むため、動作にはインターネット接続が必要です。 :::important このガイドの手順を進める前に、Adapty からフォールバック設定ファイルを[ダウンロード](/local-fallback-paywalls)してください。 ::: ## 設定 \{#configuration\} 1. フォールバック設定ファイルをAndroidプロジェクトの `assets` または `res/raw` ディレクトリに移動します。 2. 対象のペイウォールまたはオンボーディングを取得する**前に** `.setFallback` メソッドを呼び出します。 ```kotlin showLineNumbers //if you put the 'android_fallback.json' file to the 'assets' directory val location = FileLocation.fromAsset("android_fallback.json") //or `FileLocation.fromAsset("/android_fallback.json")` if you placed it in a child folder of 'assets') //if you put the 'android_fallback.json' file to the 'res/raw' directory val location = FileLocation.fromResId(context, R.raw.android_fallback) //you can also pass a file URI val fileUri: Uri = //get Uri for the file with fallback paywalls val location = FileLocation.fromFileUri(fileUri) //pass the file location Adapty.setFallback(location, callback) ``` ```java showLineNumbers //if you put the 'android_fallback.json' file to the 'assets' directory FileLocation location = FileLocation.fromAsset("android_fallback.json"); //or `FileLocation.fromAsset("/android_fallback.json");` if you placed it in a child folder of 'assets') //if you put the 'android_fallback.json' file to the 'res/raw' directory FileLocation location = FileLocation.fromResId(context, R.raw.android_fallback); //you can also pass a file URI Uri fileUri = //get Uri for the file with fallback paywalls FileLocation location = FileLocation.fromFileUri(fileUri); //pass the file location Adapty.setFallback(location, callback); ``` パラメーター: | パラメーター | 説明 | | :----------- | :----------------------------------------------------------- | | **location** | フォールバック設定ファイルの [FileLocation](https://android.adapty.io/adapty/com.adapty.utils/-file-location/-companion/) オブジェクト | --- # File: android-localizations-and-locale-codes --- --- title: "Android SDKでローカライゼーションとロケールコードを使用する" description: "アプリのローカライゼーションとロケールコードを管理して、グローバルなユーザーにリーチしましょう(Android)。" --- ## なぜこれが重要なのか \{#why-this-is-important\} ロケールコードが関係するシナリオはいくつかあります。たとえば、アプリの現在のローカライゼーションに対応する正しいペイウォールを取得しようとする場合などです。 ロケールコードは複雑で、プラットフォームによって異なる場合があるため、Adapty ではサポートするすべてのプラットフォームに対して内部標準を採用しています。ただし、これらのコードが複雑であることから、サーバーに送信している内容と、その後の処理を正確に把握しておくことが非常に重要です。そうすることで、常に期待通りの結果を受け取れます。 ## Adapty のロケールコード標準 \{#locale-code-standard-at-adapty\} ロケールコードには、Adapty は若干修正した [BCP 47 標準](https://en.wikipedia.org/wiki/IETF_language_tag) を使用しています。各コードは小文字のサブタグで構成され、ハイフンで区切られます。例:`en`(英語)、`pt-br`(ポルトガル語(ブラジル))、`zh`(簡体字中国語)、`zh-hant`(繁体字中国語)。 ## ロケールコードのマッチング \{#locale-code-matching\} Adapty がクライアント側の SDK からロケールコードを含む呼び出しを受け取り、対応するペイウォールのローカライゼーションを探す際、以下の処理が行われます: 1. 受け取ったロケール文字列が小文字に変換され、アンダースコア(`_`)がすべてハイフン(`-`)に置き換えられます 2. 完全に一致するロケールコードを持つローカライゼーションを検索します 3. 一致するものが見つからない場合、最初のハイフンより前の部分文字列(`pt-br` の場合は `pt`)を取り出し、一致するローカライゼーションを検索します 4. それでも一致するものが見つからない場合、デフォルトの `en` ローカライゼーションを返します これにより、`'pt_BR'` を送信した iOS デバイス、`pt-BR` を送信した Android デバイス、`pt-br` を送信した別のデバイスはすべて同じ結果を受け取ります。 ## ローカライゼーションの実装:推奨方法 \{#implementing-localizations-recommended-way\} ローカライゼーションについて検討している場合、すでにプロジェクト内でローカライズされた文字列ファイルを扱っている可能性が高いです。その場合、各ローカライゼーションに対応するファイルに、意図した Adapty のロケールコードをキーと値のペアで設定しておくことをお勧めします。そして、SDK を呼び出す際にそのキーの値を取得します: ```kotlin showLineNumbers // 1. Modify your strings.xml files /* strings.xml - Spanish */ es /* strings.xml - Portuguese (Brazil) */ pt-br // 2. Extract and use the locale code val localeCode = context.getString(R.string.adapty_paywalls_locale) // pass locale code to AdaptyUI.getViewConfiguration or Adapty.getPaywall method ``` この方法により、アプリのすべてのユーザーに対してどのローカライゼーションが取得されるかを完全にコントロールできます。 ## ローカライゼーションの実装:別の方法 \{#implementing-localizations-the-other-way\} すべてのローカライゼーションに対してロケールコードを明示的に定義しなくても、似た結果(ただし完全に同一ではありません)を得ることができます。それは、プラットフォームが提供する他のオブジェクトからロケールコードを抽出する方法です: ```kotlin showLineNumbers val locale = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) context.resources.configuration.locales[0] else context.resources.configuration.locale val localeCode = locale.toLanguageTag() // pass locale code to AdaptyUI.getViewConfiguration or Adapty.getPaywall method ``` この方法は、Adapty のサーバーが受け取る内容を正確に予測することが難しいため、推奨していません。 それでもこの方法を使用する場合は、関連するすべてのユースケースに対応していることを確認してください。 --- # File: android-web-paywall --- --- title: "Android SDKでウェブペイウォールを実装する" description: "ウェブペイウォールを設定して、Playストアの手数料や審査なしで収益を得ましょう。" --- :::important 始める前に、[ダッシュボードでウェブペイウォールを設定](web-paywall)し、Adapty SDK バージョン 3.15 以降をインストールしていることを確認してください。 ::: ## ウェブペイウォールを開く \{#open-web-paywalls\} 自分で開発したペイウォールを使用している場合は、SDKメソッドを使ってウェブペイウォールを処理する必要があります。`.openWebPaywall` メソッドは以下を行います: 1. 固有のURLを生成し、特定のユーザーに表示されたペイウォールと、そのユーザーがリダイレクトされるウェブページをAdaptyが紐付けられるようにします。 2. ユーザーがアプリに戻るタイミングを追跡し、プロファイルのアクセス権が更新されたかどうかを確認するために、短い間隔で`.getProfile`をリクエストします。 これにより、支払いが成功してアクセス権が更新された場合、サブスクリプションはほぼ即座にアプリ内で有効になります。 :::note ユーザーがアプリに戻った後、プロファイルの更新を反映するためにUIを更新してください。AdaptyはプロファイルのUpdateイベントを受信して処理します。 ::: ```kotlin showLineNumbers Adapty.openWebPaywall( activity = activity, product = product, ) { error -> if (error == null) { // the web paywall was opened successfully } else { // handle the error } } ``` :::note `openWebPaywall` メソッドには2つのバージョンがあります: 1. `openWebPaywall(product)` — ペイウォールに基づいてURLを生成し、プロダクトデータもURLに追加します。 2. `openWebPaywall(paywall)` — ペイウォールに基づいてURLを生成しますが、プロダクトデータはURLに追加しません。Adaptyペイウォール内のプロダクトとウェブペイウォールのプロダクトが異なる場合に使用してください。 ::: ## アプリ内ブラウザでウェブペイウォールを開く \{#open-web-paywalls-in-an-in-app-browser\} デフォルトでは、ウェブペイウォールは外部ブラウザで開きます。 シームレスなユーザー体験を提供するために、アプリ内ブラウザでウェブペイウォールを開くことができます。これにより、アプリを切り替えることなく、アプリケーション内でウェブ購入ページを表示してトランザクションを完了できます。 これを有効にするには、`presentation` パラメータを `AdaptyWebPresentation.InAppBrowser` に設定します: ```kotlin showLineNumbers Adapty.openWebPaywall( activity = activity, product = product, presentation = AdaptyWebPresentation.InAppBrowser, ) { error -> if (error == null) { // the web paywall was opened successfully } else { // handle the error val adaptyError = error } } ``` --- # File: android-troubleshoot-paywall-builder --- --- title: "Android SDKでのペイウォールビルダーのトラブルシューティング" description: "Android SDKでのペイウォールビルダーのトラブルシューティング" --- このガイドでは、Android SDKでAdapty ペイウォールビルダーを使用して作成したペイウォールに関する一般的な問題の解決方法を説明します。 ## ペイウォール設定の取得に失敗する \{#getting-a-paywall-configuration-fails\} **問題**: `getViewConfiguration` メソッドがペイウォール設定の取得に失敗する。 **原因**: ペイウォールビルダーで、デバイスへの表示が有効になっていない。 **解決策**: ペイウォールビルダーの **Show on device** トグルを有効にしてください。 ## ペイウォールのビュー数が多すぎる \{#the-paywall-view-number-is-too-big\} **問題**: ペイウォールのビュー数が想定の2倍になっている。 **原因**: コード内で `logShowPaywall` を呼び出している可能性があります。ペイウォールビルダーを使用している場合、このメソッドを呼び出すとビュー数が重複して記録されます。ペイウォールビルダーで作成したペイウォールでは、アナリティクスが自動的に計測されるため、このメソッドを使用する必要はありません。 **解決策**: ペイウォールビルダーを使用している場合は、コード内で `logShowPaywall` を呼び出していないことを確認してください。 ## その他の問題 \{#other-issues\} **問題**: 上記以外のペイウォールビルダーに関連する問題が発生している。 **解決策**: 必要に応じて、[移行ガイド](android-sdk-migration-guides)を使用してSDKを最新バージョンに移行してください。多くの問題は新しいSDKバージョンで解決されています。 --- # File: android-quickstart-manual --- --- title: "Android SDKのカスタムペイウォールで購入機能を有効にする" description: "Adapty SDKをAndroidのカスタムペイウォールに統合してアプリ内課金を有効にします。" --- このガイドでは、Adaptyをカスタムペイウォールに統合する方法を説明します。ペイウォールの実装を完全にコントロールしながら、Adapty SDKがプロダクトの取得、新規購入の処理、過去の購入の復元を担当します。 :::important **このガイドはカスタムペイウォールを実装する開発者向けです。** 購入機能を最も簡単に有効にしたい場合は、[Adapty ペイウォールビルダー](android-quickstart-paywalls)をご利用ください。ペイウォールビルダーを使えば、ノーコードのビジュアルエディタでペイウォールを作成でき、すべての購入ロジックはAdaptyが自動的に処理します。アプリを再公開することなくデザインのテストも可能です。 ::: ## 始める前に \{#before-you-start\} ### プロダクトのセットアップ \{#set-up-products\} アプリ内課金を有効にするには、3つの重要な概念を理解する必要があります。 - [**プロダクト**](product) – ユーザーが購入できるもの(サブスクリプション、消耗型アイテム、永続アクセス) - [**ペイウォール**](paywalls) – どのプロダクトを提供するかを定義する設定。Adaptyでは、ペイウォールがプロダクトを取得する唯一の手段ですが、この設計によりアプリのコードを変更することなくプロダクト・価格・オファーを変更できます。 - [**プレースメント**](placements) – アプリのどこでどのタイミングでペイウォールを表示するか(`main`、`onboarding`、`settings`など)。ダッシュボードでプレースメントにペイウォールを設定し、コード内ではプレースメントIDで取得します。これにより、A/Bテストの実施や、ユーザーごとに異なるペイウォールの表示が簡単に行えます。 カスタムペイウォールを使用する場合でも、これらの概念を理解しておいてください。基本的には、アプリで販売するプロダクトを管理するための仕組みです。 カスタムペイウォールを実装するには、**ペイウォール**を作成して**プレースメント**に追加する必要があります。この設定によってプロダクトを取得できるようになります。ダッシュボードで必要な作業を理解するために、[こちら](quickstart)のクイックスタートガイドをご参照ください。 ### ユーザーの管理 \{#manage-users\} バックエンド認証の有無にかかわらず利用できます。 ただし、Adapty SDKは匿名ユーザーと識別済みユーザーを異なる方法で処理します。詳細を理解し、ユーザーを適切に扱うために、[識別クイックスタートガイド](android-quickstart-identify)をお読みください。 ## ステップ1. プロダクトを取得する \{#step-1-get-products\} カスタムペイウォール用のプロダクトを取得するには、次の手順が必要です。 1. `getPaywall`メソッドに[プレースメント](placements)IDを渡して`paywall`オブジェクトを取得する。 2. `getPaywallProducts`メソッドを使用して、このペイウォールのプロダクト配列を取得する。 ```kotlin showLineNumbers fun loadPaywall() { Adapty.getPaywall("YOUR_PLACEMENT_ID") { result -> when (result) { is AdaptyResult.Success -> { val paywall = result.value Adapty.getPaywallProducts(paywall) { productResult -> when (productResult) { is AdaptyResult.Success -> { val products = productResult.value // Use products to build your custom paywall UI } is AdaptyResult.Error -> { val error = productResult.error // Handle the error } } } } is AdaptyResult.Error -> { val error = result.error // Handle the error } } } } ``` ```java showLineNumbers public void loadPaywall() { Adapty.getPaywall("YOUR_PLACEMENT_ID", result -> { if (result instanceof AdaptyResult.Success) { AdaptyPaywall paywall = ((AdaptyResult.Success) result).getValue(); Adapty.getPaywallProducts(paywall, productResult -> { if (productResult instanceof AdaptyResult.Success) { List products = ((AdaptyResult.Success>) productResult).getValue(); // Use products to build your custom paywall UI } else if (productResult instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) productResult).getError(); // Handle the error } }); } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // Handle the error } }); } ``` ## ステップ2. 購入を受け付ける \{#step-2-accept-purchases\} カスタムペイウォールでユーザーがプロダクトをタップしたら、選択されたプロダクトを引数として`makePurchase`メソッドを呼び出します。これにより購入フローが処理され、更新されたプロファイルが返されます。 ```kotlin showLineNumbers fun purchaseProduct(activity: Activity, product: AdaptyPaywallProduct) { Adapty.makePurchase(activity, product) { result -> when (result) { is AdaptyResult.Success -> { when (val purchaseResult = result.value) { is AdaptyPurchaseResult.Success -> { val profile = purchaseResult.profile // Purchase successful, profile updated } is AdaptyPurchaseResult.UserCanceled -> { // User canceled the purchase } is AdaptyPurchaseResult.Pending -> { // Purchase is pending (e.g., user will pay offline with cash) } } } is AdaptyResult.Error -> { val error = result.error // Handle the error } } } } ``` ```java showLineNumbers public void purchaseProduct(Activity activity, AdaptyPaywallProduct product) { Adapty.makePurchase(activity, product, null, result -> { if (result instanceof AdaptyResult.Success) { AdaptyPurchaseResult purchaseResult = ((AdaptyResult.Success) result).getValue(); if (purchaseResult instanceof AdaptyPurchaseResult.Success) { AdaptyProfile profile = ((AdaptyPurchaseResult.Success) purchaseResult).getProfile(); // Purchase successful, profile updated } else if (purchaseResult instanceof AdaptyPurchaseResult.UserCanceled) { // User canceled the purchase } else if (purchaseResult instanceof AdaptyPurchaseResult.Pending) { // Purchase is pending (e.g., user will pay offline with cash) } } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // Handle the error } }); } ``` ## ステップ3. 購入を復元する \{#step-3-restore-purchases\} Google Playをはじめとするアプリストアでは、サブスクリプションを提供するすべてのアプリに対して、ユーザーが購入を復元できる手段を提供することを義務付けています。 ユーザーが復元ボタンをタップしたら`restorePurchases`メソッドを呼び出してください。これにより購入履歴がAdaptyと同期され、更新されたプロファイルが返されます。 ```kotlin showLineNumbers fun restorePurchases() { Adapty.restorePurchases { result -> when (result) { is AdaptyResult.Success -> { val profile = result.value // Restore successful, profile updated } is AdaptyResult.Error -> { val error = result.error // Handle the error } } } } ``` ```java showLineNumbers public void restorePurchases() { Adapty.restorePurchases(result -> { if (result instanceof AdaptyResult.Success) { AdaptyProfile profile = ((AdaptyResult.Success) result).getValue(); // Restore successful, profile updated } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // Handle the error } }); } ``` ## 次のステップ \{#next-steps\} --- no_index: true --- import Callout from '../../../components/Callout.astro'; ご質問やお困りのことがあれば、[サポートフォーラム](https://adapty.featurebase.app/)をご覧ください。よくある質問への回答を見つけたり、ご自身の質問を投稿することができます。チームとコミュニティがサポートいたします! ペイウォールをアプリに表示する準備が整いました。[Google Play Storeでの購入テスト](testing-on-android)を行い、ペイウォールからテスト購入が完了できることを確認してください。本番対応の実装例については、サンプルアプリの[ProductListFragment.kt](https://github.com/adaptyteam/AdaptySDK-Android/blob/master/app/src/main/java/com/adapty/example/ProductListFragment.kt)をご覧ください。適切なエラーハンドリング、UIフィードバック、サブスクリプション管理を含む購入処理のデモが確認できます。 次に、[ユーザーが購入を完了したかどうかを確認](android-check-subscription-status)し、ペイウォールを表示するか有料機能へのアクセスを許可するかを判断してください。 --- # File: fetch-paywalls-and-products-android --- --- title: "Android SDKでリモートコンフィグペイウォールのペイウォールとプロダクトを取得する" description: "Adapty Android SDKでペイウォールとプロダクトを取得して、ユーザーの収益化を強化します。" --- リモートコンフィグおよびカスタムペイウォールを表示する前に、それらに関する情報を取得する必要があります。このトピックはリモートコンフィグおよびカスタムペイウォールに関するものです。ペイウォールビルダーでカスタマイズされたペイウォールの取得方法については、[ペイウォールビルダーのペイウォールと設定の取得](android-get-pb-paywalls)を参照してください。 :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 :::
モバイルアプリでペイウォールとプロダクトの取得を始める前に(クリックして展開) 1. Adapty ダッシュボードで[プロダクトを作成](create-product)します。 2. Adapty ダッシュボードで[ペイウォールを作成し、プロダクトをペイウォールに組み込み](create-paywall)ます。 3. Adapty ダッシュボードで[プレースメントを作成し、ペイウォールをプレースメントに組み込み](create-placement)ます。 4. モバイルアプリに[Adapty SDKをインストール](sdk-installation-android)します。
## ペイウォール情報の取得 \{#fetch-paywall-information\} Adaptyでは、[プロダクト](product)はApp StoreとGoogle Play両方のプロダクトを組み合わせたものです。これらのクロスプラットフォームプロダクトはペイウォールに統合され、特定のモバイルアプリのプレースメント内で表示できます。 プロダクトを表示するには、`getPaywall`メソッドを使用して、いずれかの[プレースメント](placements)から[ペイウォール](paywalls)を取得する必要があります。 :::important **プロダクトIDをハードコーディングしないでください。** ハードコーディングすべき唯一のIDはプレースメントIDです。ペイウォールはリモートで設定されるため、プロダクトの数や利用可能なオファーはいつでも変更される可能性があります。アプリはこれらの変更を動的に処理する必要があります。今日ペイウォールが2つのプロダクトを返し、明日3つ返した場合、コードを変更せずにすべてを表示できるようにしてください。 ::: ```kotlin showLineNumbers Adapty.getPaywall("YOUR_PLACEMENT_ID", locale = "en") { result -> when (result) { is AdaptyResult.Success -> { val paywall = result.value // the requested paywall } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` ```java showLineNumbers Adapty.getPaywall("YOUR_PLACEMENT_ID", "en", result -> { if (result instanceof AdaptyResult.Success) { AdaptyPaywall paywall = ((AdaptyResult.Success) result).getValue(); // the requested paywall } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // handle the error } }); ``` | パラメータ | 必須/任意 | 説明 | |---------|--------|-----------| | **placementId** | 必須 | [プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** |

任意

デフォルト: `en`

|

[ペイウォールのローカライゼーション](add-remote-config-locale)の識別子。このパラメータはマイナス(**-**)文字で区切られた1つ以上のサブタグで構成される言語コードであることが期待されます。最初のサブタグは言語、2番目は地域を表します。

例:`en`は英語、`pt-br`はブラジルポルトガル語を表します。

ロケールコードおよび推奨される使用方法については、[ローカライゼーションとロケールコード](android-localizations-and-locale-codes)を参照してください。

| | **fetchPolicy** | デフォルト: `.reloadRevalidatingCacheData` |

デフォルトでは、SDKはサーバーからデータを読み込もうとし、失敗した場合はキャッシュされたデータを返します。ユーザーが常に最新のデータを取得できるため、この方法を推奨します。

ただし、ユーザーが不安定なインターネット環境にある場合は、`.returnCacheDataElseLoad`を使用してキャッシュデータが存在する場合に返すことを検討してください。この場合、ユーザーは最新のデータを取得できない可能性がありますが、インターネット接続が不安定でも高速な読み込みを体験できます。キャッシュは定期的に更新されるため、ネットワークリクエストを避けるためにセッション中に使用しても安全です。

キャッシュはアプリの再起動後も保持され、アプリの再インストールまたは手動クリーンアップ時にのみクリアされます。

Adapty SDKはペイウォールを2つのレイヤーに保存します:上記の定期的に更新されるキャッシュと[フォールバックペイウォール](android-use-fallback-paywalls)です。また、CDNを使用してペイウォールをより速く取得し、CDNに到達できない場合のスタンドアロンフォールバックサーバーも使用します。このシステムは、インターネット接続が不安定な場合でも常にペイウォールの最新バージョンを取得できるよう設計されています。

| | **loadTimeout** | デフォルト: 5秒 |

この値はこのメソッドのタイムアウトを制限します。タイムアウトに達した場合、キャッシュされたデータまたはローカルフォールバックが返されます。

まれに、処理が内部で複数のリクエストで構成される場合があるため、このメソッドは`loadTimeout`で指定した時間よりわずかに遅くタイムアウトする場合があります。

| プロダクトIDをハードコーディングしないでください!ペイウォールはリモートで設定されるため、利用可能なプロダクト、プロダクト数、特別オファー(無料トライアルなど)は時間とともに変更される可能性があります。これらのシナリオをコードで処理してください。 例えば、最初に2つのプロダクトを取得した場合、アプリはその2つを表示する必要があります。その後3つのプロダクトを取得した場合、コードを変更せずに3つすべてを表示する必要があります。ハードコーディングが必要なのはプレースメントIDだけです。 レスポンスパラメータ: | パラメータ | 説明 | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- | | Paywall | プロダクトIDのリスト、ペイウォール識別子、リモートコンフィグ、その他いくつかのプロパティを含む[`AdaptyPaywall`](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall/)オブジェクト。 | ## プロダクトの取得 \{#fetch-products\} ペイウォールを取得したら、それに対応するプロダクト配列を照会できます: ```kotlin showLineNumbers Adapty.getPaywallProducts(paywall) { result -> when (result) { is AdaptyResult.Success -> { val products = result.value // the requested products } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` ```java showLineNumbers Adapty.getPaywallProducts(paywall, result -> { if (result instanceof AdaptyResult.Success) { List products = ((AdaptyResult.Success>) result).getValue(); // the requested products } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // handle the error } }); ``` レスポンスパラメータ: | パラメータ | 説明 | | :-------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Products | プロダクト識別子、プロダクト名、価格、通貨、サブスクリプション期間、その他いくつかのプロパティを含む[`AdaptyPaywallProduct`](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall-product/)オブジェクトのリスト。 | 独自のペイウォールデザインを実装する場合、[`AdaptyPaywallProduct`](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall-product/)オブジェクトのこれらのプロパティにアクセスする必要があるでしょう。以下によく使用されるプロパティを示しますが、利用可能なすべてのプロパティの詳細については、リンクされたドキュメントを参照してください。 | プロパティ | 説明 | |-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Title** | プロダクトのタイトルを表示するには、`product.localizedTitle`を使用します。ローカライゼーションはデバイス自体のロケールではなく、ユーザーが選択したストアの国に基づいています。 | | **Price** | ローカライズされた価格を表示するには、`product.price.localizedString`を使用します。このローカライゼーションはデバイスのロケール情報に基づいています。`product.price.amount`を使用して数値として価格にアクセスすることもできます。値はローカル通貨で提供されます。関連する通貨記号を取得するには、`product.price.currencySymbol`を使用します。 | | **Subscription Period** | 期間(週、月、年など)を表示するには、`product.subscriptionDetails?.localizedSubscriptionPeriod`を使用します。このローカライゼーションはデバイスのロケールに基づいています。プログラムでサブスクリプション期間を取得するには、`product.subscriptionDetails?.subscriptionPeriod`を使用します。そこから`unit`列挙型にアクセスして期間の長さ(DAY、WEEK、MONTH、YEAR、またはUNKNOWN)を取得できます。`numberOfUnits`の値で期間単位の数を取得できます。例えば、四半期ごとのサブスクリプションの場合、unitプロパティに`MONTH`、numberOfUnitsプロパティに`3`が表示されます。 | | **Introductory Offer** | サブスクリプションに初回オファーが含まれているかどうかを示すバッジやインジケーターを表示するには、`product.subscriptionDetails?.introductoryOfferPhases`プロパティを確認してください。これは最大2つの割引フェーズ(無料トライアルフェーズと初回価格フェーズ)を含めることができるリストです。各フェーズオブジェクト内には以下の役立つプロパティがあります:
• `paymentMode`:`FREE_TRIAL`、`PAY_AS_YOU_GO`、`PAY_UPFRONT`、`UNKNOWN`の値を持つ列挙型。無料トライアルは`FREE_TRIAL`タイプになります。
• `price`:数値としての割引価格。無料トライアルの場合は`0`を探してください。
• `localizedNumberOfPeriods`:オファーの期間を説明するデバイスのロケールを使用してローカライズされた文字列。例えば、3日間のトライアルオファーはこのフィールドに`3 days`と表示されます。
• `subscriptionPeriod`:または、このプロパティでオファー期間の個別の詳細を取得できます。オファーに対しては前のセクションで説明したのと同じ方法で機能します。
• `localizedSubscriptionPeriod`:ユーザーのロケールに対してフォーマットされた割引のサブスクリプション期間。 | ## デフォルトオーディエンスのペイウォールでペイウォール取得を高速化する \{#speed-up-paywall-fetching-with-default-audience-paywall\} 通常、ペイウォールはほぼ即座に取得されるため、このプロセスの高速化を心配する必要はありません。ただし、オーディエンスとペイウォールが多数あり、ユーザーのインターネット接続が弱い場合、ペイウォールの取得に予想以上に時間がかかることがあります。そのような状況では、ペイウォールをまったく表示しないよりもスムーズなユーザー体験を確保するために、デフォルトのペイウォールを表示したい場合があります。 これに対処するため、`getPaywallForDefaultAudience`メソッドを使用できます。このメソッドは、**All Users**オーディエンス向けに指定されたプレースメントのペイウォールを取得します。ただし、上記の[ペイウォール情報の取得](fetch-paywalls-and-products-android#fetch-paywall-information)セクションで詳述されているように、推奨されるアプローチは`getPaywall`メソッドでペイウォールを取得することであることを理解することが重要です。 :::warning `getPaywall`を推奨する理由 `getPaywallForDefaultAudience`メソッドにはいくつかの重大な欠点があります: - **後方互換性の問題の可能性**:現在および将来のアプリバージョンで異なるペイウォールを表示する必要がある場合、課題に直面する可能性があります。現在の(レガシー)バージョンをサポートするペイウォールを設計するか、現在の(レガシー)バージョンのユーザーがレンダリングされないペイウォールに問題が発生する可能性を受け入れる必要があります。 - **ターゲティングの喪失**:すべてのユーザーが**All Users**オーディエンス向けに設計された同じペイウォールを表示するため、パーソナライズされたターゲティング(国、マーケティングアトリビューション、独自のカスタム属性に基づくものを含む)が失われます。 これらの欠点を受け入れてペイウォール取得の高速化の恩恵を受けたい場合は、以下のように`getPaywallForDefaultAudience`メソッドを使用してください。そうでない場合は、[上記](#fetch-paywall-information)で説明した`getPaywall`を使用してください。 ::: ```kotlin showLineNumbers Adapty.getPaywallForDefaultAudience("YOUR_PLACEMENT_ID", locale = "en") { result -> when (result) { is AdaptyResult.Success -> { val paywall = result.value // the requested paywall } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` ```java showLineNumbers Adapty.getPaywallForDefaultAudience("YOUR_PLACEMENT_ID", "en", result -> { if (result instanceof AdaptyResult.Success) { AdaptyPaywall paywall = ((AdaptyResult.Success) result).getValue(); // the requested paywall } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // handle the error } }); ``` :::note `getPaywallForDefaultAudience`メソッドはAndroid SDKバージョン2.11.3以降から利用可能です。 ::: | パラメータ | 必須/任意 | 説明 | |---------|--------|-----------| | **placementId** | 必須 | [プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** |

任意

デフォルト: `en`

|

[ペイウォールのローカライゼーション](add-remote-config-locale)の識別子。このパラメータはマイナス(**-**)文字で区切られた1つ以上のサブタグで構成される言語コードであることが期待されます。最初のサブタグは言語、2番目は地域を表します。

例:`en`は英語、`pt-br`はブラジルポルトガル語を表します。

ロケールコードおよび推奨される使用方法については、[ローカライゼーションとロケールコード](android-localizations-and-locale-codes)を参照してください。

| | **fetchPolicy** | デフォルト: `.reloadRevalidatingCacheData` |

デフォルトでは、SDKはサーバーからデータを読み込もうとし、失敗した場合はキャッシュされたデータを返します。ユーザーが常に最新のデータを取得できるため、この方法を推奨します。

ただし、ユーザーが不安定なインターネット環境にある場合は、`.returnCacheDataElseLoad`を使用してキャッシュデータが存在する場合に返すことを検討してください。この場合、ユーザーは最新のデータを取得できない可能性がありますが、インターネット接続が不安定でも高速な読み込みを体験できます。キャッシュは定期的に更新されるため、ネットワークリクエストを避けるためにセッション中に使用しても安全です。

キャッシュはアプリの再起動後も保持され、アプリの再インストールまたは手動クリーンアップ時にのみクリアされます。

| --- # File: present-remote-config-paywalls-android --- --- title: "Android SDKでリモートコンフィグで設計されたペイウォールを表示する" description: "Adapty Android SDKでリモートコンフィグペイウォールを表示してユーザー体験をパーソナライズする方法を解説します。" --- リモートコンフィグを使用してペイウォールをカスタマイズした場合、ユーザーに表示するためにモバイルアプリのコードでレンダリングを実装する必要があります。リモートコンフィグは柔軟にカスタマイズできるため、何を含めるか、またペイウォールのビューをどのように表示するかはすべて自分で制御できます。リモートコンフィグ経由で設定したカスタムペイウォールを表示するために、リモート設定を取得するメソッドを提供しています。 ## ペイウォールのリモートコンフィグを取得して表示する \{#get-paywall-remote-config-and-present-it\} ペイウォールのリモートコンフィグを取得するには、`remoteConfig` プロパティにアクセスして必要な値を取り出します。 ```kotlin showLineNumbers Adapty.getPaywall("YOUR_PLACEMENT_ID") { result -> when (result) { is AdaptyResult.Success -> { val paywall = result.value val headerText = paywall.remoteConfig?.dataMap?.get("header_text") as? String } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` ```java showLineNumbers Adapty.getPaywall("YOUR_PLACEMENT_ID", result -> { if (result instanceof AdaptyResult.Success) { AdaptyPaywall paywall = ((AdaptyResult.Success) result).getValue(); AdaptyPaywall.RemoteConfig remoteConfig = paywall.getRemoteConfig(); if (remoteConfig != null) { if (remoteConfig.getDataMap().get("header_text") instanceof String) { String headerText = (String) remoteConfig.getDataMap().get("header_text"); } } } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // handle the error } }); ``` 必要な値をすべて取得したら、それらをレンダリングして視覚的に魅力的なページに組み立てます。さまざまなスマートフォンの画面サイズや向きに対応したデザインにし、あらゆるデバイスでシームレスで使いやすい体験を提供してください。 :::warning [ペイウォール表示イベントの記録](present-remote-config-paywalls-android#track-paywall-view-events)を以下の手順に従って必ず行ってください。これにより、Adapty アナリティクスがファネルおよび A/B テストの情報を収集できるようになります。 ::: ペイウォールの表示が完了したら、購入フローの設定に進みます。ユーザーが購入する際は、ペイウォールのプロダクトを使用して `.makePurchase()` を呼び出すだけです。`.makePurchase()` メソッドの詳細については、[購入の実行](android-making-purchases)をご覧ください。 インターネット接続がない場合やキャッシュが利用できない場合でもスムーズな体験を保証するために、[フォールバックペイウォールと呼ばれるバックアップペイウォールの作成](android-use-fallback-paywalls)をお勧めします。 ## ペイウォール表示イベントを記録する \{#track-paywall-view-events\} Adapty はペイウォールのパフォーマンス測定をサポートしています。購入データは自動的に収集されますが、ペイウォールの表示ログはお客様自身が記録する必要があります。ユーザーがペイウォールを見るタイミングを把握しているのはお客様だけだからです。 ペイウォール表示イベントを記録するには、`.logShowPaywall(paywall)` を呼び出すだけです。これにより、ファネルや A/B テストのペイウォール指標に反映されます。 :::important [ペイウォールビルダー](adapty-paywall-builder)で作成したペイウォールを表示している場合は、`.logShowPaywall(paywall)` を呼び出す必要はありません。 ::: ```kotlin showLineNumbers Adapty.logShowPaywall(paywall) ``` リクエストパラメーター: | パラメーター | 必須 | 説明 | | :---------- | :------- |:------------------------------------------------------------------------------------------------------------| | **paywall** | 必須 | [`AdaptyPaywall`](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall/) オブジェクト。 | --- # File: android-making-purchases --- --- title: "Android SDKでモバイルアプリのアプリ内課金を行う" description: "Adaptyを使ってアプリ内課金とサブスクリプションを処理するガイド。" --- モバイルアプリにペイウォールを表示することは、ユーザーにプレミアムコンテンツやサービスへのアクセスを提供するうえで欠かせないステップです。ただし、[ペイウォールビルダー](adapty-paywall-builder)を使ってペイウォールをカスタマイズしている場合に限り、ペイウォールを表示するだけで購入処理を完結できます。 ペイウォールビルダーを使用しない場合は、`.makePurchase()` という別のメソッドを使って購入を完了し、目的のコンテンツを解放する必要があります。このメソッドは、ユーザーがペイウォールを通じて希望のトランザクションを進めるための入口となります。 ペイウォールに、ユーザーが購入しようとしているプロダクトに対して有効なプロモーションオファーが設定されている場合、Adapty は購入時に自動的にそのオファーを適用します。 :::warning 初回オファーは、ペイウォールビルダーで設定したペイウォールを使用している場合にのみ自動的に適用されることに注意してください。 それ以外の場合は、[iOSで初回オファーの適用資格を確認する](fetch-paywalls-and-products#check-intro-offer-eligibility-on-ios)必要があります。このステップを省略すると、リリース時にアプリが審査でリジェクトされる可能性があります。さらに、初回オファーの対象ユーザーに通常価格が請求されてしまう恐れもあります。 ::: [初期設定](quickstart)を一つも省かずに完了させていることを確認してください。設定が完了していないと、購入の検証ができません。 ## 購入を行う \{#make-purchase\} :::note **[ペイウォールビルダー](adapty-paywall-builder)をお使いですか?** 購入は自動的に処理されるため、このステップはスキップできます。 **ステップバイステップのガイドをお探しですか?** 全体のコンテキストを含む実装手順については、[クイックスタートガイド](android-implement-paywalls-manually)をご確認ください。 ::: ```kotlin showLineNumbers Adapty.makePurchase(activity, product, null) { result -> when (result) { is AdaptyResult.Success -> { when (val purchaseResult = result.value) { is AdaptyPurchaseResult.Success -> { val profile = purchaseResult.profile if (profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive == true) { // Grant access to the paid features } } is AdaptyPurchaseResult.UserCanceled -> { // Handle the case where the user canceled the purchase } is AdaptyPurchaseResult.Pending -> { // Handle deferred purchases (e.g., the user will pay offline with cash) } } } is AdaptyResult.Error -> { val error = result.error // Handle the error } } } ``` ```java showLineNumbers Adapty.makePurchase(activity, product, null, result -> { if (result instanceof AdaptyResult.Success) { AdaptyPurchaseResult purchaseResult = ((AdaptyResult.Success) result).getValue(); if (purchaseResult instanceof AdaptyPurchaseResult.Success) { AdaptyProfile profile = ((AdaptyPurchaseResult.Success) purchaseResult).getProfile(); AdaptyProfile.AccessLevel premium = profile.getAccessLevels().get("YOUR_ACCESS_LEVEL"); if (premium != null && premium.isActive()) { // Grant access to the paid features } } else if (purchaseResult instanceof AdaptyPurchaseResult.UserCanceled) { // Handle the case where the user canceled the purchase } else if (purchaseResult instanceof AdaptyPurchaseResult.Pending) { // Handle deferred purchases (e.g., the user will pay offline with cash) } } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // Handle the error } }); ``` リクエストパラメータ: | パラメータ | 必須 | 説明 | | :---------- | :------- | :-------------------------------------------------------------------------------------------------- | | **Product** | 必須 | ペイウォールから取得した [`AdaptyPaywallProduct`](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall-product/) オブジェクト。 | レスポンスパラメータ: | パラメータ | 説明 | |---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Profile** |

リクエストが成功した場合、レスポンスにはこのオブジェクトが含まれます。[AdaptyProfile](https://android.adapty.io/adapty/com.adapty.models/-adapty-profile/) オブジェクトは、アプリ内のユーザーのアクセスレベル、サブスクリプション、および買い切り購入に関する包括的な情報を提供します。

アクセスレベルのステータスを確認して、ユーザーがアプリへの必要なアクセス権を持っているかどうかを確認してください。

| :::warning **注意:** Apple の StoreKit バージョンが v2.0 未満で、Adapty SDK バージョンが v2.9.0 未満の場合は、代わりに [Apple App Store 共有シークレット](app-store-connection-configuration#step-5-enter-app-store-shared-secret)を提供する必要があります。この方法は現在 Apple によって非推奨とされています。 ::: ## 購入時にサブスクリプションを変更する \{#change-subscription-when-making-a-purchase\} ユーザーが現在のサブスクリプションを更新する代わりに新しいサブスクリプションを選択した場合、その動作はアプリストアによって異なります。Google Play では、サブスクリプションは自動的に更新されません。以下に説明するように、モバイルアプリのコードで切り替えを管理する必要があります。 Android でサブスクリプションを別のものに変更するには、追加パラメータを指定して `.makePurchase()` メソッドを呼び出します: ```kotlin showLineNumbers Adapty.makePurchase( activity, product, AdaptyPurchaseParameters.Builder() .withSubscriptionUpdateParams(subscriptionUpdateParams) .build() ) { result -> when (result) { is AdaptyResult.Success -> { when (val purchaseResult = result.value) { is AdaptyPurchaseResult.Success -> { val profile = purchaseResult.profile // successful cross-grade } is AdaptyPurchaseResult.UserCanceled -> { // user canceled the purchase flow } is AdaptyPurchaseResult.Pending -> { // the purchase has not been finished yet, e.g. user will pay offline by cash } } } is AdaptyResult.Error -> { val error = result.error // Handle the error } } } ``` 追加リクエストパラメータ: | パラメータ | 必須 | 説明 | | :--------------------------- | :------- | :----------------------------------------------------------- | | **subscriptionUpdateParams** | 必須 | [`AdaptySubscriptionUpdateParameters`](https://android.adapty.io/adapty/com.adapty.models/-adapty-subscription-update-parameters/) オブジェクト。 | ```java showLineNumbers Adapty.makePurchase( activity, product, new AdaptyPurchaseParameters.Builder() .withSubscriptionUpdateParams(subscriptionUpdateParams) .build(), result -> { if (result instanceof AdaptyResult.Success) { AdaptyPurchaseResult purchaseResult = ((AdaptyResult.Success) result).getValue(); if (purchaseResult instanceof AdaptyPurchaseResult.Success) { AdaptyProfile profile = ((AdaptyPurchaseResult.Success) purchaseResult).getProfile(); // successful cross-grade } else if (purchaseResult instanceof AdaptyPurchaseResult.UserCanceled) { // user canceled the purchase flow } else if (purchaseResult instanceof AdaptyPurchaseResult.Pending) { // the purchase has not been finished yet, e.g. user will pay offline by cash } } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // Handle the error } }); ``` 追加リクエストパラメータ: | パラメータ | 必須 | 説明 | | :--------------------------- | :------- | :----------------------------------------------------------- | | **subscriptionUpdateParams** | 必須 | [`AdaptySubscriptionUpdateParameters`](https://android.adapty.io/adapty/com.adapty.models/-adapty-subscription-update-parameters/) オブジェクト。 | サブスクリプションと置き換えモードの詳細については、Google Developer のドキュメントをご覧ください: - [置き換えモードについて](https://developer.android.com/google/play/billing/subscriptions#replacement-modes) - [置き換えモードに関する Google の推奨事項](https://developer.android.com/google/play/billing/subscriptions#replacement-recommendations) - 置き換えモード [`CHARGE_PRORATED_PRICE`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode#CHARGE_PRORATED_PRICE())。注意:このメソッドはサブスクリプションのアップグレードにのみ利用可能です。ダウングレードはサポートされていません。 - 置き換えモード [`DEFERRED`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode#DEFERRED())。注意:実際のサブスクリプション変更は、現在のサブスクリプションの請求期間が終了した時点でのみ発生します。 ### プリペイドプランを管理する \{#manage-prepaid-plans\} アプリユーザーが[プリペイドプラン](https://developer.android.com/google/play/billing/subscriptions#prepaid-plans)(例:数ヶ月分の非自動更新サブスクリプションを購入)を利用できる場合、プリペイドプランの[保留中のトランザクション](https://developer.android.com/google/play/billing/subscriptions#pending)を有効にできます。 ```kotlin showLineNumbers AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withEnablePendingPrepaidPlans(true) .build() ``` ```java showLineNumbers new AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withEnablePendingPrepaidPlans(true) .build(); ``` --- # File: android-restore-purchase --- --- title: "Android SDKで購入を復元する" description: "Adaptyで購入を復元し、シームレスなユーザー体験を実現する方法を学びましょう。" --- 購入の復元は、サブスクリプションやアプリ内課金などの購入済みコンテンツに、再度課金されることなくアクセスを取り戻せる機能です。アプリをアンインストールして再インストールしたユーザーや、新しいデバイスに乗り換えたユーザーが、以前の購入コンテンツに再び支払いなしでアクセスしたい場合に特に役立ちます。 :::note [ペイウォールビルダー](adapty-paywall-builder)で作成したペイウォールでは、追加のコードなしで購入が自動的に復元されます。その場合は、このステップをスキップできます。 ::: [ペイウォールビルダー](adapty-paywall-builder)を使ってペイウォールをカスタマイズしていない場合に購入を復元するには、`.restorePurchases()` メソッドを呼び出してください。 ```kotlin showLineNumbers Adapty.restorePurchases { result -> when (result) { is AdaptyResult.Success -> { val profile = result.value if (profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive == true) { // successful access restore } } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` ```java showLineNumbers Adapty.restorePurchases(result -> { if (result instanceof AdaptyResult.Success) { AdaptyProfile profile = ((AdaptyResult.Success) result).getValue(); if (profile != null) { AdaptyProfile.AccessLevel premium = profile.getAccessLevels().get("YOUR_ACCESS_LEVEL"); if (premium != null && premium.isActive()) { // successful access restore } } } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // handle the error } }); ``` レスポンスパラメータ: | パラメータ | 説明 | |---------|-----------| | **Profile** |

[`AdaptyProfile`](https://android.adapty.io/adapty/com.adapty.models/-adapty-profile/) オブジェクト。このモデルにはアクセスレベル、サブスクリプション、買い切り購入に関する情報が含まれています。

ユーザーがアプリへのアクセス権を持っているかどうかを判断するには、**アクセスレベルのステータス**を確認してください。

| :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: --- # File: implement-observer-mode-android --- --- title: "Android SDKにオブザーバーモードを実装する" description: "Android SDKでAdaptyのオブザーバーモードを実装し、ユーザーのサブスクリプションイベントを追跡します。" --- すでに独自の購入インフラがあり、Adaptyへの完全な移行を検討していない場合は、[オブザーバーモード](observer-vs-full-mode)を検討してみてください。基本的な機能として、オブザーバーモードは高度なアナリティクスと、アトリビューションおよびアナリティクスシステムとのシームレスな連携を提供します。 これで十分な場合、必要な作業は以下の2つだけです: 1. `observerMode` パラメータを `true` に設定して、Adapty SDKの設定時にオブザーバーモードを有効化する。[Android](sdk-installation-android#activate-adapty-module-of-adapty-sdk)のセットアップ手順を参照してください。 2. 既存の購入インフラから[トランザクションをAdaptyに報告する](report-transactions-observer-mode-android)。 ## オブザーバーモードのセットアップ \{#observer-mode-setup\} 購入とサブスクリプションのステータスを自分で管理し、サブスクリプションイベントとアナリティクスの送信にAdaptyを使用する場合は、オブザーバーモードを有効にしてください。 :::important オブザーバーモードで動作している場合、Adapty SDKはトランザクションをクローズしません。そのため、ご自身でトランザクションを処理するようにしてください。 ::: ```kotlin showLineNumbers class MyApplication : Application() { override fun onCreate() { super.onCreate() Adapty.activate( applicationContext, AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withObserverMode(true) //default false .build() ) } ``` ```java showLineNumbers public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); Adapty.activate( applicationContext, new AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withObserverMode(true) //default false .build() ); } ``` パラメータ: | パラメータ | 説明 | | --------------------------- | ------------------------------------------------------------ | | observerMode | [オブザーバーモード](observer-vs-full-mode)を制御するboolean値。デフォルト値は `false` です。 | ## オブザーバーモードでAdaptyのペイウォールを使用する \{#using-adapty-paywalls-in-observer-mode\} Adaptyのペイウォールとそれを利用したA/Bテスト機能も使用したい場合は可能ですが、オブザーバーモードでは追加の設定が必要です。上記の手順に加えて、以下の作業が必要です: 1. [リモートコンフィグペイウォール](present-remote-config-paywalls-android)の場合は通常通りペイウォールを表示する。ペイウォールビルダーのペイウォールについては、[Android](android-present-paywall-builder-paywalls-in-observer-mode)の専用セットアップガイドを参照してください。 3. 購入トランザクションに[ペイウォールを関連付ける](report-transactions-observer-mode-android)。 --- # File: report-transactions-observer-mode-android --- --- title: "Android SDKのオブザーバーモードでトランザクションを報告する" description: "Android SDKのAdaptyオブザーバーモードで購入トランザクションを報告し、ユーザーインサイトと収益トラッキングを行います。" --- オブザーバーモードでは、Adapty SDKは既存の購入システムを通じて行われた購入を自動的に追跡できません。アプリストアからのトランザクションを自分で報告する必要があります。アナリティクスのエラーを防ぐため、アプリをリリースする**前に**この設定を完了しておくことが重要です。 各トランザクションをAdaptyに明示的に報告するには、`reportTransaction`を使用してください。 :::warning **トランザクションの報告をスキップしないでください!** `reportTransaction`を呼び出さない場合、Adaptyはそのトランザクションを認識できず、アナリティクスに表示されず、インテグレーションにも送信されません。 ::: Adaptyのペイウォールを使用している場合は、トランザクションを報告する際に`variationId`を含めてください。これにより、購入がトリガーとなったペイウォールに紐付けられ、正確なペイウォールアナリティクスが確保されます。 ```kotlin showLineNumbers val transactionInfo = TransactionInfo.fromPurchase(purchase) Adapty.reportTransaction(transactionInfo, variationId) { result -> if (result is AdaptyResult.Success) { // success } } ``` パラメーター: | パラメーター | 必須/任意 | 説明 | | --------------- | --------- | ------------------------------------------------------------ | | transactionInfo | 必須 | 購入からのTransactionInfoです。purchaseはBillingライブラリの[Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase)クラスのインスタンスです。 | | variationId | 任意 | バリアントの文字列識別子です。[AdaptyPaywall](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall/)オブジェクトの`variationId`プロパティを使用して取得できます。 | ```java showLineNumbers TransactionInfo transactionInfo = TransactionInfo.fromPurchase(purchase); Adapty.reportTransaction(transactionInfo, variationId, result -> { if (result instanceof AdaptyResult.Success) { // success } }); ``` パラメーター: | パラメーター | 必須/任意 | 説明 | | --------------- | --------- | ------------------------------------------------------------ | | transactionInfo | 必須 | 購入からのTransactionInfoです。purchaseはBillingライブラリの[Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase)クラスのインスタンスです。 | | variationId | 任意 | バリアントの文字列識別子です。[AdaptyPaywall](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall/)オブジェクトの`variationId`プロパティを使用して取得できます。 | オブザーバーモードでは、Adapty SDKは既存の購入システムを通じて行われた購入を自動的に追跡できません。アプリストアからのトランザクションを報告するか、復元する必要があります。アナリティクスのエラーを防ぐため、アプリをリリースする**前に**この設定を完了しておくことが重要です。 トランザクションをAdaptyに報告するには、`restorePurchases`を使用してください。 :::warning **購入の復元をスキップしないでください!** `restorePurchases`を呼び出さない場合、Adaptyはそのトランザクションを認識できず、アナリティクスに表示されず、インテグレーションにも送信されません。 ::: Adaptyのペイウォールを使用している場合は、`setVariationId`メソッドを使用して、トランザクションを購入のきっかけとなったペイウォールに紐付けてください。これにより、正確なアナリティクスのために購入がトリガーとなったペイウォールに正しく関連付けられます。この手順は、Adaptyのペイウォールを使用している場合にのみ必要です。 ```kotlin showLineNumbers Adapty.restorePurchases { result -> if (result is AdaptyResult.Success) { // success } } Adapty.setVariationId(transactionId, variationId) { error -> if (error == null) { // success } } ``` パラメーター: | パラメーター | 必須/任意 | 説明 | | ------------- | --------- | ------------------------------------------------------------ | | transactionId | 必須 | 購入の文字列識別子(`purchase.getOrderId`)です。purchaseはBillingライブラリの[Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase)クラスのインスタンスです。 | | variationId | 必須 | バリアントの文字列識別子です。[AdaptyPaywall](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall/)オブジェクトの`variationId`プロパティを使用して取得できます。 | ```java showLineNumbers Adapty.restorePurchases(result -> { if (result instanceof AdaptyResult.Success) { // success } }); Adapty.setVariationId(transactionId, variationId, error -> { if (error == null) { // success } }); ``` パラメーター: | パラメーター | 必須/任意 | 説明 | | ------------- | --------- | ------------------------------------------------------------ | | transactionId | 必須 | 購入の文字列識別子(`purchase.getOrderId`)です。purchaseはBillingライブラリの[Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase)クラスのインスタンスです。 | | variationId | 必須 | バリアントの文字列識別子です。[AdaptyPaywall](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall/)オブジェクトの`variationId`プロパティを使用して取得できます。 | **トランザクションの報告** オブザーバーモードでAdaptyにトランザクションを報告するには、[モバイルコードでの購入の復元](android-restore-purchase)ページで説明されているように`restorePurchases`を使用してください。 :::warning **トランザクションの報告をスキップしないでください!** `restorePurchases`を呼び出さない場合、Adaptyはそのトランザクションを認識できず、アナリティクスに表示されず、インテグレーションにも送信されません。 ::: **ペイウォールとトランザクションの関連付け** Adapty SDKは購入の発生元を判断できません。購入の処理はあなた自身が行うためです。そのため、オブザーバーモードでペイウォールやA/B テストを使用する場合は、アプリストアからのトランザクションをモバイルアプリのコード内で対応するペイウォールに関連付ける必要があります。アプリのリリース前にこれを正しく設定しておくことが重要です。設定しないと、アナリティクスにエラーが発生します。 ```kotlin Adapty.setVariationId(transactionId, variationId) { error -> if (error == null) { // success } } ``` リクエストパラメーター: | パラメーター | 必須/任意 | 説明 | | ------------- | --------- | ------------------------------------------------------------ | | transactionId | 必須 | 購入の文字列識別子(purchase.getOrderId)です。purchaseはBillingライブラリの[Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase)クラスのインスタンスです。 | | variationId | 必須 | バリアントの文字列識別子です。[AdaptyPaywall](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall/)オブジェクトの`variationId`プロパティを使用して取得できます。 | ```java Adapty.setVariationId(transactionId, variationId, error -> { if (error == null) { // success } }); ``` | パラメーター | 必須/任意 | 説明 | | ------------- | --------- | ------------------------------------------------------------ | | transactionId | 必須 | 購入の文字列識別子(purchase.getOrderId)です。purchaseはBillingライブラリの[Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase)クラスのインスタンスです。 | | variationId | 必須 | バリアントの文字列識別子です。[AdaptyPaywall](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall/)オブジェクトの`variationId`プロパティを使用して取得できます。 | --- # File: android-present-paywall-builder-paywalls-in-observer-mode --- --- title: "Android SDKのObserverモードでペイウォールビルダーのペイウォールを表示する" description: "Adaptyのペイウォールビルダーを使用してObserverモードでペイウォールを表示する方法について説明します。" --- ペイウォールビルダーを使ってペイウォールをカスタマイズした場合、モバイルアプリのコードでユーザーに表示するための描画処理を別途実装する必要はありません。このようなペイウォールには、表示内容と表示方法の両方が含まれています。 :::warning このセクションは[Observerモード](observer-vs-full-mode)専用です。Observerモードを使用していない場合は、[Android - ペイウォールビルダーのペイウォールを表示する](android-present-paywalls)を参照してください。 :::
ペイウォールの表示を始める前に(クリックして展開) 1. Adaptyの初期連携を[Google Play](initial-android)および[App Store](initial_ios)と行います。 2. Adapty SDKをインストールして設定します。`observerMode`パラメータを`true`に設定してください。フレームワーク別の手順は[Android向け](sdk-installation-android)を参照してください。 3. Adapty ダッシュボードで[プロダクトを作成](create-product)します。 4. Adapty ダッシュボードで[ペイウォールを設定してプロダクトを割り当て](create-paywall)、ペイウォールビルダーを使ってカスタマイズします。 5. Adapty ダッシュボードで[プレースメントを作成してペイウォールを割り当て](create-placement)ます。 6. モバイルアプリのコードで[ペイウォールビルダーのペイウォールとその設定を取得](android-get-pb-paywalls)します。

1. `AdaptyUiObserverModeHandler`を実装します。 `onPurchaseInitiated`イベントは、ユーザーが購入を開始したことを通知します。このコールバックに応じてカスタムの購入フローをトリガーできます: ```kotlin showLineNumbers val observerModeHandler = AdaptyUiObserverModeHandler { product, paywall, paywallView, onStartPurchase, onFinishPurchase -> onStartPurchase() yourBillingClient.makePurchase( product, onSuccess = { purchase -> onFinishPurchase() //handle success }, onError = { onFinishPurchase() //handle error }, onCancel = { onFinishPurchase() //handle cancel } ) } ``` ```java showLineNumbers AdaptyUiObserverModeHandler observerModeHandler = (product, paywall, paywallView, onStartPurchase, onFinishPurchase) -> { onStartPurchase.invoke(); yourBillingClient.makePurchase( product, purchase -> { onFinishPurchase.invoke(); //handle success }, error -> { onFinishPurchase.invoke(); //handle error }, () -> { //cancellation onFinishPurchase.invoke(); //handle cancel } ); }; ``` Observerモードでの復元を処理するには、`getRestoreHandler()`をオーバーライドします。デフォルトでは`null`が返され、Adaptyの組み込み`Adapty.restorePurchases()`フローが使用されます。独自の復元実装を提供するには: ```kotlin showLineNumbers val observerModeHandler = object : AdaptyUiObserverModeHandler { // onPurchaseInitiated implementation (see above) override fun getRestoreHandler() = AdaptyUiObserverModeHandler.RestoreHandler { onStartRestore, onFinishRestore -> onStartRestore() yourBillingClient.restorePurchases( onSuccess = { restoredPurchases -> onFinishRestore() //handle successful restore }, onError = { onFinishRestore() //handle error } ) } } ``` ```java showLineNumbers AdaptyUiObserverModeHandler observerModeHandler = new AdaptyUiObserverModeHandler() { // onPurchaseInitiated implementation (see above) @Override public RestoreHandler getRestoreHandler() { return (onStartRestore, onFinishRestore) -> { onStartRestore.invoke(); yourBillingClient.restorePurchases( restoredPurchases -> { onFinishRestore.invoke(); //handle successful restore }, error -> { onFinishRestore.invoke(); //handle error } ); }; } }; ``` 購入または復元プロセスをAdaptyUIに通知するために、以下のコールバックを呼び出すことを忘れないでください。これはローダーの表示など、ペイウォールの正常な動作に必要です: | コールバック | 説明 | | :----------------- |:---------------------------------------------------------------------------------------| | onStartPurchase() | 購入が開始されたことをAdaptyUIに通知するために呼び出します。 | | onFinishPurchase() | 購入が完了したことをAdaptyUIに通知するために呼び出します。 | | onStartRestore() | 任意。復元が開始されたことをAdaptyUIに通知するために呼び出せます。 | | onFinishRestore() | 任意。復元が完了したことをAdaptyUIに通知するために呼び出せます。 | 2. デバイス画面にビジュアルペイウォールを表示するには、まず設定が必要です。 これを行うには、`AdaptyUI.getPaywallView()`メソッドを呼び出すか、`AdaptyPaywallView`を直接作成します: ```kotlin showLineNumbers val paywallView = AdaptyUI.getPaywallView( activity, viewConfiguration, products, eventListener, personalizedOfferResolver, tagResolver, timerResolver, observerModeHandler, ) ``` ```kotlin showLineNumbers val paywallView = AdaptyPaywallView(activity) // or retrieve it from xml ... with(paywallView) { showPaywall( viewConfiguration, products, eventListener, personalizedOfferResolver, tagResolver, timerResolver, observerModeHandler, ) } ``` ```java showLineNumbers AdaptyPaywallView paywallView = AdaptyUI.getPaywallView( activity, viewConfiguration, products, eventListener, personalizedOfferResolver, tagResolver, timerResolver, observerModeHandler ); ``` ```java showLineNumbers AdaptyPaywallView paywallView = new AdaptyPaywallView(activity); //add to the view hierarchy if needed, or you receive it from xml ... paywallView.showPaywall(viewConfiguration, products, eventListener, personalizedOfferResolver, tagResolver, timerResolver, observerModeHandler); ``` ```xml showLineNumbers ``` ビューが正常に作成されたら、ビュー階層に追加して表示できます。 このコンポーザブル関数を使用します: ```kotlin showLineNumbers AdaptyPaywallScreen( viewConfiguration, products, eventListener, personalizedOfferResolver, tagResolver, timerResolver, ) ``` リクエストパラメータ: | パラメータ | 必須 | 説明 | |---------|--------|-----------| | **Products** | 任意 | `AdaptyPaywallProduct`の配列を指定すると、画面上のプロダクト表示タイミングを最適化できます。`null`を渡した場合、AdaptyUIが必要なプロダクトを自動的に取得します。 | | **ViewConfiguration** | 必須 | ペイウォールのビジュアル詳細を含む`AdaptyViewConfiguration`オブジェクトを指定します。`Adapty.getViewConfiguration(paywall)`メソッドを使って読み込みます。詳細は[ペイウォールのビジュアル設定を取得する](#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder)を参照してください。 | | **EventListener** | 任意 | `AdaptyUiEventListener`を指定してペイウォールのイベントを監視します。使いやすさのためAdaptyUiDefaultEventListenerの継承が推奨されます。詳細は[ペイウォールイベントの処理](android-handling-events)を参照してください。 | | **PersonalizedOfferResolver** | 任意 | パーソナライズ価格([詳細](https://developer.android.com/google/play/billing/integrate#personalized-price))を示すには、`AdaptyUiPersonalizedOfferResolver`を実装し、`AdaptyPaywallProduct`の価格がパーソナライズされている場合はtrue、そうでない場合はfalseを返す独自のロジックを渡します。 | | **TagResolver** | 任意 | `AdaptyUiTagResolver`を使用してペイウォールテキスト内のカスタムタグを解決します。このリゾルバーはタグパラメータを受け取り、対応する文字列に解決します。詳細はペイウォールビルダーのカスタムタグのトピックを参照してください。 | | **ObserverModeHandler** | Observerモードでは必須 | 前のステップで実装した`AdaptyUiObserverModeHandler`。 | | **variationId** | 必須 | バリアントの文字列識別子。[`AdaptyPaywall`](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall/)オブジェクトの`variationId`プロパティを使って取得できます。 | | **transaction** | 必須 |

iOS、StoreKit1の場合:[`SKPaymentTransaction`](https://developer.apple.com/documentation/storekit/skpaymenttransaction)オブジェクト。

iOS、StoreKit 2の場合:[Transaction](https://developer.apple.com/documentation/storekit/transaction)オブジェクト。

Androidの場合:購入のString識別子(`purchase.getOrderId()`)。ここで購入はBillingライブラリの[Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase)クラスのインスタンスです。

|
ペイウォールの表示を始める前に(クリックして展開) 1. Adaptyの初期連携を[Google Play](initial-android)および[App Store](initial_ios)と行います。 2. Adapty SDKをインストールして設定します。`observerMode`パラメータを`true`に設定してください。フレームワーク別の手順は[Android](sdk-installation-android)、[React Native](sdk-installation-reactnative)、[Flutter](sdk-installation-flutter#activate-adapty-module-of-adapty-sdk)、[Unity](sdk-installation-unity#activate-adapty-module-of-adapty-sdk)を参照してください。 3. Adapty ダッシュボードで[プロダクトを作成](create-product)します。 4. Adapty ダッシュボードで[ペイウォールを設定してプロダクトを割り当て](create-paywall)、ペイウォールビルダーを使ってカスタマイズします。 5. Adapty ダッシュボードで[プレースメントを作成してペイウォールを割り当て](create-placement)ます。 6. モバイルアプリのコードで[ペイウォールビルダーのペイウォールとその設定を取得](android-get-pb-paywalls)します。
1. `AdaptyUiObserverModeHandler`を実装します。`AdaptyUiObserverModeHandler`のコールバック(`onPurchaseInitiated`)は、ユーザーが購入を開始したタイミングを通知します。このコールバックに応じてカスタムの購入フローを次のようにトリガーできます: ```kotlin showLineNumbers val observerModeHandler = AdaptyUiObserverModeHandler { product, paywall, paywallView, onStartPurchase, onFinishPurchase -> onStartPurchase() yourBillingClient.makePurchase( product, onSuccess = { purchase -> onFinishPurchase() //handle success }, onError = { onFinishPurchase() //handle error }, onCancel = { onFinishPurchase() //handle cancel } ) } ``` ```java showLineNumbers AdaptyUiObserverModeHandler observerModeHandler = (product, paywall, paywallView, onStartPurchase, onFinishPurchase) -> { onStartPurchase.invoke(); yourBillingClient.makePurchase( product, purchase -> { onFinishPurchase.invoke(); //handle success }, error -> { onFinishPurchase.invoke(); //handle error }, () -> { //cancellation onFinishPurchase.invoke(); //handle cancel } ); }; ``` また、AdaptyUIへのコールバックを忘れずに呼び出してください。これはローダーの表示など、ペイウォールの正常な動作に必要です: | Kotlinでのコールバック | Javaでのコールバック | 説明 | | :----------------- | :------------------------ | :-------------------------------------------------------------------------------------------------------------------------------- | | onStartPurchase() | onStartPurchase.invoke() | 購入が開始されたことをAdaptyUIに通知するために呼び出します。 | | onFinishPurchase() | onFinishPurchase.invoke() | 購入が正常に完了したか、失敗したか、またはキャンセルされたことをAdaptyUIに通知するために呼び出します。 | 2. ビジュアルペイウォールを表示するには、まず初期化が必要です。`AdaptyUI.getPaywallView()`メソッドを呼び出すか、`AdaptyPaywallView`を直接作成します: ```kotlin showLineNumbers val paywallView = AdaptyUI.getPaywallView( activity, viewConfiguration, products, AdaptyPaywallInsets.of(topInset, bottomInset), eventListener, personalizedOfferResolver, tagResolver, observerModeHandler, ) //======= OR ======= val paywallView = AdaptyPaywallView(activity) // or retrieve it from xml ... with(paywallView) { setEventListener(eventListener) setObserverModeHandler(observerModeHandler) showPaywall( viewConfiguration, products, AdaptyPaywallInsets.of(topInset, bottomInset), personalizedOfferResolver, tagResolver, ) } ``` ```java showLineNumbers AdaptyPaywallView paywallView = AdaptyUI.getPaywallView( activity, viewConfiguration, products, AdaptyPaywallInsets.of(topInset, bottomInset), eventListener, personalizedOfferResolver, tagResolver, observerModeHandler ); //======= OR ======= AdaptyPaywallView paywallView = new AdaptyPaywallView(activity); //add to the view hierarchy if needed, or you receive it from xml ... paywallView.setEventListener(eventListener); paywallView.setObserverModeHandler(observerModeHandler); paywallView.showPaywall(viewConfiguration, products, AdaptyPaywallInsets.of(topInset, bottomInset), personalizedOfferResolver); ``` ```xml showLineNumbers ``` ビューが正常に作成されたら、ビュー階層に追加して表示できます。 リクエストパラメータ: | パラメータ | 必須 | 説明 | |---------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Products** | 任意 | `AdaptyPaywallProduct`の配列を指定すると、画面上のプロダクト表示タイミングを最適化できます。`null`を渡した場合、AdaptyUIが必要なプロダクトを自動的に取得します。 | | **ViewConfiguration** | 必須 | ペイウォールのビジュアル詳細を含む`AdaptyViewConfiguration`オブジェクトを指定します。`Adapty.getViewConfiguration(paywall)`メソッドを使って読み込みます。詳細は[ペイウォールのビジュアル設定を取得する](android-get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder)を参照してください。 | | **Insets** | 必須 | システムバーで覆われる領域の情報を含む`AdaptyPaywallInsets`オブジェクトを定義し、コンテンツの上下マージンを設定します。ステータスバーもナビゲーションバーも`AdaptyPaywallView`と重ならない場合は`AdaptyPaywallInsets.NONE`を渡します。システムバーがUIの一部と重なるフルスクリーンモードの場合は、表の下に示す方法でインセットを取得します。 | | **EventListener** | 任意 | `AdaptyUiEventListener`を指定してペイウォールのイベントを監視します。使いやすさのためAdaptyUiDefaultEventListenerの継承が推奨されます。詳細は[ペイウォールイベントの処理](android-handling-events)を参照してください。 | | **PersonalizedOfferResolver** | 任意 | パーソナライズ価格([詳細](https://developer.android.com/google/play/billing/integrate#personalized-price))を示すには、`AdaptyUiPersonalizedOfferResolver`を実装し、`AdaptyPaywallProduct`の価格がパーソナライズされている場合はtrue、そうでない場合はfalseを返す独自のロジックを渡します。 | | **TagResolver** | 任意 | `AdaptyUiTagResolver`を使用してペイウォールテキスト内のカスタムタグを解決します。このリゾルバーはタグパラメータを受け取り、対応する文字列に解決します。詳細はペイウォールビルダーのカスタムタグのトピックを参照してください。 | | **ObserverModeHandler** | Observerモードでは必須 | 前のステップで実装した`AdaptyUiObserverModeHandler`。 | | **variationId** | 必須 | バリアントの文字列識別子。[`AdaptyPaywall`](https://android.adapty.io/adapty/com.adapty.models/-adapty-paywall/)オブジェクトの`variationId`プロパティを使って取得できます。 | | **transaction** | 必須 |

iOS、StoreKit1の場合:[`SKPaymentTransaction`](https://developer.apple.com/documentation/storekit/skpaymenttransaction)オブジェクト。

iOS、StoreKit 2の場合:[Transaction](https://developer.apple.com/documentation/storekit/transaction)オブジェクト。

Androidの場合:購入のString識別子(`purchase.getOrderId()`)。ここで購入はBillingライブラリの[Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase)クラスのインスタンスです。

| システムバーがUIの一部と重なるフルスクリーンモードでは、次のようにインセットを取得します: ```kotlin showLineNumbers import androidx.core.graphics.Insets import androidx.core.view.ViewCompat import androidx.core.view.WindowInsetsCompat //create extension function fun View.onReceiveSystemBarsInsets(action: (insets: Insets) -> Unit) { ViewCompat.setOnApplyWindowInsetsListener(this) { _, insets -> val systemBarInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars()) ViewCompat.setOnApplyWindowInsetsListener(this, null) action(systemBarInsets) insets } } //and then use it with the view paywallView.onReceiveSystemBarsInsets { insets -> val paywallInsets = AdaptyPaywallInsets.of(insets.top, insets.bottom) paywallView.setEventListener(eventListener) paywallView.setObserverModeHandler(observerModeHandler) paywallView.showPaywall(viewConfig, products, paywallInsets, personalizedOfferResolver, tagResolver) } ``` ```java showLineNumbers import androidx.core.graphics.Insets; import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; ... ViewCompat.setOnApplyWindowInsetsListener(paywallView, (view, insets) -> { Insets systemBarInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars()); ViewCompat.setOnApplyWindowInsetsListener(paywallView, null); AdaptyPaywallInsets paywallInsets = AdaptyPaywallInsets.of(systemBarInsets.top, systemBarInsets.bottom); paywallView.setEventListener(eventListener); paywallView.setObserverModeHandler(observerModeHandler); paywallView.showPaywall(viewConfiguration, products, paywallInsets, personalizedOfferResolver, tagResolver); return insets; }); ``` 戻り値: | オブジェクト | 説明 | | :------------------ | :------------------------------------------------- | | `AdaptyPaywallView` | リクエストされたペイウォール画面を表すオブジェクト。 | :::warning [購入トランザクションにペイウォールを関連付ける](report-transactions-observer-mode-android)のを忘れないでください。設定しないと、Adaptyは購入元のペイウォールを特定できません。 :::
--- # File: android-troubleshoot-purchases --- --- title: "Android SDKでの購入に関するトラブルシューティング" description: "Android SDKでの購入に関するトラブルシューティング" --- このガイドでは、Android SDKで手動購入を実装する際によく発生する問題の解決方法を説明します。 ## makePurchaseが正常に完了してもプロファイルが更新されない \{#makepurchase-is-called-successfully-but-the-profile-is-not-being-updated\} **問題**: `makePurchase` メソッドが正常に完了するにもかかわらず、ユーザーのプロファイルとサブスクリプション状態がAdaptyで更新されない。 **原因**: 通常、Google Play Storeのセットアップが不完全であるか、設定に問題があることを示しています。 **解決策**: [Google Play のセットアップ手順](initial-android)がすべて完了しているか確認してください。 ## makePurchaseが2回呼び出される \{#makepurchase-is-invoked-twice\} **問題**: 同じ購入に対して `makePurchase` メソッドが複数回呼び出されている。 **原因**: UIの状態管理の問題や、ユーザーの素早い操作によって購入フローが複数回トリガーされる場合に発生します。 **解決策**: [Google Play のセットアップ手順](initial-android)がすべて完了しているか確認してください。 ## オブザーバーモードでのAdaptyError.cantMakePayments \{#adaptyerrorcantmakepayments-in-observer-mode\} **問題**: オブザーバーモードで `makePurchase` を使用すると `AdaptyError.cantMakePayments` が発生する。 **原因**: オブザーバーモードでは、Adaptyの `makePurchase` メソッドを使用せず、購入処理はご自身で行う必要があります。 **解決策**: 購入に `makePurchase` を使用している場合は、オブザーバーモードをオフにしてください。`makePurchase` を使用するか、オブザーバーモードで自前の購入処理を行うか、どちらか一方を選択してください。詳細は[オブザーバーモードの実装](implement-observer-mode-android)を参照してください。 ## Adaptyエラー: (code: 103, message: Play Market request failed on purchases updated: responseCode=3, debugMessage=Billing Unavailable, detail: null) \{#adapty-error-code-103-message-play-market-request-failed-on-purchases-updated-responsecode3-debugmessagebilling-unavailable-detail-null\} **問題**: Google Play Storeから課金不可エラーが返ってくる。 **原因**: このエラーはAdaptyとは無関係です。デバイスで課金が利用できないことを示すGoogle Play Billing Libraryのエラーです。 **解決策**: このエラーはAdaptyとは無関係です。Play Storeのドキュメントで詳細を確認できます: [Handle BillingResult response codes](https://developer.android.com/google/play/billing/errors#billing_unavailable_error_code_3) | Play Billing | Android Developers。 ## makePurchasesCompletionHandlersが見つからない \{#not-found-makepurchasescompletionhandlers\} **問題**: `makePurchasesCompletionHandlers` が見つからないというエラーが発生する。 **原因**: 通常、サンドボックステストに関連する問題です。 **解決策**: 新しいサンドボックスユーザーを作成して再試行してください。これによりサンドボックス関連の購入完了ハンドラーの問題が解決されることがほとんどです。 ## その他の問題 \{#other-issues\} **問題**: 上記に該当しない購入関連の問題が発生している。 **解決策**: 必要に応じて[移行ガイド](android-sdk-migration-guides)を参照し、SDKを最新バージョンに移行してください。多くの問題は新しいSDKバージョンで解決されています。 --- # File: android-identifying-users --- --- title: "Android SDKでユーザーを識別する" description: "Adaptyでユーザーを識別して、パーソナライズされたサブスクリプション体験を向上させます(Android)。" --- Adaptyはすべてのユーザーに対して内部プロファイルIDを作成します。ただし、独自の認証システムがある場合は、独自のCustomer User IDを設定する必要があります。[Profiles](profiles-crm)セクションでCustomer User IDによってユーザーを検索したり、すべてのインテグレーションに送信される[サーバーサイドAPI](getting-started-with-server-side-api)で使用したりできます。 ### 設定時にCustomer User IDを設定する \{#setting-customer-user-id-on-configuration\} 設定時にユーザーIDが存在する場合は、`.activate()`メソッドの`customerUserId`パラメータとして渡すだけです: ```kotlin showLineNumbers Adapty.activate(applicationContext, "PUBLIC_SDK_KEY", customerUserId = "YOUR_USER_ID") ``` :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: ### 設定後にCustomer User IDを設定する \{#setting-customer-user-id-after-configuration\} SDK設定時にユーザーIDがない場合は、`.identify()`メソッドを使っていつでも後から設定できます。このメソッドを使う最も一般的なケースは、ユーザーが匿名ユーザーから認証済みユーザーに切り替わる登録後や認証後です。 ```kotlin showLineNumbers Adapty.identify("YOUR_USER_ID") { error -> if (error == null) { // successful identify } } ``` ```java showLineNumbers Adapty.identify("YOUR_USER_ID", error -> { if (error == null) { // successful identify } }); ``` リクエストパラメータ: - **Customer User ID**(必須):文字列のユーザー識別子。 :::warning 重要なユーザーデータの再送信 ユーザーが再度アカウントにログインする場合など、Adaptyのサーバーにそのユーザーの情報がすでに存在するケースがあります。このような場合、Adapty SDKは自動的に新しいユーザーとして切り替えて動作します。カスタム属性やサードパーティネットワークからのアトリビューションなど、匿名ユーザーに渡したデータがある場合は、識別済みユーザーに対してそのデータを再送信する必要があります。 また、新しいユーザーのデータが異なる場合があるため、ユーザーを識別した後はすべてのペイウォールとプロダクトを再取得する必要がある点にも注意してください。 ::: ### ログアウトとログイン \{#logging-out-and-logging-in\} `.logout()`メソッドを呼び出すことで、いつでもユーザーをログアウトできます: ```kotlin showLineNumbers Adapty.logout { error -> if (error == null) { // successful logout } } ``` ```java showLineNumbers Adapty.logout(error -> { if (error == null) { // successful logout } }); ``` その後、`.identify()`メソッドを使ってユーザーをログインできます。 ### デバイスをまたいでユーザーを検出する \{#detect-users-across-devices\} --- no_index: true --- SDKが有効化されると、StoreKit(iOS)またはGoogle Play Billing(Android)からユーザーの既存のエンタイトルメントを自動的に読み取り、Adaptyバックエンドと同期します。有効なサブスクリプションは、アプリが`restorePurchases`を呼び出すことなく、Adaptyプロファイルに表示されます。 **自動では行われない**のは、新しいデバイスのプロファイルが元のデバイスと同じユーザーのものであることの認識です。AdaptyはCustomer User IDでプロファイルを照合するため、同一性の継続性はCUIDとして何を使用するかによって異なります。 **デバイス間でAdaptyが検出できること** | あなたの設定 | Adaptyが検出すること | 必要な対応 | | --- | --- | --- | | Customer User ID = `device_id`(アプリのログインなし) | 新しいデバイスは異なるCUIDを取得するため、異なるプロファイルが作成されます。サブスクリプションは**Access level updated**イベントを通じて新しいプロファイルに同期されますが、`subscription_started`は発火しません。新しいプロファイルは元の購入の継承者として扱われます。`subscription_started`に基づくアナリティクスは、リターニングユーザーをカウント不足します。 | リターニングユーザーが既存のプロファイルをデバイス間で照合できるよう、安定したアカウントIDをCustomer User IDとして使用してください。 | | Customer User ID = 安定したアカウントID(すべてのデバイスでログイン) | SDKは`activate()`でサブスクリプションを自動同期し、`identify()`がCUIDで既存のプロファイルを照合します。 | 追加の設定は不要です。IDとサブスクリプションの両方が自動的に解決されます。 | | Apple Family Sharing の継承者 | ファミリーメンバーは**Access level updated**イベントのみを通じてサブスクリプションを受け取ります。`subscription_started`は発火しません。 | **Access level updated**をリッスンしてください。完全なイベントマトリクスは[Apple Family Sharing](apple-family-sharing)を参照してください。 | | 同じApple/Googleアカウント、異なるアプリ内ユーザー | 最初に購入を記録したプロファイルが親になります。その後のプロファイルは継承者チェーンを通じてサブスクリプションを確認し、**Access level updated**イベントが1回発生します。 | ログインを必須にし、あなたのモデルに合った[共有モード](sharing-paid-access-between-user-accounts)を選択してください。 | **新しいデバイスでの購入の復元** ペイウォールにユーザーが操作できる「購入を復元」ボタンを設置してください。Apple App Review(ガイドライン3.1.1)で必須とされており、自動同期がエッジケースを見逃した場合のフォールバックとして機能します。このボタンはSDKの`restorePurchases`を呼び出す必要があります。 初回起動時にプログラムで`restorePurchases`を呼び出すことは、通常の使用では必要ありません。SDKはすでに`activate()`で同等の処理を実行しています。プログラムによる呼び出しは、`activate()`完了後にアクセスが欠落している場合のデバッグなど、強制的に新しいレシートチェックを行う場合にのみ使用してください。 --- # File: android-setting-user-attributes --- --- title: "Android SDKでユーザー属性を設定する" description: "Adaptyでユーザー属性を設定してオーディエンスのセグメンテーションを改善する方法を学びます。" --- メールアドレスや電話番号などのオプション属性をアプリのユーザーに設定できます。設定した属性を使って、ユーザーの[セグメント](segments)を作成したり、CRMで確認したりすることができます。 ### ユーザー属性の設定 \{#setting-user-attributes\} ユーザー属性を設定するには、`.updateProfile()` メソッドを呼び出します。 ```kotlin showLineNumbers val builder = AdaptyProfileParameters.Builder() .withEmail("email@email.com") .withPhoneNumber("+18888888888") .withFirstName("John") .withLastName("Appleseed") .withGender(AdaptyProfile.Gender.OTHER) .withBirthday(AdaptyProfile.Date(1970, 1, 3)) Adapty.updateProfile(builder.build()) { error -> if (error != null) { // handle the error } } ``` ```java showLineNumbers AdaptyProfileParameters.Builder builder = new AdaptyProfileParameters.Builder() .withEmail("email@email.com") .withPhoneNumber("+18888888888") .withFirstName("John") .withLastName("Appleseed") .withGender(AdaptyProfile.Gender.OTHER) .withBirthday(new AdaptyProfile.Date(1970, 1, 3)); Adapty.updateProfile(builder.build(), error -> { if (error != null) { // handle the error } }); ``` `updateProfile` メソッドで以前に設定した属性はリセットされませんのでご注意ください。 :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: ### 使用可能なキーの一覧 \{#the-allowed-keys-list\} `AdaptyProfileParameters.Builder` で使用できるキー `` と値 `` の一覧は以下のとおりです。 | キー | 値 | |---|-----| |

email

phoneNumber

firstName

lastName

| String | | gender | Enum。使用可能な値: `female`、`male`、`other` | | birthday | Date | ### カスタムユーザー属性 \{#custom-user-attributes\} 独自のカスタム属性を設定することもできます。カスタム属性は通常、アプリの使用状況に関連するものです。たとえば、フィットネスアプリなら週あたりの運動回数、語学学習アプリならユーザーの習熟度レベルなどが挙げられます。セグメントで活用してターゲットを絞ったペイウォールやオファーを作成したり、アナリティクスでどのプロダクト指標が収益に最も影響するかを把握したりすることができます。 ```kotlin showLineNumbers builder.withCustomAttribute("key1", "value1") ``` ```java showLineNumbers builder.withCustomAttribute("key1", "value1"); ``` 既存のキーを削除するには、`.withRemoved(customAttributeForKey:)` メソッドを使用します。 ```kotlin showLineNumbers builder.withRemovedCustomAttribute("key2") ``` ```java showLineNumbers builder.withRemovedCustomAttribute("key2"); ``` これまでに設定されたカスタム属性を確認したい場合は、`AdaptyProfile` オブジェクトの `customAttributes` フィールドを使用してください。 :::warning ユーザー属性は異なるデバイスからいつでも送信される可能性があるため、`customAttributes` の値は最新の状態ではない場合があります。最後の同期後にサーバー上の属性が更新されている可能性があります。 ::: ### 制限事項 \{#limits\} - ユーザーごとに最大30件のカスタム属性を設定可能 - キー名は最大30文字。キー名には英数字と以下の記号が使用可能: `_` `-` `.` - 値は文字列またはfloatで、最大50文字まで。 --- # File: android-listen-subscription-changes --- --- title: "Android SDKでサブスクリプションステータスを確認する" description: "Adaptyを使用してAndroidアプリのユーザーサブスクリプションステータスを追跡・管理し、顧客維持率を向上させましょう。" --- Adaptyを使えば、サブスクリプションのステータス管理が簡単になります。プロダクトIDをコードに直接記述する必要はありません。アクティブな[アクセスレベル](access-level)を確認するだけで、ユーザーのサブスクリプションステータスを手軽に把握できます。 サブスクリプションステータスの確認を始める前に、[リアルタイム デベロッパー通知(RTDN)](enable-real-time-developer-notifications-rtdn)を設定してください。 ## アクセスレベルとAdaptyProfileオブジェクト \{#access-level-and-the-adaptyprofile-object\} アクセスレベルは[AdaptyProfile](https://android.adapty.io/adapty/com.adapty.models/-adapty-profile/)オブジェクトのプロパティです。アプリ起動時(例:[ユーザーを識別する](android-identifying-users#setting-customer-user-id-on-configuration)タイミングなど)にプロファイルを取得し、変更があるたびに更新することをおすすめします。こうすることで、毎回リクエストを送らずともプロファイルオブジェクトを活用できます。 プロファイルの更新通知を受け取るには、以下の[プロファイル更新(アクセスレベルを含む)をリッスンする](android-listen-subscription-changes)セクションで説明している方法でプロファイルの変更を監視してください。 :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: ## サーバーからアクセスレベルを取得する \{#retrieving-the-access-level-from-the-server\} サーバーからアクセスレベルを取得するには、`.getProfile()`メソッドを使用します: ```kotlin showLineNumbers Adapty.getProfile { result -> when (result) { is AdaptyResult.Success -> { val profile = result.value // check the access } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` ```java showLineNumbers Adapty.getProfile(result -> { if (result instanceof AdaptyResult.Success) { AdaptyProfile profile = ((AdaptyResult.Success) result).getValue(); // check the access } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // handle the error } }); ``` レスポンスパラメーター: | パラメーター | 説明 | | --------- | ------------------------------------------------------------ | | Profile |

[AdaptyProfile](https://android.adapty.io/adapty/com.adapty.models/-adapty-profile/)オブジェクト。通常、ユーザーがプレミアムアクセスを持っているかどうかを判断するには、プロファイルのアクセスレベルのステータスを確認するだけで十分です。

`.getProfile`メソッドは常にAPIへのクエリを試みるため、最新の結果を返します。何らかの理由(例:インターネット接続なし)でAdapty SDKがサーバーから情報を取得できない場合、キャッシュのデータが返されます。なお、Adapty SDKは`AdaptyProfile`のキャッシュを定期的に更新し、情報をできる限り最新の状態に保ちます。

| `.getProfile()`メソッドはユーザープロファイルを返し、そこからアクセスレベルのステータスを取得できます。アプリごとに複数のアクセスレベルを設定することが可能です。たとえばニュースアプリで異なるトピックへのサブスクリプションを個別に販売する場合、「sports」や「science」といったアクセスレベルを作成できます。ただし、ほとんどの場合は1つのアクセスレベルで十分であり、その場合はデフォルトの「premium」アクセスレベルを使用するだけで問題ありません。 デフォルトの「premium」アクセスレベルを確認する例: ```kotlin showLineNumbers Adapty.getProfile { result -> when (result) { is AdaptyResult.Success -> { val profile = result.value if (profile.accessLevels["premium"]?.isActive == true) { // grant access to premium features } } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` ```java showLineNumbers Adapty.getProfile(result -> { if (result instanceof AdaptyResult.Success) { AdaptyProfile profile = ((AdaptyResult.Success) result).getValue(); AdaptyProfile.AccessLevel premium = profile.getAccessLevels().get("premium"); if (premium != null && premium.isActive()) { // grant access to premium features } } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // handle the error } }); ``` ### サブスクリプションステータスの更新をリッスンする \{#listening-for-subscription-status-updates\} ユーザーのサブスクリプションが変更されるたびに、Adaptyはイベントを発火します。 Adaptyからメッセージを受け取るには、追加の設定が必要です: ```kotlin showLineNumbers Adapty.setOnProfileUpdatedListener { profile -> // handle any changes to subscription state } ``` ```java showLineNumbers t Adapty.setOnProfileUpdatedListener(profile -> { // handle any changes to subscription state }); ``` Adaptyはアプリケーション起動時にもイベントを発火します。この場合、キャッシュされたサブスクリプションステータスが渡されます。 ### サブスクリプションステータスのキャッシュ \{#subscription-status-cache\} Adapty SDKに実装されているキャッシュは、プロファイルのサブスクリプションステータスを保存します。そのため、サーバーが利用できない状況でも、キャッシュされたデータからプロファイルのサブスクリプションステータスを取得できます。 ただし、キャッシュから直接データをリクエストすることはできません。SDKは1分ごとにサーバーへクエリを送り、プロファイルに関する更新や変更を確認します。新しいトランザクションやその他の更新があった場合、それらはサーバーとの同期を保つためにキャッシュデータへ反映されます。 --- # File: kids-mode-android --- --- title: "Android SDKのキッズモード" description: "キッズモードを簡単に有効化してGoogleのポリシーに準拠。Android SDKではGAIDや広告データは収集されません。" --- Androidアプリが子ども向けの場合、[Google](https://support.google.com/googleplay/android-developer/answer/9893335)のポリシーに従う必要があります。Adapty SDKを使用している場合、いくつかの簡単な手順でこれらのポリシーに準拠し、アプリストアの審査を通過できるよう設定できます。 ## 必要な対応 \{#whats-required\} Adapty SDKで以下の収集を無効化する必要があります: - [Android広告ID(AAID/GAID)](https://support.google.com/googleplay/android-developer/answer/6048248) - [IPアドレス](https://www.ftc.gov/system/files/ftc_gov/pdf/p235402_coppa_application.pdf) また、カスタマーユーザーIDの扱いにも注意が必要です。``形式のユーザーIDは、メールアドレスと同様に個人情報の収集とみなされる可能性があります。キッズモードでは、ランダム化または匿名化された識別子(ハッシュIDやデバイス生成のUUIDなど)を使用することがベストプラクティスです。 ## キッズモードの有効化 \{#enabling-kids-mode\} ### Adapty ダッシュボードでの設定 \{#updates-in-the-adapty-dashboard\} Adapty ダッシュボードでは、IPアドレスの収集を無効化する必要があります。[App settings](https://app.adapty.io/settings/general)に移動し、**Collect users' IP address**の下にある**Disable IP address collection**をクリックしてください。 ### モバイルアプリのコードでの設定 \{#updates-in-your-mobile-app-code\} ポリシーに準拠するため、Adapty SDKの初期化時にAndroid広告ID(AAID/GAID)とIPアドレスの収集を無効化する必要があります: **Kotlin:** ```kotlin showLineNumbers override fun onCreate() { super.onCreate() Adapty.activate( applicationContext, AdaptyConfig.Builder("PUBLIC_SDK_KEY") // highlight-start .withAdIdCollectionDisabled(true) // set to `true` .withIpAddressCollectionDisabled(true) // set to `true` // highlight-end .build() ) } ``` **Java:** ```java showLineNumbers @Override public void onCreate() { super.onCreate(); Adapty.activate( applicationContext, new AdaptyConfig.Builder("PUBLIC_SDK_KEY") // highlight-start .withAdIdCollectionDisabled(true) // set to `true` .withIpAddressCollectionDisabled(true) // set to `true` // highlight-end .build() ); } ``` ### Androidマニフェストでの設定 \{#updates-in-your-android-manifest\} :::note アプリが子ども**専用**であり、Android 13(API 33)以上をターゲットとしてコンパイルしている場合、Google Playでは`AD_ID`パーミッションをリクエストしないことが求められます。分析、アトリビューション、または広告向けの別のSDKがマニフェストのマージを通じてこのパーミッションを追加している場合があります。`withAdIdCollectionDisabled(true)`を設定するとAdaptyによるIDの収集は停止しますが、他のSDKが宣言したパーミッションは削除されません。 ::: パーミッションを削除するには、`app/src/main/AndroidManifest.xml`の``要素内に以下を追加してください。``要素では`xmlns:tools="http://schemas.android.com/tools"`を宣言する必要があります。 ```xml showLineNumbers title="AndroidManifest.xml" ``` --- # File: android-get-onboardings --- --- title: "Android SDKでオンボーディングを取得する" description: "AdaptyのAndroid向けオンボーディング取得方法について説明します。" --- Adapty ダッシュボードのビルダーで[オンボーディングのビジュアル部分をデザイン](design-onboarding)したら、Androidアプリに表示できます。まず最初に、プレースメントに紐付いたオンボーディングとそのビュー設定を取得する必要があります。詳しくは以下をご覧ください。 始める前に、以下を確認してください: 1. [Adapty Android SDK](sdk-installation-android) バージョン 3.8.0 以上がインストールされていること。 2. [オンボーディングを作成済み](create-onboarding)であること。 3. オンボーディングを[プレースメント](placements)に追加済みであること。 ## オンボーディングの取得 \{#fetch-onboarding\} ノーコードビルダーで[オンボーディング](onboardings)を作成すると、アプリが取得・表示する必要のある設定を含むコンテナとして保存されます。このコンテナは、表示するコンテンツ・見せ方・ユーザーの操作(クイズの回答やフォーム入力など)の処理まで、すべてのエクスペリエンスを管理します。また、コンテナはアナリティクスイベントを自動的に追跡するため、別途ビュートラッキングを実装する必要はありません。 パフォーマンスを最大限に発揮させるため、ユーザーに表示する前に画像のダウンロードが完了するよう、早めにオンボーディングの設定を取得してください。 オンボーディングを取得するには、`getOnboarding` メソッドを使用します: ```kotlin showLineNumbers Adapty.getOnboarding("YOUR_PLACEMENT_ID") { result -> when (result) { is AdaptyResult.Success -> { val onboarding = result.value // the requested onboarding } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` パラメーター: | パラメーター | 必須/任意 | 説明 | |---------|--------|------| | **placementId** | 必須 | 対象の[プレースメント](placements)の識別子です。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** |

任意

デフォルト:`en`

|

オンボーディングのローカライズ識別子です。マイナス(**-**)文字で区切られた1つまたは2つのサブタグで構成される言語コードを指定してください。最初のサブタグは言語、2番目のサブタグは地域を示します。

例:`en` は英語、`pt-br` はブラジルポルトガル語を表します。

ロケールコードの詳細と推奨される使い方については、[ローカライズとロケールコード](localizations-and-locale-codes)をご覧ください。

| | **fetchPolicy** | デフォルト:`.reloadRevalidatingCacheData` |

デフォルトでは、SDKはサーバーからデータを読み込もうとし、失敗した場合はキャッシュデータを返します。ユーザーに常に最新のデータを提供できるため、このオプションを推奨します。

ただし、ユーザーのインターネット接続が不安定だと思われる場合は、`.returnCacheDataElseLoad` を使用してキャッシュデータが存在すればそれを返すことを検討してください。この場合、最新のデータが取得できないことがありますが、接続状態に関わらず読み込みが速くなります。キャッシュは定期的に更新されるため、セッション中にネットワークリクエストを避けて使用しても安全です。

キャッシュはアプリを再起動しても消えず、アプリを再インストールするか手動でクリアした場合のみ削除されます。

Adapty SDK はオンボーディングをローカルに2つの層で保存しています。上記で説明した定期更新キャッシュとフォールバックオンボーディングです。また、オンボーディングの取得を高速化するためにCDNを使用し、CDNに接続できない場合に備えた独立したフォールバックサーバーも用意しています。このシステムは、インターネット接続が不安定な場合でも、常に最新のオンボーディングを確実に取得できるよう設計されています。

| | **loadTimeout** | デフォルト:5秒 |

このメソッドのタイムアウト上限です。タイムアウトに達した場合、キャッシュデータまたはローカルフォールバックが返されます。

なお、このメソッドは内部で複数のリクエストが発生する場合があるため、`loadTimeout` で指定した時間よりわずかに遅れてタイムアウトすることがあります。

Android の場合:拡張関数(例:`5.seconds`、`.seconds` は `import com.adapty.utils.seconds` から)を使って `TimeInterval` を作成するか、`TimeInterval.seconds(5)` を使用できます。制限を設けない場合は `TimeInterval.INFINITE` を指定してください。

| レスポンスパラメーター: | パラメーター | 説明 | |:----------|:-----| | Onboarding | オンボーディングの識別子と設定、リモートコンフィグ、その他いくつかのプロパティを含む [`AdaptyOnboarding`](https://android.adapty.io/adapty/com.adapty.models/-adapty-onboarding/) オブジェクトです。 | ## デフォルトオーディエンスのオンボーディングで取得を高速化する \{#speed-up-onboarding-fetching-with-default-audience-onboarding\} 通常、オンボーディングはほぼ即座に取得されるため、この処理の高速化を気にする必要はありません。ただし、オーディエンスやオンボーディングが多数あり、ユーザーのインターネット接続が遅い場合、オンボーディングの取得に予想より時間がかかることがあります。そのような状況では、オンボーディングをまったく表示しないよりも、デフォルトのオンボーディングを表示してスムーズなユーザー体験を提供したい場合があります。 この問題に対応するため、`getOnboardingForDefaultAudience` メソッドを使用できます。このメソッドは、指定されたプレースメントの **All Users** オーディエンス向けオンボーディングを取得します。ただし、推奨される方法は上記の[オンボーディングの取得](#fetch-onboarding)セクションで説明した `getOnboarding` メソッドを使用することです。 :::warning `getOnboardingForDefaultAudience` の代わりに `getOnboarding` の使用を検討してください。前者には以下の重要な制限があります: - **互換性の問題**:複数のアプリバージョンをサポートする際に問題が生じる可能性があり、後方互換性のあるデザインが必要になるか、古いバージョンで正しく表示されないことを受け入れる必要があります。 - **パーソナライズなし**:"All Users" オーディエンス向けのコンテンツのみ表示され、国・アトリビューション・カスタム属性によるターゲティングが機能しません。 高速な取得がこれらのデメリットを上回る場合は、以下に示すように `getOnboardingForDefaultAudience` を使用してください。それ以外の場合は、[上記](#fetch-onboarding)で説明した `getOnboarding` を使用してください。 ::: ```kotlin Adapty.getOnboardingForDefaultAudience("YOUR_PLACEMENT_ID") { result -> when (result) { is AdaptyResult.Success -> { val onboarding = result.value // Handle successful onboarding retrieval } is AdaptyResult.Error -> { val error = result.error // Handle error case } } } ``` パラメーター: | パラメーター | 必須/任意 | 説明 | |---------|--------|------| | **placementId** | 必須 | 対象の[プレースメント](placements)の識別子です。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** |

任意

デフォルト:`en`

|

オンボーディングのローカライズ識別子です。マイナス(**-**)文字で区切られた1つまたは2つのサブタグで構成される言語コードを指定してください。最初のサブタグは言語、2番目のサブタグは地域を示します。

例:`en` は英語、`pt-br` はブラジルポルトガル語を表します。

ロケールコードの詳細と推奨される使い方については、[ローカライズとロケールコード](localizations-and-locale-codes)をご覧ください。

| | **fetchPolicy** | デフォルト:`.reloadRevalidatingCacheData` |

デフォルトでは、SDKはサーバーからデータを読み込もうとし、失敗した場合はキャッシュデータを返します。ユーザーに常に最新のデータを提供できるため、このオプションを推奨します。

ただし、ユーザーのインターネット接続が不安定だと思われる場合は、`.returnCacheDataElseLoad` を使用してキャッシュデータが存在すればそれを返すことを検討してください。この場合、最新のデータが取得できないことがありますが、接続状態に関わらず読み込みが速くなります。キャッシュは定期的に更新されるため、セッション中にネットワークリクエストを避けて使用しても安全です。

キャッシュはアプリを再起動しても消えず、アプリを再インストールするか手動でクリアした場合のみ削除されます。

Adapty SDK はオンボーディングをローカルに2つの層で保存しています。上記で説明した定期更新キャッシュとフォールバックオンボーディングです。また、オンボーディングの取得を高速化するためにCDNを使用し、CDNに接続できない場合に備えた独立したフォールバックサーバーも用意しています。このシステムは、インターネット接続が不安定な場合でも、常に最新のオンボーディングを確実に取得できるよう設計されています。

| --- # File: android-present-onboardings --- --- title: "Android SDKでオンボーディングを表示する" description: "Androidでオンボーディングを表示して、効果的なユーザーエンゲージメントを実現する方法を学びましょう。" --- 始める前に、以下を確認してください: 1. [Adapty Android SDK](sdk-installation-android) 3.8.0 以降をインストール済みであること。 2. [オンボーディングを作成済み](create-onboarding)であること。 3. オンボーディングを[プレースメント](placements)に追加済みであること。 オンボーディングビルダーを使ってオンボーディングをカスタマイズした場合、モバイルアプリのコードでレンダリングについて心配する必要はありません。そのようなオンボーディングには、表示内容と表示方法の両方が含まれています。 デバイス画面にビジュアルオンボーディングを表示するには、まず設定が必要です。`AdaptyUI.getOnboardingView()` メソッドを呼び出すか、`OnboardingView` を直接作成してください: ```kotlin val onboardingView = AdaptyUI.getOnboardingView( activity = this, viewConfig = onboardingConfig, eventListener = eventListener ) ``` ```kotlin val onboardingView = AdaptyOnboardingView(activity) onboardingView.show( viewConfig = onboardingConfig, delegate = eventListener ) ``` ```java AdaptyOnboardingView onboardingView = AdaptyUI.getOnboardingView( activity, onboardingConfig, eventListener ); ``` ```java AdaptyOnboardingView onboardingView = new AdaptyOnboardingView(activity); onboardingView.show(onboardingConfig, eventListener); ``` ```xml ``` ビューが正常に作成されたら、ビュー階層に追加してデバイス画面に表示できます。 リクエストパラメータ: | パラメータ | 必須 | 説明 | | :-------- | :------- |:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **viewConfig** | 必須 | `AdaptyUI.getOnboardingConfiguration()` から取得したオンボーディング設定 | | **eventListener** | 必須 | オンボーディングイベントを処理する `AdaptyOnboardingEventListener` の実装。詳細は[オンボーディングイベントの処理](android-handle-onboarding-events)を参照してください。 | ## ローディングインジケーターの色を変更する \{#change-loading-indicator-color\} 以下の方法でローディングインジケーターのデフォルトカラーをオーバーライドできます: ```xml ``` ## スプラッシュ画面とオンボーディング間のスムーズなトランジションを追加する \{#add-smooth-transitions-between-the-splash-screen-and-onboarding\} デフォルトでは、スプラッシュ画面とオンボーディングの間に、オンボーディングが完全に読み込まれるまでローディング画面が表示されます。ただし、トランジションをよりスムーズにしたい場合は、スプラッシュ画面を延長するか別のものを表示するようにカスタマイズできます。 これを行うには、`res/layout` に `adapty_onboarding_placeholder_view.xml` を作成し、そこでプレースホルダー(オンボーディングの読み込み中に表示する内容)を定義してください。 プレースホルダーを定義すると、オンボーディングはバックグラウンドで読み込まれ、準備が整い次第自動的に表示されます。 ## セーフエリアのパディングを無効にする \{#disable-safe-area-paddings\} デフォルトでは、オンボーディングビューはステータスバーやナビゲーションバーなどのシステムUI要素を避けるために、セーフエリアのパディングを自動的に適用します。ただし、この動作を無効にしてレイアウトを完全に制御したい場合は、`safeAreaPaddings` パラメータを `false` に設定することで対応できます。 ```kotlin val onboardingView = AdaptyUI.getOnboardingView( activity = this, viewConfig = onboardingConfig, eventListener = eventListener, safeAreaPaddings = false ) ``` ```kotlin val onboardingView = AdaptyOnboardingView(activity) onboardingView.show( viewConfig = onboardingConfig, delegate = eventListener, safeAreaPaddings = false ) ``` ```java AdaptyOnboardingView onboardingView = AdaptyUI.getOnboardingView( activity, onboardingConfig, eventListener, false ); ``` ```java AdaptyOnboardingView onboardingView = new AdaptyOnboardingView(activity); onboardingView.show(onboardingConfig, eventListener, false); ``` あるいは、アプリにブールリソースを追加することで、この動作をグローバルに制御することもできます: ```xml false ``` `safeAreaPaddings` を `false` に設定すると、オンボーディングは自動的なパディング調整なしにフルスクリーンに拡張され、レイアウトを完全に制御できるようになり、オンボーディングコンテンツが画面全体のスペースを使用できるようになります。 ## オンボーディングでのリンクの開き方をカスタマイズする \{#customize-how-links-open-in-onboardings\} :::important オンボーディングでのリンクの開き方のカスタマイズは、Adapty SDK v3.15.1 以降でサポートされています。 ::: デフォルトでは、オンボーディング内のリンクはアプリ内ブラウザで開きます。これにより、アプリを切り替えることなくアプリ内でウェブページを表示できるため、シームレスなユーザー体験が提供されます。 代わりに外部ブラウザでリンクを開きたい場合は、`externalUrlsPresentation` パラメータを `AdaptyWebPresentation.ExternalBrowser` に設定することでこの動作をカスタマイズできます: ```kotlin val onboardingConfig = AdaptyUI.getOnboardingConfiguration( onboarding = onboarding, externalUrlsPresentation = AdaptyWebPresentation.ExternalBrowser // default – InAppBrowser ) ``` ```java AdaptyOnboardingConfiguration onboardingConfig = AdaptyUI.getOnboardingConfiguration( onboarding, AdaptyWebPresentation.ExternalBrowser // default – InAppBrowser ); ``` --- # File: android-handle-onboarding-events --- --- title: "Android SDKでオンボーディングイベントを処理する" description: "Adaptyを使用してAndroidでオンボーディング関連のイベントを処理します。" --- 始める前に、以下を確認してください: 1. [Adapty Android SDK](sdk-installation-android) 3.8.0 以降をインストール済みであること。 2. [オンボーディングを作成](create-onboarding)済みであること。 3. オンボーディングを[プレースメント](placements)に追加済みであること。 ビルダーで設定されたオンボーディングは、アプリが応答できるイベントを生成します。それらのイベントへの対応方法を以下で説明します。 Android アプリ内のオンボーディング画面で発生するプロセスを制御・監視するには、`AdaptyOnboardingEventListener` インターフェースを実装してください。 ## カスタムアクション \{#custom-actions\} ビルダーでは、ボタンに**カスタム**アクションを追加してIDを割り当てることができます。このIDをコード内で使用して、カスタムアクションとして処理できます。 たとえば、ユーザーが**ログイン**や**通知を許可**などのカスタムボタンをタップすると、デリゲートメソッド `onCustomAction` がビルダーのアクションIDとともに呼び出されます。"allowNotifications" のような独自のIDを作成できます。 ```kotlin showLineNumbers class YourActivity : AppCompatActivity() { private val eventListener = object : AdaptyOnboardingEventListener { override fun onCustomAction(action: AdaptyOnboardingCustomAction, context: Context) { when (action.actionId) { "allowNotifications" -> { // Request notification permissions } } } override fun onError(error: AdaptyOnboardingError, context: Context) { // Handle errors } // ... other required delegate methods } } ```
イベント例(クリックして展開) ```json { "actionId": "allowNotifications", "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 0, "screensTotal": 3 } } ```
## オンボーディングを閉じる \{#closing-onboarding\} オンボーディングは、ユーザーが**閉じる**アクションが割り当てられたボタンをタップすると、閉じられたとみなされます。ユーザーがオンボーディングを閉じたときの動作を管理する必要があります。例: :::important ユーザーがオンボーディングを閉じたときの動作を管理する必要があります。たとえば、オンボーディング自体の表示を停止する処理が必要です。 ::: 例: ```kotlin override fun onCloseAction(action: AdaptyOnboardingCloseAction, context: Context) { // Dismiss the onboarding screen (context as? Activity)?.onBackPressed() } ```
イベント例(クリックして展開) ```json { "action_id": "close_button", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "final_screen", "screen_index": 3, "total_screens": 4 } } ```
## ペイウォールを開く \{#opening-a-paywall\} :::tip オンボーディング内でペイウォールを開きたい場合は、このイベントを処理してください。オンボーディングが閉じた後にペイウォールを開きたい場合は、[`AdaptyOnboardingCloseAction`](#closing-onboarding) を処理して、イベントデータに依存せずにペイウォールを開く方がシンプルです。 ::: オンボーディング内でペイウォールをシームレスに扱う最善の方法は、アクションIDをペイウォールのプレースメントIDと同じにすることです。こうすることで、`AdaptyOnboardingOpenPaywallAction` の後にプレースメントIDを使ってすぐにペイウォールを取得・表示できます: ```kotlin override fun onOpenPaywallAction(action: AdaptyOnboardingOpenPaywallAction, context: Context) { // Get the paywall using the placement ID from the action Adapty.getPaywall(placementId = action.actionId) { result -> when (result) { is AdaptyResult.Success -> { val paywall = result.value // Get the paywall configuration AdaptyUI.getViewConfiguration(paywall) { result -> when(result) { is AdaptyResult.Success -> { val paywallConfig = result.value // Create and present the paywall val paywallView = AdaptyUI.getPaywallView( activity = this, viewConfig = paywallConfig, products, eventListener = paywallEventListener ) // Add the paywall view to your layout binding.container.addView(paywallView) } is AdaptyResult.Error -> { val error = result.error // handle the error } } } is AdaptyResult.Error -> { val error = result.error // handle the error } } } } ```
イベント例(クリックして展開) ```json { "action_id": "premium_offer_1", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "pricing_screen", "screen_index": 2, "total_screens": 4 } } ```
## オンボーディングの読み込み完了 \{#finishing-loading-onboarding\} オンボーディングの読み込みが完了すると、このメソッドが呼び出されます: ```kotlin override fun onFinishLoading(action: AdaptyOnboardingLoadedAction, context: Context) { // Handle loading completion } ```
イベント例(クリックして展開) ```json { "meta": { "onboarding_id": "onboarding_123", "screen_cid": "welcome_screen", "screen_index": 0, "total_screens": 4 } } ```
## ナビゲーションイベント \{#navigation-events\} `onAnalyticsEvent` メソッドは、オンボーディングフロー中にさまざまなアナリティクスイベントが発生したときに呼び出されます。 `event` オブジェクトは以下のいずれかの型になります: | 型 | 説明 | |------------|-------------| | `OnboardingStarted` | オンボーディングが読み込まれたとき | | `ScreenPresented` | 任意の画面が表示されたとき | | `ScreenCompleted` | 画面が完了したとき。オプションの `elementId`(完了した要素の識別子)とオプションの `reply`(ユーザーからの返答)を含みます。ユーザーが画面を離れる操作を行ったときに発火します。 | | `SecondScreenPresented` | 2番目の画面が表示されたとき | | `UserEmailCollected` | 入力フィールドでユーザーのメールアドレスが収集されたとき | | `OnboardingCompleted` | ユーザーが `final` IDを持つ画面に到達したときに発火します。このイベントが必要な場合は、最後の画面に `final` IDを割り当ててください。 | | `Unknown` | 認識できないイベントタイプの場合。`name`(不明なイベントの名前)と `meta`(追加のメタデータ)を含みます。 | 各イベントには以下の `meta` 情報が含まれます: | フィールド | 説明 | |------------|-------------| | `onboardingId` | オンボーディングフローの一意の識別子 | | `screenClientId` | 現在の画面の識別子 | | `screenIndex` | フロー内での現在の画面の位置 | | `totalScreens` | フロー内の画面の総数 | アナリティクスイベントをトラッキングに使用する例: ```kotlin override fun onAnalyticsEvent(event: AdaptyOnboardingAnalyticsEvent, context: Context) { when (event) { is AdaptyOnboardingAnalyticsEvent.OnboardingStarted -> { // Track onboarding start trackEvent("onboarding_started", event.meta) } is AdaptyOnboardingAnalyticsEvent.ScreenPresented -> { // Track screen presentation trackEvent("screen_presented", event.meta) } is AdaptyOnboardingAnalyticsEvent.ScreenCompleted -> { // Track screen completion with user response trackEvent("screen_completed", event.meta, event.elementId, event.reply) } is AdaptyOnboardingAnalyticsEvent.OnboardingCompleted -> { // Track successful onboarding completion trackEvent("onboarding_completed", event.meta) } is AdaptyOnboardingAnalyticsEvent.Unknown -> { // Handle unknown events trackEvent(event.name, event.meta) } // Handle other cases as needed } } ```
イベント例(クリックして展開) ```javascript // OnboardingStarted { "name": "onboarding_started", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "welcome_screen", "screen_index": 0, "total_screens": 4 } } // ScreenPresented { "name": "screen_presented", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "interests_screen", "screen_index": 2, "total_screens": 4 } } // ScreenCompleted { "name": "screen_completed", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "profile_screen", "screen_index": 1, "total_screens": 4 }, "params": { "element_id": "profile_form", "reply": "success" } } // SecondScreenPresented { "name": "second_screen_presented", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "profile_screen", "screen_index": 1, "total_screens": 4 } } // UserEmailCollected { "name": "user_email_collected", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "profile_screen", "screen_index": 1, "total_screens": 4 } } // OnboardingCompleted { "name": "onboarding_completed", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "final_screen", "screen_index": 3, "total_screens": 4 } } ```
--- # File: android-onboarding-input --- --- title: "Android SDKでオンボーディングのデータを処理する" description: "Adapty SDKを使ってAndroidアプリのオンボーディングデータを保存・活用する方法を説明します。" --- ユーザーがクイズの質問に回答したり、入力フィールドにデータを入力したりすると、`onStateUpdatedAction` メソッドが呼び出されます。コード内でフィールドの種類を保存したり処理したりできます。 例: ```kotlin override fun onStateUpdatedAction(action: AdaptyOnboardingStateUpdatedAction, context: Context) { // Store user preferences or responses when (val params = action.params) { is AdaptyOnboardingStateUpdatedParams.Select -> { // Handle single selection } is AdaptyOnboardingStateUpdatedParams.MultiSelect -> { // Handle multiple selections } is AdaptyOnboardingStateUpdatedParams.Input -> { // Handle text input } is AdaptyOnboardingStateUpdatedParams.DatePicker -> { // Handle date selection } } } ``` アクションのフォーマットは[こちら](https://android.adapty.io/adapty-ui/com.adapty.ui.onboardings.actions/-adapty-onboarding-state-updated-action/)でご確認ください。
保存されたデータの例(実装によってフォーマットが異なる場合があります) ```javascript // Example of a saved select action { "elementId": "preference_selector", "meta": { "onboardingId": "onboarding_123", "screenClientId": "preferences_screen", "screenIndex": 1, "screensTotal": 3 }, "params": { "type": "select", "value": { "id": "option_1", "value": "premium", "label": "Premium Plan" } } } // Example of a saved multi-select action { "elementId": "interests_selector", "meta": { "onboardingId": "onboarding_123", "screenClientId": "interests_screen", "screenIndex": 2, "screensTotal": 3 }, "params": { "type": "multiSelect", "value": [ { "id": "interest_1", "value": "sports", "label": "Sports" }, { "id": "interest_2", "value": "music", "label": "Music" } ] } } // Example of a saved input action { "elementId": "name_input", "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 0, "screensTotal": 3 }, "params": { "type": "input", "value": { "type": "text", "value": "John Doe" } } } // Example of a saved date picker action { "elementId": "birthday_picker", "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 0, "screensTotal": 3 }, "params": { "type": "datePicker", "value": { "day": 15, "month": 6, "year": 1990 } } } ```
## ユースケース \{#use-cases\} ### ユーザープロファイルをデータで充実させる \{#enrich-user-profiles-with-data\} 入力されたデータをユーザープロファイルにすぐ紐付けて、同じ情報を二度聞かないようにするには、アクションを処理するタイミングで入力データを使って[ユーザープロファイルを更新](android-setting-user-attributes)する必要があります。 たとえば、ID が `name` のテキストフィールドに名前を入力してもらい、その値をユーザーの名(first name)として設定したいとします。また、`email` フィールドにメールアドレスを入力してもらう場合、アプリのコードは次のようになります。 ```kotlin showLineNumbers override fun onStateUpdatedAction(action: AdaptyOnboardingStateUpdatedAction, context: Context) { // Store user preferences or responses when (val params = action.params) { is AdaptyOnboardingStateUpdatedParams.Input -> { // Handle text input val builder = AdaptyProfileParameters.Builder() // Map elementId to appropriate profile field when (action.elementId) { "name" -> { when (val inputParams = params.params) { is AdaptyOnboardingInputParams.Text -> { builder.withFirstName(inputParams.value) } } } "email" -> { when (val inputParams = params.params) { is AdaptyOnboardingInputParams.Email -> { builder.withEmail(inputParams.value) } } } } Adapty.updateProfile(builder.build()) { error -> if (error != null) { // handle the error } } } } } ``` ### 回答に基づいてペイウォールをカスタマイズする \{#customize-paywalls-based-on-answers\} オンボーディングのクイズを活用して、オンボーディング完了後にユーザーへ表示するペイウォールをカスタマイズすることもできます。 たとえば、スポーツの経験について質問し、ユーザーグループごとに異なる CTA やプロダクトを表示できます。 1. オンボーディングビルダーで[クイズを追加](onboarding-quizzes)し、各選択肢に意味のある ID を割り当てます。 2. ID に基づいてクイズの回答を処理し、ユーザーに[カスタム属性を設定](android-setting-user-attributes)します。 ```kotlin showLineNumbers override fun onStateUpdatedAction(action: AdaptyOnboardingStateUpdatedAction, context: Context) { // Handle quiz responses and set custom attributes when (val params = action.params) { is AdaptyOnboardingStateUpdatedParams.Select -> { // Handle quiz selection val builder = AdaptyProfileParameters.Builder() // Map quiz responses to custom attributes when (action.elementId) { "experience" -> { // Set custom attribute 'experience' with the selected value (beginner, amateur, pro) builder.withCustomAttribute("experience", params.params.value) } } Adapty.updateProfile(builder.build()) { error -> if (error != null) { // handle the error } } } } } ``` 3. カスタム属性の値ごとに[セグメントを作成](segments)します。 4. [プレースメント](placements)を作成し、作成した各セグメントに対して[オーディエンス](audience)を追加します。 5. アプリのコードでそのプレースメントの[ペイウォールを表示](android-paywalls)します。オンボーディングにペイウォールを開くボタンがある場合は、[そのボタンのアクションへの応答](android-handle-onboarding-events#opening-a-paywall)としてペイウォールのコードを実装してください。 Human --- # File: android-sdk-call-order --- --- title: "Android SDKの呼び出し順序" description: "Adapty SDKのメソッドを正しい順序で呼び出すことで、プレミアムアクセスの喪失、アトリビューションの欠落、断続的なADAPTY_NOT_INITIALIZEDエラーを回避できます。" --- `Adapty.activate()` が完了してから、他のAdapty SDKメソッドを呼び出す必要があります。完了するまでSDKは状態を持ちません。`activate()` の前または並行して発行された呼び出しはすべて [`ADAPTY_NOT_INITIALIZED`](android-sdk-error-handling) で失敗します。 アプリがユーザーを認証し、起動後にカスタマーユーザーIDを取得する場合は、そのタイミングで `Adapty.identify()` を呼び出してください。`identify` の完了コールバックが発火するまで、ユーザー操作に関わるメソッドを呼び出さないようにしてください。`identify` と競合する呼び出しは、コールバックでエラーが返るか、アクティベーション時に作成された匿名プロファイルに対して処理されます。この状態になると、アトリビューション、`appsflyer_id` などのMMP ID、インストールの所有権が識別済みプロファイルに正しく引き継がれないことがあります。アプリがユーザーを認証しない場合は `identify` をスキップし、匿名プロファイルのまま利用を続けてください。 MMP・アナリティクスSDK(AppsFlyer、Adjust、Branch、PostHog)も同じルールに従います。先にそれらを初期化し、UIDコールバックを待ってから `Adapty.activate` を呼び出してください。そうしないと、MMP IDが一時的な匿名プロファイルに紐付けられ、識別済みプロファイルに必ずしも引き継がれません。AppsFlyer固有の詳細については、[AppsFlyer](appsflyer) を参照してください。 ## 正しい順序 \{#the-correct-order\} どのパスをたどるかは、カスタマーユーザーIDをいつ取得するか、そしてMMPやアナリティクスSDKを使用するかどうかによって異なります。 - **ステップ2と5**: すべてのアプリで必須です。SDKをアクティベートしてから、SDKメソッドを呼び出します。 - **ステップ1と3**: MMPまたはアナリティクスSDK(AppsFlyer、Adjust、Branch、PostHog)を連携する場合のみ必要です。 - **ステップ4**: アプリがユーザーを認証し、起動後にカスタマーユーザーIDを収集する場合のみ必要です。 アプリ起動時にカスタマーユーザーIDが取得できる場合は、`activate()` を呼び出す前に(ステップ2a)`AdaptyConfig.Builder` に渡してください。このパスでは匿名プロファイルが作成されないため、ステップ4は不要です。 | ステップ | 呼び出し | タイミング | 備考 | |------|---------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------| | 1 | MMPまたはアナリティクスSDKの初期化(AppsFlyer、Adjust、PostHog、Branch) | アプリ起動時、最初に | MMPのUIDコールバック(例: `getAppsFlyerUID`)を待つこと。 | | 2a | `Adapty.activate(context, AdaptyConfig.Builder("KEY").withCustomerUserId(...).build())` | アプリ起動時、ステップ1の後、カスタマーユーザーIDが取得できる場合 | 推奨。匿名プロファイルは一切作成されない。 | | 2b | `Adapty.activate(context, AdaptyConfig.Builder("KEY").build())` — `customerUserId` なし | アプリ起動時、ステップ1の後、カスタマーユーザーIDが取得できない場合(または取得しない場合) | Adaptyが匿名プロファイルを作成する。 | | 3 | 各MMPに対して `Adapty.setIntegrationIdentifier("appsflyer_id", uid)` | ステップ2の後、ユーザー操作の呼び出しより前 | MMP IDを正しいプロファイルに紐付けるために必要。 | | 4 | `Adapty.identify("YOUR_USER_ID") { error -> ... }` | ステップ3の後(MMPがない場合はステップ2の後)、ステップ5より前 — 認証ありのパス2bのみ | 完了コールバックを使用すること。`identify` 中の並行呼び出しは匿名プロファイルに対して処理される場合がある。 | | 5 | `getPaywall`、`getPaywallProducts`、`restorePurchases`、`makePurchase`、`updateAttribution`、`updateProfile` | `identify` を呼び出す場合はステップ4の後、それ以外はステップ3の後(またはMMPがない場合はステップ2の後) | これらの呼び出しには安定したプロファイルが必要。 | :::important これらのステップをスキップすると、再インストールユーザーのプレミアムアクセスが失われたり、プロファイルに `appsflyer_id` が記録されなかったり、誤ったオーディエンスに対してペイウォールが返されたりする原因となります。 ::: ## Web2appおよびウェブファネル経由のインストール \{#web2app-and-web-funnel-installs\} ユーザーがウェブチェックアウト(Stripe、Paddle)で購入し、後からネイティブアプリをインストールした場合、デバイス初回の `activate()` により新しい匿名プロファイルが作成されます。このプロファイルはウェブプロファイルとは紐付けられません。認証フローやインストールリファラーなどからアプリ起動前にカスタマーユーザーIDを解決できる場合は、`AdaptyConfig.Builder` に直接渡してください。それ以外の場合、`identify("YOUR_USER_ID")` を呼び出して `restorePurchases` を実行するまで、ウェブでの購入はデバイス上に表示されません。 各ウェブチェックアウトで送信するメタデータについては、以下を参照してください。 - [Stripe](stripe) - [Paddle](paddle) --- # File: android-optimize-paywall-fetching --- --- title: "Android SDKでペイウォールの取得を最適化する" description: "Android向けにAdaptyペイウォールを確実に取得する:タイミング、キャッシュ、フォールバックのパターン。" --- Android上での信頼性の高いペイウォール取得は、3つのことを実現します:高速なレンダリング、オーディエンスターゲティングされたペイウォールの返却、そしてネットワークが遅い場合のグレースフルなフォールバック。以下のルールは、これを実現するためのタイミング、キャッシュ、フォールバックのパターンをカバーしています。 :::tip これらのルールは、`Adapty.activate()` と `Adapty.identify()` がすでに完了していることを前提としています。[Android SDKの呼び出し順序](android-sdk-call-order)を参照してください。 ::: ## ルールと注意点 \{#rules-and-pitfalls\} | こうする | こうしない | 理由 | |---|---|---| | これから表示するプレースメントを取得する。 | 起動時にすべてのプレースメントを並列でプリフェッチする。 | 一括プリフェッチはメインスレッドをブロックし、バースト中にブラックスクリーンが表示される。 | | アトリビューションが解決される機会を持った後に `getPaywall` を取得する — たとえば、`activate` の1〜2秒後、または `setOnProfileUpdatedListener` が発火した後。 | `Application.onCreate()` で `getPaywall` を呼び出す。 | アトリビューションがまだ反映されていない。ペイウォールはデフォルトのオーディエンスに対して解決され、セグメントやASAのパーソナライゼーションが暗黙的にスキップされる。 | | `loadTimeout` を設定し、すべてのプレースメントに[フォールバックペイウォール](fallback-paywalls)を設定する。 | `getPaywall` を無期限に待つ。 | タイムアウトがないと、接続が不安定なユーザーはネットワークが解決するまで、またはアプリを閉じるまで空白の画面を見続けることになる。 | `fetchPolicy` と `loadTimeout` パラメーターのリファレンスは[ペイウォールとプロダクトの取得](fetch-paywalls-and-products-android)を、適切なプレースメントの選び方は[プレースメント](placements)を参照してください。 ## 接続が不安定な環境向けのチューニング \{#tune-for-poor-connectivity\} 接続が常に不安定な市場(農村部、交通機関、ルーティングの問題が多い地域)向けには: - 最初の取得を除くすべての取得で、`fetchPolicy` を `AdaptyPlacementFetchPolicy.ReturnCacheDataElseLoad` に設定する。 - Adapty ダッシュボードのすべてのプレースメントに[フォールバックペイウォール](fallback-paywalls)を設定する。 - `loadTimeout` を3〜5秒に設定し、タイムアウト発生時はフォールバックを受け入れる。 - `getProfile` にペイウォールの表示を依存させない。`getPaywall` は独立して呼び出し、プロファイルの取得が遅くてもUIをブロックしないようにする。 --- # File: android-test --- --- title: "Android SDKのテストとリリース" description: "AdaptyでAndroidアプリのサブスクリプション状態を確認する方法を学びます。" --- AdaptyのSDKをAndroidアプリに実装済みの場合は、すべてが正しく設定されており、購入が期待通りに動作することをテストする必要があります。これには、SDK統合のテストと、Google Playのサンドボックス環境での実際の購入フローのテストが含まれます。 ## アプリをテストする \{#test-your-app\} サンドボックステストやクローズドトラックの検証を含む、アプリ内課金の包括的なテスト方法については、[テストガイド](testing-on-android)をご覧ください。 ## リリースの準備 \{#prepare-for-release\} アプリをストアに申請する前に、[リリースチェックリスト](release-checklist)に従って以下を確認してください: - ストア接続とサーバー通知が設定されている - 購入が完了し、Adaptyに報告されている - アクセスが正しくアンロックおよび復元される - プライバシーとレビューの要件が満たされている --- # File: android-sdk-error-handling --- --- title: "Android SDKのエラーを処理する" description: "AdaptyのトラブルシューティングガイドでAndroid SDKのエラーを効果的に処理しましょう。" --- SDKから返されるエラーはすべて `AdaptyError` です。 :::tip **デバッグ前に詳細ログを有効にしてください。** ほとんどの `AdaptyError` は、Play Billing、ネットワーク、またはバックエンドのエラーをラップしています。詳細ログを有効にすると(`Adapty.logLevel = AdaptyLogLevel.VERBOSE` — [ログ記録](sdk-installation-android#logging)を参照)、ラップされたエラーがコンソールに出力され、実際の原因がわかることがほとんどです。 ::: :::important これらの解決策で問題が解決しない場合は、サポートに問い合わせる前に[その他の問題](#other-issues)を参照して、より効率的にサポートできるよう手順をご確認ください。 ::: | エラー | 解決策 | |----------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | UNKNOWN | 不明または予期しないエラーが発生したことを示します。 | | [ITEM_UNAVAILABLE](https://developer.android.com/reference/com/android/billingclient/api/BillingClient.BillingResponseCode#ITEM_UNAVAILABLE()) | このエラーは主にテスト段階で発生します。プロダクトが本番環境に存在しないか、ユーザーが Google Play のテスターグループに属していない可能性があります。 | | ADAPTY_NOT_INITIALIZED | Adapty SDK が有効化されていません。
スプラッシュスクリーンや初期の UI フックが `Adapty.activate` の完了前に Adapty のメソッドを呼び出している場合によく見られます。実機ではエミュレーターと実行タイミングが異なるため、再現しないこともあります。`Adapty.activate` が完了してから、他の SDK 呼び出しを行うようにしてください。完全な手順については [Android SDK の呼び出し順序](android-sdk-call-order) を参照してください。また、`Adapty.activate` メソッドを使用して [Adapty SDK を正しく設定](sdk-installation-android#activate-adapty-module-of-adapty-sdk) する必要があります。 | | PROFILE_WAS_CHANGED | 操作中にユーザープロファイルが変更されました。
`Adapty.identify` の実行中に別のメソッドを呼び出すと発生します。実行中の呼び出しが切り替え直前のプロファイルに対して行われ、SDK によって拒否されます。`Adapty.identify` の完了後に他の SDK 呼び出しを行うようにしてください。[Android SDK の呼び出し順序](android-sdk-call-order) を参照してください。 | | PRODUCT_NOT_FOUND | 購入しようとしたプロダクトがストアで利用できないことを示します。 | | INVALID_JSON |

ローカルのフォールバックペイウォール JSON が無効です。

デフォルトの英語のペイウォールを修正してから、無効なローカルペイウォールを置き換えてください。ペイウォールの修正方法については [リモートコンフィグでペイウォールをカスタマイズする](customize-paywall-with-remote-config) を、ローカルペイウォールの置き換え方法については [ローカルフォールバックペイウォールを定義する](fallback-paywalls) を参照してください。

| |

CURRENT_SUBSCRIPTION_TO_UPDATE

\_NOT_FOUND_IN_HISTORY

| 置き換え対象の元のサブスクリプションが有効なサブスクリプションの中に見つかりません。 | | [BILLING_SERVICE_TIMEOUT](https://developer.android.com/google/play/billing/errors#service_timeout_error_code_-3) | Google Play が応答する前にリクエストが最大タイムアウトに達したことを示します。Play Billing Library の呼び出しで要求されたアクションの実行が遅延した場合などに発生します。 | | [FEATURE_NOT_SUPPORTED](https://developer.android.com/reference/com/android/billingclient/api/BillingClient.BillingResponseCode#FEATURE_NOT_SUPPORTED()) | 要求された機能が現在のデバイスの Play Store でサポートされていません。 | | [BILLING_SERVICE_DISCONNECTED](https://developer.android.com/google/play/billing/errors#service_disconnected_error_code_-1) | クライアントアプリと `BillingClient` 経由の Google Play Store サービスとの接続が切断されたことを示します。 | | [BILLING_SERVICE_UNAVAILABLE](https://developer.android.com/google/play/billing/errors#service_unavailable_error_code_2) | Google Play Billing サービスが現在利用できないことを示します。ほとんどの場合、クライアントデバイスと Google Play Billing サービスの間のどこかでネットワーク接続の問題が発生しています。 | | [BILLING_UNAVAILABLE](https://developer.android.com/google/play/billing/errors#billing_unavailable_error_code_3) |

購入プロセス中に請求に関する問題が発生したことを示します。考えられる原因は以下のとおりです:

1. ユーザーのデバイスに Play Store アプリがインストールされていないか、古いバージョンです。

2. ユーザーがサポートされていない国にいます。

3. ユーザーが、管理者によって購入が無効化されているエンタープライズアカウントに属しています。

4. Google Play がユーザーの支払い方法に請求できませんでした(例:クレジットカードの有効期限切れ)。

5. ユーザーが Play Store アプリにログインしていません。

| | [DEVELOPER_ERROR](https://developer.android.com/google/play/billing/errors#developer_error) | API の使い方が正しくないことを示します。 | | [BILLING_ERROR](https://developer.android.com/google/play/billing/errors#error_error_code_6) | Google Play 自体の内部的な問題を示します。 | | [ITEM_ALREADY_OWNED](https://developer.android.com/reference/com/android/billingclient/api/BillingClient.BillingResponseCode#ITEM_ALREADY_OWNED()) | そのプロダクトはすでに購入済みです。 | | [ITEM_NOT_OWNED](https://developer.android.com/reference/com/android/billingclient/api/BillingClient.BillingResponseCode#ITEM_NOT_OWNED()) | ユーザーがそのアイテムを所有していないため、要求されたアクションが失敗したことを示します。 | | [BILLING_NETWORK_ERROR](https://developer.android.com/google/play/billing/errors#network_error_error_code_12) | デバイスと Play のシステム間のネットワーク接続に問題があったことを示します。 | | NO_PRODUCT_IDS_FOUND |

ペイウォール内のプロダクトがいずれもストアで利用できないことを示します。

このエラーが発生した場合は、以下の手順で解決してください:

  1. すべてのプロダクトが Adapty ダッシュボードに追加されているか確認してください。
  2. アプリの **Package name** が Google Play Console のものと一致していることを確認してください。
  3. アプリストアのプロダクト ID がダッシュボードに追加したものと一致していることを確認してください。ストアにすでに Bundle ID が含まれている場合を除き、ID に Bundle ID を含めないようにしてください。
  4. Google の税設定でアプリの有料ステータスが **Active** になっていることを確認してください。税情報が最新であり、証明書が有効であることも確認してください。
  5. 収益化の対象となるよう、アプリに銀行口座が紐付けられているか確認してください。
  6. プロダクトがお住まいの地域で利用可能か確認してください。
  7. アプリがいずれかのテストトラックに登録されていることを確認してください。**Internal testing** トラックはレビュー不要でアプリが顧客に公開されないため、最も手軽な選択肢です。
| | NO_PURCHASES_TO_RESTORE | Google Play が復元する購入を見つけられなかったことを示します。 | | AUTHENTICATION_ERROR | `Adapty.activate` メソッドを使用して [Adapty SDK を正しく設定](sdk-installation-android#activate-adapty-module-of-adapty-sdk) する必要があります。 | | BAD_REQUEST | リクエストが不正です。
[Google Play との連携](google-play-store-connection-configuration) に必要なすべての手順を完了していることを確認してください。 | | SERVER_ERROR | サーバーエラーです。 | | REQUEST_FAILED | 正確に特定できないネットワークの問題を示します。 | | DECODING_FAILED | レスポンスのデコードに失敗しました。
コードを確認し、送信しているパラメータが有効であることを確認してください。例えば、無効な API キーを使用している場合にもこのエラーが発生することがあります。 | | ANALYTICS_DISABLED | [無効化されている](analytics-integration#disabling-external-analytics-for-a-specific-customer) ため、アナリティクスイベントを処理できません。 | | WRONG_PARAMETER | パラメータの一部が正しくないことを示します。空白にできない箇所が空白になっている、型が間違っているなどが原因として考えられます。 | ## その他の問題 \{#other-issues\} まだ解決策が見つかっていない場合は、次のステップを試してみてください。 - **SDKを最新バージョンにアップグレードする**: 最新のSDKバージョンは安定性が高く、既知の問題の修正が含まれているため、常にアップグレードをおすすめします。 - **サポートチームへの問い合わせ、またはコミュニティでの質問**: [サポートフォーラム](https://adapty.featurebase.app/)で他の開発者に質問することもできます。 - **[support@adapty.io](mailto:support@adapty.io) またはチャットでサポートチームに連絡する**: SDKのアップグレードが難しい場合や、アップグレードしても解決しない場合は、サポートチームにお問い合わせください。[詳細ログを有効化](sdk-installation-android#logging)してログを共有いただくと、問題の解決が早くなります。関連するコードスニペットを添付することもできます。 --- # File: migration-to-android-312 --- --- title: "Adapty Android SDK を v3.12 に移行する" description: "パフォーマンス向上と新しいマネタイズ機能のために Adapty Android SDK v3.12 に移行する。" --- Adapty SDK 3.12.0 では、`logShowOnboarding` メソッドを SDK から削除しました。 このメソッドを使用していた場合、SDK をバージョン 3.12 以降にアップグレードすると利用できなくなります。 代わりに、[Adapty のノーコード オンボーディングビルダーでオンボーディングを作成](onboardings)できます。これらのオンボーディングの分析は自動的に追跡され、カスタマイズオプションも豊富に用意されています。 --- # File: migration-to-android-310 --- --- title: "Android Adapty SDK 3.10.0 移行ガイド" description: "" --- Adapty SDK 3.10.0 はメジャーリリースであり、いくつかの改善が含まれていますが、移行作業が必要な場合があります。 1. `AdaptyUiPersonalizedOfferResolver` が削除されました。使用している場合は、`onAwaitingPurchaseParams` コールバックで渡してください。 2. ペイウォールビルダーのペイウォールで使用している `onAwaitingSubscriptionUpdateParams` メソッドのシグネチャを更新してください。 ## 購入パラメータコールバックの更新 \{#update-purchase-parameters-callback\} `onAwaitingSubscriptionUpdateParams` メソッドは `onAwaitingPurchaseParams` に名称変更され、`AdaptySubscriptionUpdateParameters` の代わりに `AdaptyPurchaseParameters` を使用するようになりました。これにより、サブスクリプション切り替えパラメータ(クロスグレード)の指定、価格が個人向けかどうかの指定([詳細はこちら](https://developer.android.com/google/play/billing/integrate#personalized-price))、その他の購入パラメータを設定できます。 ```diff showLineNumbers - override fun onAwaitingSubscriptionUpdateParams( - product: AdaptyPaywallProduct, - context: Context, - onSubscriptionUpdateParamsReceived: SubscriptionUpdateParamsCallback, - ) { - onSubscriptionUpdateParamsReceived(AdaptySubscriptionUpdateParameters(...)) - } + override fun onAwaitingPurchaseParams( + product: AdaptyPaywallProduct, + context: Context, + onPurchaseParamsReceived: AdaptyUiEventListener.PurchaseParamsCallback, + ): AdaptyUiEventListener.PurchaseParamsCallback.IveBeenInvoked { + onPurchaseParamsReceived( + AdaptyPurchaseParameters.Builder() + .withSubscriptionUpdateParams(AdaptySubscriptionUpdateParameters(...)) + .withOfferPersonalized(true) + .build() + ) + return AdaptyUiEventListener.PurchaseParamsCallback.IveBeenInvoked + } ``` 追加パラメータが不要な場合は、次のように記述できます。 ```kotlin showLineNumbers + override fun onAwaitingPurchaseParams( product: AdaptyPaywallProduct, context: Context, onPurchaseParamsReceived: AdaptyUiEventListener.PurchaseParamsCallback, ): AdaptyUiEventListener.PurchaseParamsCallback.IveBeenInvoked { onPurchaseParamsReceived(AdaptyPurchaseParameters.Empty) return AdaptyUiEventListener.PurchaseParamsCallback.IveBeenInvoked } ``` --- # File: migration-to-android-sdk-34 --- --- title: "Adapty Android SDK を v3.4 へ移行する" description: "Adapty Android SDK v3.4 への移行で、パフォーマンス向上と新しいマネタイズ機能を活用しましょう。" --- Adapty SDK 3.4.0 はメジャーリリースであり、お客様側での移行作業が必要な改善が含まれています。 ## フォールバックペイウォールファイルの更新 \{#update-fallback-paywall-files\} 新しい SDK バージョンとの互換性を確保するため、フォールバックペイウォールファイルを更新してください。 1. Adapty ダッシュボードから[更新済みのフォールバックペイウォールファイルをダウンロード](fallback-paywalls)します。 2. モバイルアプリ内の[既存のフォールバックペイウォールを新しいファイルに置き換え](android-use-fallback-paywalls)ます。 ## オブザーバーモードの実装を更新する \{#update-implementation-of-observer-mode\} オブザーバーモードを使用している場合は、その実装を更新してください。 以前のバージョンでは、オブザーバーモードで Adapty が独自インフラ経由のトランザクションに直接アクセスできないため、Adapty に認識させるには購入を復元する必要がありました。ペイウォールを使用していた場合は、各トランザクションをそれを起点としたペイウォールに手動で紐付ける必要もありました。 新しいバージョンでは、Adapty にトランザクションを認識させるために各トランザクションを明示的にレポートする必要があります。ペイウォールを使用している場合は、トランザクションを使用したペイウォールに紐付けるためにバリエーション ID も渡す必要があります。 :::warning **トランザクションのレポートを省略しないでください!** `reportTransaction` を呼び出さないと、Adapty はトランザクションを認識できず、アナリティクスに表示されず、インテグレーションにも送信されません。 ::: ```diff showLineNumbers - Adapty.restorePurchases { result -> - if (result is AdaptyResult.Success) { - // success - } - } - - Adapty.setVariationId(transactionId, variationId) { error -> - if (error == null) { - // success - } - } + val transactionInfo = TransactionInfo.fromPurchase(purchase) + + Adapty.reportTransaction(transactionInfo, variationId) { result -> + if (result is AdaptyResult.Success) { + // success + } + } ``` ```diff showLineNumbers - Adapty.restorePurchases(result -> { - if (result instanceof AdaptyResult.Success) { - // success - } - }); - - Adapty.setVariationId(transactionId, variationId, error -> { - if (error == null) { - // success - } - }); + TransactionInfo transactionInfo = TransactionInfo.fromPurchase(purchase); + + Adapty.reportTransaction(transactionInfo, variationId, result -> { + if (result instanceof AdaptyResult.Success) { + // success + } + }); ``` --- # File: migration-to-android330 --- --- title: "Adapty Android SDK を v3.3 に移行する" description: "パフォーマンス向上と新しいマネタイズ機能のために Adapty Android SDK v3.3 に移行します。" --- Adapty SDK 3.3.0 はメジャーリリースであり、いくつかの改善が含まれていますが、移行手順が必要になる場合があります。 1. ペイウォールビルダーで作成されていないペイウォールでの購入処理を更新してください。`USER_CANCELED` および `PENDING_PURCHASE` エラーコードの処理を停止してください。キャンセルされた購入はエラーとして扱われなくなり、エラーなしの購入結果として返されます。 2. ペイウォールビルダーで作成されたペイウォールの `onPurchaseCanceled` および `onPurchaseSuccess` イベントを、新しい `onPurchaseFinished` イベントに置き換えてください。この変更も同じ理由です:キャンセルされた購入はエラーとして扱われなくなり、エラーなしの購入結果に含まれます。 3. ペイウォールビルダーのペイウォールに対する `onAwaitingSubscriptionUpdateParams` のメソッドシグネチャを変更してください。 4. ファイル URI を直接渡してフォールバックペイウォールを提供している場合は、その方法を更新してください。 5. Adjust、AirBridge、Amplitude、AppMetrica、Appsflyer、Branch、Facebook Ads、Firebase and Google Analytics、Mixpanel、OneSignal、Pushwoosh のインテグレーション設定を更新してください。 ## 購入処理の更新 \{#update-making-purchase\} 以前は、キャンセルされた購入と保留中の購入はエラーとして扱われ、それぞれ `USER_CANCELED` および `PENDING_PURCHASE` コードが返されていました。 新しい `AdaptyPurchaseResult` クラスを使用して、キャンセル・成功・保留中の購入を示すようになりました。以下のように購入コードを更新してください: ~~~diff Adapty.makePurchase(activity, product) { result -> when (result) { is AdaptyResult.Success -> { - val info = result.value - val profile = info?.profile - - if (profile?.accessLevels?.get("YOUR_ACCESS_LEVEL")?.isActive == true) { - // Grant access to the paid features - } + when (val purchaseResult = result.value) { + is AdaptyPurchaseResult.Success -> { + val profile = purchaseResult.profile + if (profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive == true) { + // Grant access to the paid features + } + } + + is AdaptyPurchaseResult.UserCanceled -> { + // Handle the case where the user canceled the purchase + } + + is AdaptyPurchaseResult.Pending -> { + // Handle deferred purchases (e.g., the user will pay offline with cash + } + } } is AdaptyResult.Error -> { val error = result.error // Handle the error } } } ~~~ 完全なコード例については、[モバイルアプリで購入する](android-making-purchases#make-purchase) ページをご覧ください。 ## ペイウォールビルダーの購入イベントを変更する \{#modify-paywall-builder-purchase-events\} 1. `onPurchaseFinished` イベントを追加します: ```diff showLineNumbers + public override fun onPurchaseFinished( + purchaseResult: AdaptyPurchaseResult, + product: AdaptyPaywallProduct, + context: Context, + ) { + when (purchaseResult) { + is AdaptyPurchaseResult.Success -> { + // Grant access to the paid features + } + is AdaptyPurchaseResult.UserCanceled -> { + // Handle the case where the user canceled the purchase + } + is AdaptyPurchaseResult.Pending -> { + // Handle deferred purchases (e.g., the user will pay offline with cash) + } + } + } ``` 完全なコード例については、[成功・キャンセル・保留中の購入](android-handling-events#successful-canceled-or-pending-purchase) とイベントの説明をご覧ください。 2. `onPurchaseCancelled` イベントの処理を削除します: ```diff showLineNumbers - public override fun onPurchaseCanceled( - product: AdaptyPaywallProduct, - context: Context, - ) {} ``` 3. `onPurchaseSuccess` を削除します: ```diff showLineNumbers - public override fun onPurchaseSuccess( - profile: AdaptyProfile?, - product: AdaptyPaywallProduct, - context: Context, - ) { - // Your logic on successful purchase - } ``` ## onAwaitingSubscriptionUpdateParams メソッドのシグネチャを変更する \{#change-the-signature-of--onawaitingsubscriptionupdateparams-method\} 別のサブスクリプションがアクティブな状態で新しいサブスクリプションが購入された場合、新しいサブスクリプションで既存のサブスクリプションを置き換えるには `onSubscriptionUpdateParamsReceived(AdaptySubscriptionUpdateParameters...))` を、既存のサブスクリプションをアクティブに維持しながら新しいサブスクリプションを別途追加するには `onSubscriptionUpdateParamsReceived(null)` を呼び出してください: ```diff showLineNumbers - public override fun onAwaitingSubscriptionUpdateParams( - product: AdaptyPaywallProduct, - context: Context, - ): AdaptySubscriptionUpdateParameters? { - return AdaptySubscriptionUpdateParameters(...) - } + public override fun onAwaitingSubscriptionUpdateParams( + product: AdaptyPaywallProduct, + context: Context, + onSubscriptionUpdateParamsReceived: SubscriptionUpdateParamsCallback, + ) { + onSubscriptionUpdateParamsReceived(AdaptySubscriptionUpdateParameters(...)) + } ``` 最終的なコード例については、[サブスクリプションのアップグレード](android-handling-events#upgrade-subscription) のドキュメントセクションをご覧ください。 ## フォールバックペイウォールの提供方法を更新する \{#update-providing-fallback-paywalls\} フォールバックペイウォールを提供するためにファイル URI を渡している場合は、以下のように更新してください: ```diff showLineNumbers val fileUri: Uri = // Get the URI for the file with fallback paywalls - Adapty.setFallbackPaywalls(fileUri, callback) + Adapty.setFallbackPaywalls(FileLocation.fromFileUri(fileUri), callback) ``` ```diff showLineNumbers Uri fileUri = // Get the URI for the file with fallback paywalls - Adapty.setFallbackPaywalls(fileUri, callback); + Adapty.setFallbackPaywalls(FileLocation.fromFileUri(fileUri), callback); ``` ## サードパーティインテグレーションの SDK 設定を更新する \{#update-third-party-integration-sdk-configuration\} Adapty Android SDK 3.3.0 以降でインテグレーションが正しく動作するように、以下のセクションに従って各インテグレーションの SDK 設定を更新してください。 ### Adjust 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[Adjust インテグレーションの SDK 設定](adjust#connect-your-app-to-adjust) をご覧ください。 ```diff showLineNumbers - Adjust.getAttribution { attribution -> - if (attribution == null) return@getAttribution - - Adjust.getAdid { adid -> - if (adid == null) return@getAdid - - Adapty.updateAttribution(attribution, AdaptyAttributionSource.ADJUST, adid) { error -> - // Handle the error - } - } - } + Adjust.getAdid { adid -> + if (adid == null) return@getAdid + + Adapty.setIntegrationIdentifier("adjust_device_id", adid) { error -> + if (error != null) { + // Handle the error + } + } + } + + Adjust.getAttribution { attribution -> + if (attribution == null) return@getAttribution + + Adapty.updateAttribution(attribution, "adjust") { error -> + if (error != null) { + // Handle the error + } + } + } ``` ```diff showLineNumbers val config = AdjustConfig(context, adjustAppToken, environment) config.setOnAttributionChangedListener { attribution -> attribution?.let { attribution -> - Adapty.updateAttribution(attribution, AdaptyAttributionSource.ADJUST) { error -> + Adapty.updateAttribution(attribution, "adjust") { error -> if (error != null) { // Handle the error } } } } Adjust.onCreate(config) ``` ### AirBridge 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[AirBridge インテグレーションの SDK 設定](airbridge#connect-your-app-to-airbridge) をご覧ください。 ```diff showLineNumbers Airbridge.getDeviceInfo().getUUID(object: AirbridgeCallback.SimpleCallback() { override fun onSuccess(result: String) { - val params = AdaptyProfileParameters.Builder() - .withAirbridgeDeviceId(result) - .build() - Adapty.updateProfile(params) { error -> - if (error != null) { - // Handle the error - } - } + Adapty.setIntegrationIdentifier("airbridge_device_id", result) { error -> + if (error != null) { + // Handle the error + } + } } override fun onFailure(throwable: Throwable) { } }) ``` ### Amplitude 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[Amplitude インテグレーションの SDK 設定](amplitude#sdk-configuration) をご覧ください。 ```diff showLineNumbers // For Amplitude maintenance SDK (obsolete) val amplitude = Amplitude.getInstance() val amplitudeDeviceId = amplitude.getDeviceId() val amplitudeUserId = amplitude.getUserId() //for actual Amplitude Kotlin SDK val amplitude = Amplitude( Configuration( apiKey = AMPLITUDE_API_KEY, context = applicationContext ) ) val amplitudeDeviceId = amplitude.store.deviceId val amplitudeUserId = amplitude.store.userId // - val params = AdaptyProfileParameters.Builder() - .withAmplitudeDeviceId(amplitudeDeviceId) - .withAmplitudeUserId(amplitudeUserId) - .build() - Adapty.updateProfile(params) { error -> - if (error != null) { - // Handle the error - } - } + Adapty.setIntegrationIdentifier("amplitude_user_id", amplitudeUserId) { error -> + if (error != null) { + // Handle the error + } + } + Adapty.setIntegrationIdentifier("amplitude_device_id", amplitudeDeviceId) { error -> + if (error != null) { + // Handle the error + } + } ``` ### AppMetrica 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[AppMetrica インテグレーションの SDK 設定](appmetrica#sdk-configuration) をご覧ください。 ```diff showLineNumbers val startupParamsCallback = object: StartupParamsCallback { override fun onReceive(result: StartupParamsCallback.Result?) { val deviceId = result?.deviceId ?: return - val params = AdaptyProfileParameters.Builder() - .withAppmetricaDeviceId(deviceId) - .withAppmetricaProfileId("YOUR_ADAPTY_CUSTOMER_USER_ID") - .build() - Adapty.updateProfile(params) { error -> - if (error != null) { - // Handle the error - } - } + Adapty.setIntegrationIdentifier("appmetrica_device_id", deviceId) { error -> + if (error != null) { + // Handle the error + } + } + + Adapty.setIntegrationIdentifier("appmetrica_profile_id", "YOUR_ADAPTY_CUSTOMER_USER_ID") { error -> + if (error != null) { + // Handle the error + } + } } override fun onRequestError( reason: StartupParamsCallback.Reason, result: StartupParamsCallback.Result? ) { // Handle the error } } AppMetrica.requestStartupParams(context, startupParamsCallback, listOf(StartupParamsCallback.APPMETRICA_DEVICE_ID)) ``` ### AppsFlyer 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[AppsFlyer インテグレーションの SDK 設定](appsflyer#connect-your-app-to-appsflyer) をご覧ください。 ```diff showLineNumbers val conversionListener: AppsFlyerConversionListener = object : AppsFlyerConversionListener { override fun onConversionDataSuccess(conversionData: Map) { - Adapty.updateAttribution( - conversionData, - AdaptyAttributionSource.APPSFLYER, - AppsFlyerLib.getInstance().getAppsFlyerUID(context) - ) { error -> - if (error != null) { - // Handle the error - } - } + val uid = AppsFlyerLib.getInstance().getAppsFlyerUID(context) + Adapty.setIntegrationIdentifier("appsflyer_id", uid) { error -> + if (error != null) { + // Handle the error + } + } + Adapty.updateAttribution(conversionData, "appsflyer") { error -> + if (error != null) { + // Handle the error + } + } } } ``` ### Branch 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[Branch インテグレーションの SDK 設定](branch#connect-your-app-to-branch) をご覧ください。 ```diff showLineNumbers // Login and update attribution Branch.getAutoInstance(this) .setIdentity("YOUR_USER_ID") { referringParams, error -> referringParams?.let { data -> - Adapty.updateAttribution(data, AdaptyAttributionSource.BRANCH) { error -> - if (error != null) { - // Handle the error - } - } + Adapty.updateAttribution(data, "branch") { error -> + if (error != null) { + // Handle the error + } + } } } // Logout Branch.getAutoInstance(context).logout() ``` ### Facebook Ads 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[Facebook Ads インテグレーションの SDK 設定](facebook-ads#connect-your-app-to-facebook-ads) をご覧ください。 ```diff showLineNumbers - val builder = AdaptyProfileParameters.Builder() - .withFacebookAnonymousId(AppEventsLogger.getAnonymousAppDeviceGUID(context)) - - Adapty.updateProfile(builder.build()) { error -> - if (error != null) { - // Handle the error - } - } + Adapty.setIntegrationIdentifier( + "facebook_anonymous_id", + AppEventsLogger.getAnonymousAppDeviceGUID(context) + ) { error -> + if (error != null) { + // Handle the error + } + } ``` ### Firebase and Google Analytics 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[Firebase and Google Analytics インテグレーションの SDK 設定](firebase-and-google-analytics) をご覧ください。 ```diff showLineNumbers // After Adapty.activate() FirebaseAnalytics.getInstance(context).appInstanceId.addOnSuccessListener { appInstanceId -> - Adapty.updateProfile( - AdaptyProfileParameters.Builder() - .withFirebaseAppInstanceId(appInstanceId) - .build() - ) { error -> - if (error != null) { - // Handle the error - } - } + Adapty.setIntegrationIdentifier("firebase_app_instance_id", appInstanceId) { error -> + if (error != null) { + // Handle the error + } + } } ``` ```diff showLineNumbers // After Adapty.activate() - FirebaseAnalytics.getInstance(context).getAppInstanceId().addOnSuccessListener(appInstanceId -> { - AdaptyProfileParameters params = new AdaptyProfileParameters.Builder() - .withFirebaseAppInstanceId(appInstanceId) - .build(); - - Adapty.updateProfile(params, error -> { - if (error != null) { - // Handle the error - } - }); - }); + FirebaseAnalytics.getInstance(context).getAppInstanceId().addOnSuccessListener(appInstanceId -> { + Adapty.setIntegrationIdentifier("firebase_app_instance_id", appInstanceId, error -> { + if (error != null) { + // Handle the error + } + }); + }); ``` ### Mixpanel 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[Mixpanel インテグレーションの SDK 設定](mixpanel#sdk-configuration) をご覧ください。 ```diff showLineNumbers - val params = AdaptyProfileParameters.Builder() - .withMixpanelUserId(mixpanelAPI.distinctId) - .build() - - Adapty.updateProfile(params) { error -> - if (error != null) { - // Handle the error - } - } + Adapty.setIntegrationIdentifier("mixpanel_user_id", mixpanelAPI.distinctId) { error -> + if (error != null) { + // Handle the error + } + } ``` ### OneSignal 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[OneSignal インテグレーションの SDK 設定](onesignal#sdk-configuration) をご覧ください。 ```diff showLineNumbers // SubscriptionID val oneSignalSubscriptionObserver = object: IPushSubscriptionObserver { override fun onPushSubscriptionChange(state: PushSubscriptionChangedState) { - val params = AdaptyProfileParameters.Builder() - .withOneSignalSubscriptionId(state.current.id) - .build() - - Adapty.updateProfile(params) { error -> + Adapty.setIntegrationIdentifier("one_signal_subscription_id", state.current.id) { error -> if (error != null) { // Handle the error } } } } ``` ```diff showLineNumbers // SubscriptionID IPushSubscriptionObserver oneSignalSubscriptionObserver = state -> { - AdaptyProfileParameters params = new AdaptyProfileParameters.Builder() - .withOneSignalSubscriptionId(state.getCurrent().getId()) - .build(); - Adapty.updateProfile(params, error -> { + Adapty.setIntegrationIdentifier("one_signal_subscription_id", state.getCurrent().getId(), error -> { if (error != null) { // Handle the error } }); }; ``` ```diff showLineNumbers // PlayerID val osSubscriptionObserver = OSSubscriptionObserver { stateChanges -> stateChanges?.to?.userId?.let { playerId -> - val params = AdaptyProfileParameters.Builder() - .withOneSignalPlayerId(playerId) - .build() - - Adapty.updateProfile(params) { error -> + Adapty.setIntegrationIdentifier("one_signal_player_id", playerId) { error -> if (error != null) { // Handle the error } - } } } ``` ```diff showLineNumbers // PlayerID OSSubscriptionObserver osSubscriptionObserver = stateChanges -> { OSSubscriptionState to = stateChanges != null ? stateChanges.getTo() : null; String playerId = to != null ? to.getUserId() : null; if (playerId != null) { - AdaptyProfileParameters params1 = new AdaptyProfileParameters.Builder() - .withOneSignalPlayerId(playerId) - .build(); - - Adapty.updateProfile(params1, error -> { + Adapty.setIntegrationIdentifier("one_signal_player_id", playerId, error -> { if (error != null) { // Handle the error } - }); } }; ``` ### Pushwoosh 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[Pushwoosh インテグレーションの SDK 設定](pushwoosh#sdk-configuration) をご覧ください。 ```diff showLineNumbers - val params = AdaptyProfileParameters.Builder() - .withPushwooshHwid(Pushwoosh.getInstance().hwid) - .build() - Adapty.updateProfile(params) { error -> + Adapty.setIntegrationIdentifier("pushwoosh_hwid", Pushwoosh.getInstance().hwid) { error -> if (error != null) { // Handle the error } } ``` ```diff showLineNumbers - AdaptyProfileParameters params = new AdaptyProfileParameters.Builder() - .withPushwooshHwid(Pushwoosh.getInstance().getHwid()) - .build(); - - Adapty.updateProfile(params, error -> { + Adapty.setIntegrationIdentifier("pushwoosh_hwid", Pushwoosh.getInstance().getHwid(), error -> { if (error != null) { // Handle the error } }); ``` --- # File: migration-to-android-sdk-v3 --- --- title: "Adapty Android SDK を v3.0 に移行する" description: "Adapty Android SDK v3.0 に移行して、パフォーマンスの向上と新しいマネタイゼーション機能を活用しましょう。" --- Adapty SDK v3.0 では、新しい [Adapty ペイウォールビルダー](adapty-paywall-builder)をサポートしています。これはペイウォールをノーコードで作成できる使いやすいツールの新バージョンです。高い柔軟性と豊富なデザイン機能により、より効果的で収益性の高いペイウォールを作成できます。 Adapty SDK は BoM(Bill of Materials)として提供されており、アプリ内の Adapty SDK と AdaptyUI SDK のバージョンを常に一致させることができます。 v3.0 に移行するには、以下のようにコードを更新してください: ```diff showLineNumbers dependencies { ... - implementation 'io.adapty:android-sdk:2.11.5' - implementation 'io.adapty:android-ui:2.11.3' + implementation platform('io.adapty:adapty-bom:3.0.4') + implementation 'io.adapty:android-sdk' + implementation 'io.adapty:android-ui' } ``` ```diff showLineNumbers dependencies { ... - implementation("io.adapty:android-sdk:2.11.5") - implementation("io.adapty:android-ui:2.11.3") + implementation(platform("io.adapty:adapty-bom:3.0.4")) + implementation("io.adapty:android-sdk") + implementation("io.adapty:android-ui") } ``` ```diff showLineNumbers //libs.versions.toml [versions] .. - adapty = "2.11.5" - adaptyUi = "2.11.3" + adaptyBom = "3.0.4" [libraries] .. - adapty = { group = "io.adapty", name = "android-sdk", version.ref = "adapty" } - adapty-ui = { group = "io.adapty", name = "android-ui", version.ref = "adaptyUi" } + adapty-bom = { module = "io.adapty:adapty-bom", version.ref = "adaptyBom" } + adapty = { module = "io.adapty:android-sdk" } + adapty-ui = { module = "io.adapty:android-ui" } //module-level build.gradle.kts dependencies { ... + implementation(libs.adapty.bom) implementation(libs.adapty) implementation(libs.adapty.ui) } ``` --- # End of Documentation _Generated on: 2026-06-24T14:36:28.457Z_ _Successfully processed: 40/40 files_ # API - Adapty Documentation (Full Content) This file contains the complete content of all documentation pages for this platform. Locale: ja Generated on: 2026-06-24T14:36:28.459Z Total files: 18 --- # File: developer-cli --- --- title: "Developer CLI" description: "Overview of the Adapty Developer CLI." --- The **Adapty Developer CLI** is a command-line tool for managing your Adapty account without opening the Dashboard. It provides the main configuration capabilities, accessible from your terminal or automated environments. **What you can do with the CLI:** - Create and configure iOS and Android apps in your Adapty account - Define access levels — the subscription tiers your app checks at runtime - Set up products and map them to App Store and Google Play store IDs - Create paywalls and assign products to them - Configure placements to fetch paywalls via the SDK :::link Using an AI assistant or MCP client? An [Adapty CLI skill](https://github.com/adaptyteam/adapty-cli/tree/main/skills/adapty-cli) is available to help LLMs work with the CLI. ::: --- # File: developer-cli-quickstart --- --- title: "Adapty Developer CLI クイックスタートガイド" description: "Developer CLI を使って Adapty アカウントをエンドツーエンドでセットアップ — アプリ作成からプレースメント公開まで、数コマンドで完了。" --- :::link AI アシスタントを使っていますか?LLM が CLI を操作しやすくなる [Adapty CLI スキル](https://github.com/adaptyteam/adapty-cli/tree/main/skills/adapty-cli) が利用できます。 ::: Adapty CLI を使うと、アプリの設定をすべてコマンドラインから行えます。ターミナル作業を好む方や [MCP クライアント](https://github.com/adaptyteam/adapty-cli/tree/main/skills/adapty-cli)を使う方向けに、[ダッシュボードのクイックスタート](integrate-payments)の代替手段として活用できます。 :::note App Store Connect や Google Play への接続は、ダッシュボードでの一度きりのセットアップが必要です — 手順 3 で説明します。 ::: この手順を完了すると、アプリ・アクセスレベル・プロダクト・ペイウォール・プレースメントがすべて [Adapty ダッシュボード](https://app.adapty.io) に表示されます。 ## 1. CLI をインストールする \{#1-install-the-cli\} [Node.js](https://nodejs.org/en/download) 18 以降が必要です。 CLI をインストールするには、次のコマンドを実行します: ```bash npm install -g adapty ``` または、直接実行する場合: ```bash npx adapty auth login ``` ## 2. 認証する \{#2-authenticate\} ログインコマンドを実行して、CLI を Adapty アカウントに接続します。 ```bash adapty auth login ``` CLI がブラウザタブを開きます。ターミナルに表示されたコードとブラウザに表示されたコードが一致していることを確認し、**Authorize** をクリックします。認証が完了するとターミナルに確認メッセージが表示されます。 ## 3. アプリを作成する \{#3-create-your-app\} Adapty のアプリはモバイルアプリケーションを表します。1 つの Adapty アプリが App Store と Google Play の両方に接続されるため、公開するストアの数に関わらず、作成するのは 1 つで十分です。 ```bash adapty apps create --title "My App" --platform ios --platform android --apple-bundle-id com.example.app --google-bundle-id com.example.app ``` ```bash adapty apps create --title "My App" --platform ios --apple-bundle-id com.example.app ``` ```bash adapty apps create --title "My App" --platform android --google-bundle-id com.example.app ``` このコマンドは `` を返します。以降のコマンドではすべてこの ID を使用します。 :::important 次の手順に進む前に、Adapty ダッシュボードでアプリを App Store Connect および Google Play に接続してください。手順 5 では両ストアのプロダクト ID が必要です。 - [App Store Connect を接続する](app-store-connection-configuration) - [Google Play を接続する](google-play-store-connection-configuration) ::: ## 4. アクセスレベルを作成する(任意) \{#4-create-an-access-level-optional\} [アクセスレベル](access-level)は、購入後にユーザーがアクセスできる内容を管理します。特定のプロダクトを購入したかどうかを確認する代わりに、アプリはユーザーが特定のアクセスレベルを持っているかどうかを確認します。これにより、アプリのロジックを特定のプロダクト ID から切り離すことができます。 `premium` アクセスレベルは新しいアプリとともに自動的に作成されます。**ほとんどのアプリではこの手順はスキップできます。** 手順 5 ではアクセスレベル ID として `premium` を使用してください。 異なるプロダクトが異なるユーザーグループの異なる機能をアンロックする場合 — たとえば「Basic」サブスクライバーと「Pro」サブスクライバーがアプリの異なる部分にアクセスできる場合 — にのみ、このコマンドを実行してください。 ```bash adapty access-levels create --app --sdk-id "pro" --title "Pro" ``` - `--sdk-id` はアプリコード内でユーザーがその機能を利用できるかどうかを確認するために使う識別子です(例:`if user.hasAccessLevel("pro")`)。この手順をスキップしてデフォルトのアクセスレベルを使う場合、その `--sdk-id` は `premium` です。 - `--title` は Adapty ダッシュボードでの参照用に表示されるラベルです。 このコマンドは `` を返します。 ## 5. プロダクトを作成する \{#5-create-a-product\} Adapty における[プロダクト](product)は、アプリが販売するもの — サブスクリプションや買い切り購入 — を表します。App Store Connect と Google Play のアイテムを 1 つの Adapty プロダクトにまとめて、一元管理できます。 各ストアのプロダクト ID が必要です:App Store Connect の Apple プロダクト ID、および Google Play Console の Android プロダクト ID とベースプラン ID。確認方法の詳細は[プロダクト](quickstart-products)を参照してください。 手順 4 をスキップした場合は、手順 3 の `apps create` コマンドが返した `default_access_level.id` を `` として使用してください。 :::important ここでリンクするストアのプロダクト ID(`--ios-product-id`、`--android-product-id`)は作成後に変更できません。別のストアプロダクト ID を使用する場合は、新しいプロダクトを作成してください。 ::: ```bash adapty products create --app --title "My Product" --access-level-id --period monthly --ios-product-id --android-product-id --android-base-plan-id ``` ```bash adapty products create --app --title "My Product" --access-level-id --period monthly --ios-product-id ``` ```bash adapty products create --app --title "My Product" --access-level-id --period monthly --android-product-id --android-base-plan-id ``` このコマンドは `` を返します。 ## 6. ペイウォールを作成する \{#6-create-a-paywall\} [ペイウォール](paywalls)はプロダクトを格納するコンテナです。Adapty では、ペイウォールがユーザーにプロダクトを届ける唯一の方法です。すべてのプロダクトは、アプリに表示される前にペイウォールに含まれている必要があります。 :::important ペイウォールがプレースメントにリンクされると、そのプロダクトは変更できません。別のプロダクトを使用するには、新しいペイウォールを作成してプレースメントがそちらを参照するように更新してください。 ::: ```bash adapty paywalls create --app --title "My Paywall" --product-id ``` ```bash adapty paywalls create --app --title "My Paywall" --product-id --product-id ``` このコマンドは `` を返します。 ## 7. プレースメントを作成する \{#7-create-a-placement\} [プレースメント](placements)は、アプリ内でペイウォールを表示する場所を指します。アプリコードにハードコードするのはプレースメント ID だけです。どのペイウォールをどのユーザーに表示するかといった設定はすべて、新しいアプリバージョンをリリースすることなくダッシュボードから管理できます。 `--developer-id` は、後でアプリコードからこの場所に表示するペイウォールを Adapty に問い合わせる際に参照する文字列です。場所を表すわかりやすい名前(例:`"main"`、`"onboarding"`、`"settings"`)を指定してください。 ```bash adapty placements create --app --title "Main" --developer-id "main" --audiences '[{"segment_ids":[],"paywall_id":"","priority":0}]' ``` `--audiences` フラグは、どのユーザーにどのペイウォールを表示するかを制御します。上の例では単一のデフォルトオーディエンスを設定しており、このプレースメントのすべてのユーザーに同じペイウォールが表示されます。 ## 次のステップ \{#whats-next\} すべてのエンティティが [Adapty ダッシュボード](https://app.adapty.io) に表示されるようになりました。次は: - [ペイウォールをデザインする](adapty-paywall-builder) — ノーコードのペイウォールビルダーを使って、作成したペイウォールにビジュアル・レイアウト・コピーを追加します。 - [Adapty SDK を組み込む](quickstart-sdk) — アプリに SDK を追加して、プレースメントを取得・表示します。 - 異なるユーザー[セグメント](segments)を異なるペイウォールにルーティングする — 詳細は完全リファレンスの [`placements update`](developer-cli-reference#adapty-placements-update) と [`segments list`](developer-cli-reference#adapty-segments-list) を参照してください。 --- # File: developer-cli-authentication --- --- title: "Adapty Developer CLI での認証" description: "Adapty Developer CLI での認証方法について説明します。" --- :::link AIアシスタントを使用していますか?LLMがCLIを操作するための[Adapty CLIスキル](https://github.com/adaptyteam/adapty-cli/tree/main/skills/adapty-cli)が利用できます。 ::: CLIはAdapty APIを呼び出すために認証が必要です。 ## ログイン \{#log-in\} ログインするには: 1. ターミナルで次のコマンドを実行します: ```bash adapty auth login ``` 2. CLIが`XXXX-XXXX`形式の確認コードを表示し、Adapty ダッシュボードをブラウザで開きます。 3. 認証ページで、コードがターミナルの出力と一致していることを確認します。 4. **Authorize**をクリックします。ブラウザに「CLI authorized! You can close this tab.」と表示されます。 5. ターミナルに戻ると、CLIが認証済みであることを確認するメッセージが表示されます。 認証前にコードが期限切れになった場合、または**Deny**をクリックした場合は、次のコマンドを再度実行してフローを再開してください: ```bash adapty auth login ``` ## 認証の管理 \{#manage-authentication\} ### 認証状態の確認 \{#check-authentication-status\} 現在の認証状態を確認するには、次のコマンドを実行します: ```bash adapty auth status ``` 認証済みの場合、出力にはメールアドレス、マスクされたトークンのプレフィックス、およびローカル設定ファイルのパスが表示されます: ``` Email: you@example.com Token: abcd1234**** Config: ~/.config/adapty/config.json ``` 未認証の場合: ``` Not authenticated. Run `adapty auth login`. ``` ### トークンの検証 \{#verify-your-token\} トークンが有効であることを確認し、アカウントの詳細を表示するには、次のコマンドを実行します: ```bash adapty auth whoami ``` `adapty auth status`とは異なり、このコマンドはサーバーにリクエストを送信してトークンを検証します。 ### ログアウト \{#log-out\} 保存されている認証情報をローカルから削除するには、次のコマンドを実行します: ```bash adapty auth logout ``` これにより`~/.config/adapty/config.json`が削除されます。トークンは有効期限が切れるまでサーバー側では有効なままです。すぐに無効化する必要がある場合は、代わりに`adapty auth revoke`を使用してください。 ### トークンの失効 \{#revoke-your-token\} サーバー上のトークンを無効化し、ローカルからも削除するには、次のコマンドを実行します: ```bash adapty auth revoke ``` このコマンドは、たとえば認証情報が漏洩した可能性がある場合など、トークンを完全に無効化したいときに使用します。失効後、再認証するには`adapty auth login`を実行してください。 ## トークンエラー \{#token-errors\} トークンが失効または無効になった場合、CLIコマンドは401エラーを返します。再認証するには、次のコマンドを実行します: ```bash adapty auth login ``` --- # File: developer-cli-reference --- --- title: "Adapty Developer CLIの完全リファレンス" description: "すべてのAdapty Developer CLIコマンドの完全リファレンス。" --- :::link AIアシスタントを使っていますか?LLMがCLIを操作しやすいように[Adapty CLIスキル](https://github.com/adaptyteam/adapty-cli/tree/main/skills/adapty-cli)が用意されています。 ::: この記事では、Adapty CLIのすべてのコマンドと引数、フラグ、使用可能な値を一覧で紹介します。 :::link 認証の設定とトークン管理については、[認証](developer-cli-authentication)を参照してください。 ::: ## グローバルフラグ \{#global-flags\} これらのフラグはすべてのコマンドで使用できます。 | フラグ | 説明 | |---|---| | `--json` | フォーマットテキストの代わりにJSONで出力する | | `--help` | コマンドのヘルプを表示する | すべての `list` コマンドではページネーションフラグも使用できます: | フラグ | デフォルト | 説明 | |---|---|---| | `--page` | `1` | ページ番号 | | `--page-size` | `20` | 1ページあたりのアイテム数(最大:100) | ## アプリ \{#apps\} Adaptyアカウント内のアプリを管理します。ダッシュボードベースの設定については、[App settings](general)を参照してください。 ### adapty apps list \{#adapty-apps-list\} Adaptyアカウント内のすべてのアプリを一覧表示します。 ```bash adapty apps list ``` [ページネーションフラグ](#global-flags)を使用できます。 ### adapty apps get \{#adapty-apps-get\} 特定のアプリの詳細を取得します。 ```bash adapty apps get ``` | 引数 | 説明 | |---|---| | `app-id` | アプリID(UUID) | ### adapty apps create \{#adapty-apps-create\} 新しいアプリを作成します。 ```bash adapty apps create --title "My App" --platform ios --apple-bundle-id com.example.app ``` | フラグ | 必須 | 説明 | |---|---|---| | `--title` | はい | アプリのタイトル | | `--platform` | はい | プラットフォーム:`ios` または `android`。両方指定する場合は繰り返す:`--platform ios --platform android` | | `--apple-bundle-id` | `--platform ios` 指定時に必須 | AppleバンドルID | | `--google-bundle-id` | `--platform android` 指定時に必須 | GoogleバンドルID | ### adapty apps update \{#adapty-apps-update\} 既存のアプリを更新します。 ```bash adapty apps update --title "New Name" ``` | 引数 | 説明 | |---|---| | `app-id` | アプリID(UUID) | | フラグ | 説明 | |---|---| | `--title` | 新しいアプリタイトル | | `--apple-bundle-id` | 新しいAppleバンドルID | | `--google-bundle-id` | 新しいGoogleバンドルID | 少なくとも1つのフラグが必要です。`--platform` は作成後に変更できません。 ## アクセスレベル \{#access-levels\} ### adapty access-levels list \{#adapty-access-levels-list\} アプリのすべての[アクセスレベル](access-level)を一覧表示します。 ```bash adapty access-levels list --app ``` | フラグ | 必須 | 説明 | |---|---|---| | `--app` | はい | アプリID(UUID) | [ページネーションフラグ](#global-flags)を使用できます。 ### adapty access-levels get \{#adapty-access-levels-get\} 特定の[アクセスレベル](access-level)の詳細を取得します。 ```bash adapty access-levels get --app ``` | 引数 | 説明 | |---|---| | `access-level-id` | アクセスレベルID(UUID) | | フラグ | 必須 | 説明 | |---|---|---| | `--app` | はい | アプリID(UUID) | ### adapty access-levels create \{#adapty-access-levels-create\} 新しい[アクセスレベル](access-level)を作成します。 ```bash adapty access-levels create --app --sdk-id "pro" --title "Pro" ``` | フラグ | 必須 | 説明 | |---|---|---| | `--app` | はい | アプリID(UUID) | | `--sdk-id` | はい | アプリコード内でアクセス確認に使用する識別子(例:`"pro"` や `"premium"`) | | `--title` | はい | Adaptyダッシュボードに表示されるラベル | ### adapty access-levels update \{#adapty-access-levels-update\} 既存の[アクセスレベル](access-level)を更新します。 ```bash adapty access-levels update --app --title "Pro Access" ``` | 引数 | 説明 | |---|---| | `access-level-id` | アクセスレベルID(UUID) | | フラグ | 必須 | 説明 | |---|---|---| | `--app` | はい | アプリID(UUID) | | `--title` | はい | 新しい表示ラベル | `--sdk-id` は作成後に変更できません。 ## プロダクト \{#products\} ### adapty products list \{#adapty-products-list\} アプリのすべての[プロダクト](product)を一覧表示します。 ```bash adapty products list --app ``` | フラグ | 必須 | 説明 | |---|---|---| | `--app` | はい | アプリID(UUID) | [ページネーションフラグ](#global-flags)を使用できます。 ### adapty products get \{#adapty-products-get\} 特定の[プロダクト](product)の詳細を取得します。 ```bash adapty products get --app ``` | 引数 | 説明 | |---|---| | `product-id` | プロダクトID(UUID) | | フラグ | 必須 | 説明 | |---|---|---| | `--app` | はい | アプリID(UUID) | ### adapty products create \{#adapty-products-create\} 新しい[プロダクト](product)を作成します。 :::important ストアのプロダクトID(`--ios-product-id`、`--android-product-id`、`--android-base-plan-id`)は作成後に変更できません。異なるストアプロダクトIDを使用したい場合は、新しいプロダクトを作成してください。 ::: ```bash adapty products create --app --title "Monthly" --access-level-id --period monthly --ios-product-id com.example.monthly ``` | フラグ | 必須 | 説明 | |---|---|---| | `--app` | はい | アプリID(UUID) | | `--title` | はい | プロダクトタイトル | | `--access-level-id` | はい | このプロダクトがアンロックする[アクセスレベル](access-level)ID(UUID) | | `--period` | はい | サブスクリプション期間:`weekly`、`monthly`、`2_months`、`3_months`、`6_months`、`yearly`、`lifetime` | | `--ios-product-id` | 少なくとも1つのプラットフォームが必須 | App Store ConnectのプロダクトID | | `--android-product-id` | 少なくとも1つのプラットフォームが必須 | Google Play ConsoleのプロダクトID | | `--android-base-plan-id` | `--android-product-id` 指定時に必須(`--period lifetime` の場合を除く) | Google Play ConsoleのベースプランID | ### adapty products update \{#adapty-products-update\} 既存の[プロダクト](product)を更新します。 ストアのプロダクトID(`--ios-product-id`、`--android-product-id`)は作成後に変更できないため、このコマンドでは使用できません。異なるストアプロダクトIDを使用したい場合は、新しいプロダクトを作成してください。 ```bash adapty products update --app --title "Monthly" --access-level-id ``` | 引数 | 説明 | |---|---| | `product-id` | プロダクトID(UUID) | | フラグ | 必須 | 説明 | |---|---|---| | `--app` | はい | アプリID(UUID) | | `--title` | いいえ | プロダクトタイトル | | `--access-level-id` | いいえ | このプロダクトがアンロックする[アクセスレベル](access-level)ID(UUID) | ## ペイウォール \{#paywalls\} ### adapty paywalls list \{#adapty-paywalls-list\} アプリのすべての[ペイウォール](paywalls)を一覧表示します。 ```bash adapty paywalls list --app ``` | フラグ | 必須 | 説明 | |---|---|---| | `--app` | はい | アプリID(UUID) | [ページネーションフラグ](#global-flags)を使用できます。 ### adapty paywalls get \{#adapty-paywalls-get\} 特定の[ペイウォール](paywalls)の詳細を取得します。 ```bash adapty paywalls get --app ``` | 引数 | 説明 | |---|---| | `paywall-id` | ペイウォールID(UUID) | | フラグ | 必須 | 説明 | |---|---|---| | `--app` | はい | アプリID(UUID) | ### adapty paywalls create \{#adapty-paywalls-create\} 新しい[ペイウォール](paywalls)を作成します。 ```bash adapty paywalls create --app --title "Default Paywall" --product-id ``` | フラグ | 必須 | 説明 | |---|---|---| | `--app` | はい | アプリID(UUID) | | `--title` | はい | ペイウォールタイトル | | `--product-id` | はい | [プロダクト](product)ID(UUID)。複数指定する場合は繰り返す:`--product-id --product-id ` | ### adapty paywalls update \{#adapty-paywalls-update\} 既存の[ペイウォール](paywalls)のすべてのフィールドを置き換えます。 :::important ペイウォールがプレースメントに紐付けられると、そのプロダクトは変更できません。本番稼働中のペイウォールで異なるプロダクトを使用したい場合は、新しいペイウォールを作成し、プレースメントがそちらを参照するよう更新してください。 ::: ```bash adapty paywalls update --app --title "Default Paywall" --product-id ``` このコマンドはプロダクトリスト全体を含む、ペイウォールのすべてのフィールドを置き換えます。 | 引数 | 説明 | |---|---| | `paywall-id` | ペイウォールID(UUID) | | フラグ | 必須 | 説明 | |---|---|---| | `--app` | はい | アプリID(UUID) | | `--title` | はい | ペイウォールタイトル | | `--product-id` | はい | [プロダクト](product)ID(UUID)。複数指定する場合は繰り返す:`--product-id --product-id ` | ### adapty paywalls placements \{#adapty-paywalls-placements\} 指定した[ペイウォール](paywalls)を現在使用しているすべての[プレースメント](placements)を一覧表示します。 ```bash adapty paywalls placements --app ``` | 引数 | 説明 | |---|---| | `paywall-id` | ペイウォールID(UUID) | | フラグ | 必須 | 説明 | |---|---|---| | `--app` | はい | アプリID(UUID) | ペイウォールを切り替える前に、このコマンドで影響を受けるプレースメントを確認してください。 ## プレースメント \{#placements\} ### adapty placements list \{#adapty-placements-list\} アプリのすべての[プレースメント](placements)を一覧表示します。 ```bash adapty placements list --app ``` | フラグ | 必須 | 説明 | |---|---|---| | `--app` | はい | アプリID(UUID) | [ページネーションフラグ](#global-flags)を使用できます。 ### adapty placements get \{#adapty-placements-get\} 特定の[プレースメント](placements)の詳細を取得します。 ```bash adapty placements get --app ``` | 引数 | 説明 | |---|---| | `placement-id` | プレースメントID(UUID) | | フラグ | 必須 | 説明 | |---|---|---| | `--app` | はい | アプリID(UUID) | レスポンスには `audiences` 配列が含まれます。各エントリは `{segment_ids, paywall_id, priority}` の形式です。デフォルトのオーディエンスは `segment_ids: []` を持ち、最も高いpriorityの値(最後に評価される)を持ちます。フォーマット済みの人間向け出力には、便宜上デフォルトオーディエンスから導出したトップレベルの `Paywall ID` も表示されます。`--json` を使用すると、加工されていないAPIレスポンスがそのまま返されます。 ### adapty placements create \{#adapty-placements-create\} 新しい[プレースメント](placements)を作成します。 ```bash adapty placements create --app --title "Main" --developer-id "main" --audiences '[{"segment_ids":[],"paywall_id":"","priority":0}]' ``` | フラグ | 必須 | 説明 | |---|---|---| | `--app` | はい | アプリID(UUID) | | `--title` | はい | プレースメントタイトル | | `--developer-id` | はい | アプリコード内でこの[プレースメント](placements)をリクエストする際に使用する文字列識別子 | | `--audiences` | どちらか一方 | `{segment_ids, paywall_id, priority}` エントリのJSON配列。[オーディエンスの形式](#audiences-shape)を参照 | | `--paywall-id` | どちらか一方 | **非推奨。** [ペイウォール](paywalls)ID(UUID)。クライアント側で単一のデフォルトオーディエンスにラップされます | `--audiences` または `--paywall-id` のいずれか一方のみを指定してください。両方指定または両方省略するとエラーになります。 :::warning `--paywall-id` は非推奨であり、今後削除される予定です。指定した場合、CLIはstderrに警告を出力し、値をデフォルトオーディエンスに変換します。新しい自動化処理では `--audiences` を使用してください。 ::: ### adapty placements update \{#adapty-placements-update\} 既存の[プレースメント](placements)のすべてのフィールドを置き換えます。 ```bash adapty placements update --app --title "Main" --developer-id "main" --audiences '[{"segment_ids":[],"paywall_id":"","priority":0}]' ``` このコマンドはオーディエンスリスト全体を含む、プレースメントのすべてのフィールドを置き換えます。 | 引数 | 説明 | |---|---| | `placement-id` | プレースメントID(UUID) | | フラグ | 必須 | 説明 | |---|---|---| | `--app` | はい | アプリID(UUID) | | `--title` | はい | プレースメントタイトル | | `--developer-id` | はい | アプリコード内でこの[プレースメント](placements)をリクエストする際に使用する文字列識別子 | | `--audiences` | どちらか一方 | `{segment_ids, paywall_id, priority}` エントリのJSON配列。[オーディエンスの形式](#audiences-shape)を参照 | | `--paywall-id` | どちらか一方 | **非推奨。** [ペイウォール](paywalls)ID(UUID)。すべてのオーディエンスを単一のデフォルトオーディエンスで置き換えます | :::warning `--paywall-id` を指定すると、プレースメントのすべてのオーディエンスが上書きされます。セグメント固有のオーディエンスは削除されます。それらを保持したい場合は `--audiences` を使用し、維持したいすべてのエントリを含めてください。 ::: #### オーディエンスの形式 \{#audiences-shape\} `--audiences` フラグはJSON配列を受け取ります。各エントリには以下のフィールドがあります: | フィールド | 型 | 説明 | |---|---|---| | `segment_ids` | `string[]` | このオーディエンスが対象とする[セグメント](segments)IDの配列。要素数は0または1。空配列は**デフォルトオーディエンス**(他のセグメントにマッチしないユーザーへのフォールバック)を表します | | `paywall_id` | `string` | このオーディエンスのユーザーに表示される[ペイウォール](paywalls)ID(UUID) | | `priority` | `number` | 0始まりで、プレースメント内で一意。オーディエンスは値の小さい順に評価され、デフォルトオーディエンスは最も高い値を持つ必要があります | プレースメントには必ずデフォルトオーディエンスが1つ必要です。 1つのターゲットオーディエンスと1つのデフォルトオーディエンスを持つ例: ```bash adapty placements update --app --title "Main" --developer-id "main" \ --audiences '[{"segment_ids":[""],"paywall_id":"","priority":0},{"segment_ids":[],"paywall_id":"","priority":1}]' ``` セグメント固有のルーティングを維持しながら複数のプレースメントでペイウォールを切り替えるには: 1. 影響を受けるプレースメントを確認する: ```bash adapty paywalls placements --app ``` 2. それぞれの `audiences` 配列全体を取得する: ```bash adapty placements get --app --json ``` 3. 対象の `paywall_id` の値をクライアント側で置き換える。 4. 変更したペイロードを書き戻す: ```bash adapty placements update --app --title "" --developer-id "<developer-id>" --audiences '<modified-payload>' ``` ## セグメント \{#segments\} [セグメント](segments)はCLI経由では読み取り専用です。作成・編集は[Adaptyダッシュボード](https://app.adapty.io)で行ってください。プレースメントのオーディエンスを構成する際にセグメントIDを調べるためにこれらのコマンドを使用します。 ### adapty segments list \{#adapty-segments-list\} アプリのすべての[セグメント](segments)を一覧表示します。 ```bash adapty segments list --app <app-id> ``` | フラグ | 必須 | 説明 | |---|---|---| | `--app` | はい | アプリID(UUID) | [ページネーションフラグ](#global-flags)を使用できます。 ### adapty segments get \{#adapty-segments-get\} 特定の[セグメント](segments)の詳細を取得します。 ```bash adapty segments get --app <app-id> <segment-id> ``` | 引数 | 説明 | |---|---| | `segment-id` | セグメントID(UUID) | | フラグ | 必須 | 説明 | |---|---|---| | `--app` | はい | アプリID(UUID) | レスポンスには `id`、`title`、`description` が含まれます。フィルタールールはこのAPIでは公開されていません。 ## 認証 \{#auth\} | コマンド | 説明 | |---|---| | `adapty auth login` | デバイスフローを使用してブラウザ経由で認証する | | `adapty auth logout` | ローカルに保存された認証情報を削除する | | `adapty auth whoami` | サーバーでトークンを検証してユーザー情報を表示する | | `adapty auth status` | サーバーへの問い合わせなしにローカルの認証状態を表示する | | `adapty auth revoke` | サーバー側でトークンを失効させ、ローカルからも削除する | 各コマンドの詳細については[認証](developer-cli-authentication)を参照してください。 --- # File: getting-started-with-server-side-api --- --- title: "サーバーサイド API" description: "サブスクリプション管理のための Adapty サーバーサイド API を使ってみましょう。" --- :::tip AI コーディングエージェントを使っていますか?[バックエンドからサブスクリプションアクセスを確認・付与する](server-side-api-with-ai)に、一つのページにまとめたエンドツーエンドのレシピがあります。 ::: この API を使うと、以下のことができます: 1. ユーザーのサブスクリプション状態を確認する。 2. アクセスレベルでユーザーのサブスクリプションを有効化する。 3. ユーザー属性を取得する。 4. ユーザー属性を設定する。 5. ペイウォール設定を取得・更新する。 <img src="/assets/shared/img/server.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> <p> </p> :::note サブスクリプションイベントを追跡するには、Adapty の [Webhook](webhook) 連携を利用するか、既存のサービスと直接連携してください。 ::: ## ウェブとモバイル間でサブスクライバーを同期する場合 \{#case-1-sync-subscribers-between-web-and-mobile\} StripeやChargeBeeなどのWeb決済プロバイダーを使用している場合、サブスクリプションユーザーを簡単に同期できます。手順は以下のとおりです: 1. <InlineTooltip tooltip="各ユーザーに一意のIDを割り当てる">[iOS](identifying-users)、[Android](android-identifying-users)、[React Native](react-native-identifying-users)、[Flutter](flutter-identifying-users)、[Unity](unity-identifying-users)</InlineTooltip> 2. APIを使用して[サブスクリプションのステータスを確認する](api-adapty/operations/getProfile)。 3. ユーザーがフリーミアムプランの場合、Webサイトにペイウォールを表示する。 4. 決済が完了したら、APIを通じてAdaptyの[サブスクリプションステータスを更新する](api-adapty/operations/setTransaction)。 5. サブスクリプションユーザーはモバイルアプリと自動的に同期されます。 ## Case 2: サブスクリプションを付与する \{#case-2-grant-a-subscription\} :::note セキュリティ上の理由から、SDK を使ってサブスクリプションを付与することはできません。 ::: Google Play や App Store 以外のプラットフォーム(独自のオンラインストア、Amazon Appstore、Microsoft Store など)で販売している場合は、アクセス権の付与とアナリティクスでのトランザクション追跡を行うために、それらのトランザクションを Adapty と同期する必要があります。 1. <InlineTooltip tooltip="各ユーザーに固有のIDを割り当てる">[iOS](identifying-users)、[Android](android-identifying-users)、[React Native](react-native-identifying-users)、[Flutter](flutter-identifying-users)、[Unity](unity-identifying-users)</InlineTooltip> 2. [Adapty ダッシュボードでプロダクトのカスタムストアを設定する](custom-store)。 3. [Set transaction](api-adapty/operations/setTransaction) API リクエストを使用して、トランザクションを Adapty に同期する。 ## ケース3: アクセスレベルを付与する \{#case-3-grant-an-access-level\} 7日間の無料トライアルプロモーションを実施していて、プラットフォーム間で一貫したエクスペリエンスを提供したいとします。モバイルアプリと同期するには: 1. <InlineTooltip tooltip="各ユーザーに一意のIDを割り当てる">[iOS](identifying-users)、[Android](android-identifying-users)、[React Native](react-native-identifying-users)、[Flutter](flutter-identifying-users)、[Unity](unity-identifying-users)</InlineTooltip>。 2. APIを使用して、7日間の[プレミアムアクセスを付与](api-adapty/operations/grantAccessLevel)します。 7日間が経過しても購読しないユーザーは、無料プランにダウングレードされます。 ## ケース4: ユーザーのプロパティとカスタム属性を同期する \{#case-4-sync-users-properties-and-custom-attributes\} 言語学習アプリで学習した単語数など、ユーザー独自のカスタム属性がある場合も同期できます。 1. <InlineTooltip tooltip="各ユーザーに一意のIDを割り当てる">[iOS](identifying-users)、[Android](android-identifying-users)、[React Native](react-native-identifying-users)、[Flutter](flutter-identifying-users)、[Unity](unity-identifying-users)</InlineTooltip>。 2. APIまたはSDKで[属性を更新](api-adapty/operations/updateProfile)する。 これらのカスタム属性を使用して、セグメントを作成したり A/B テストを実行したりできます。 ## ケース5: ペイウォール設定を管理する \{#case-5-manage-paywall-configurations\} アプリを再デプロイすることなく、ペイウォールの外観や動作を動的に変更するために、[ペイウォールのリモートコンフィグを更新](api-adapty/operations/updatePaywall)できます。 --- **次のステップ:** - [サーバーサイド API の認証](ss-authorization)に進む - リクエスト: - [プロファイルを取得する](api-adapty/operations/getProfile) - [プロファイルを作成する](api-adapty/operations/createProfile) - [プロファイルを更新する](api-adapty/operations/updateProfile) - [プロファイルを削除する](api-adapty/operations/deleteProfile) - [アクセスレベルを付与する](api-adapty/operations/grantAccessLevel) - [アクセスレベルを取り消す](api-adapty/operations/revokeAccessLevel) - [トランザクションを設定する](api-adapty/operations/setTransaction) - [購入を検証し、顧客にアクセスレベルを付与し、トランザクション履歴をインポートする](api-adapty/operations/validateStripePurchase) - [インテグレーション識別子を追加する](api-adapty/operations/setIntegrationIdentifiers) - [ペイウォールを取得する](api-adapty/operations/getPaywall) - [ペイウォール一覧を取得する](api-adapty/operations/listPaywalls) - [ペイウォールを更新する](api-adapty/operations/updatePaywall) --- # File: ss-authorization --- --- title: "サーバーサイド API の認証とリクエスト形式" description: "" --- ## 認証 \{#authorization\} API リクエストは、シークレットキーまたはパブリック API キーを Authorization ヘッダーとして使用して認証する必要があります。これらのキーは [**App Settings**](https://app.adapty.io/settings/general) で確認できます。値の形式は `Api-Key {your-secret-api-key}` で、例えば `Api-Key secret_live_...` のようになります。 :::important API キーはアプリごとに固有です。複数のアプリを持っている場合は、それぞれに異なるキーを使用してください。 ::: ## リクエスト形式 \{#request-format\} **ヘッダー** サーバーサイド API リクエストには特定のヘッダーと JSON ボディが必要です。以下の詳細を参考にリクエストを構成してください。 | **ヘッダー** | **説明** | | --------------------------- | ------------------------------------------------------------ | | **adapty-profile-id** | <p>ユーザーの Adapty プロファイル ID。[Adapty Dashboard -> **Profiles**](https://app.adapty.io/profiles/users) -> 特定のプロファイルページの **Adapty ID** フィールドで確認できます。</p><p>**adapty-customer-user-id** と互換性があり、どちらでも使用できます。</p> | | **adapty-customer-user-id** | <p>あなたのシステムにおけるユーザー ID。[Adapty Dashboard -> **Profiles**](https://app.adapty.io/profiles/users) -> 特定のプロファイルページの **Customer user ID** フィールドで確認できます。</p><p>**adapty-profile-id** と互換性があり、どちらでも使用できます。</p><p>⚠️ Adapty SDK を使用してアプリコード内で<InlineTooltip tooltip="アプリ内でユーザーを識別する">[iOS](identifying-users)、[Android](android-identifying-users)、[React Native](react-native-identifying-users)、[Flutter](flutter-identifying-users)、[Unity](unity-identifying-users)</InlineTooltip>している場合にのみ機能します。</p> | | **adapty-platform** | (任意)アプリがインストールされているデバイスのプラットフォームを指定します。[Installation Meta](server-side-api-objects#installation-meta) オブジェクトを変更する [Create profile](api-adapty/operations/createProfile) および [Update profile](api-adapty/operations/updateProfile) リクエストでは、このパラメータを設定することを推奨します。これはユーザーが使用しているデバイスに依存し、1 人のユーザーが複数のデバイスを持つ場合があるためです。指定できる値: `iOS`、`macOS`、`iPadOS`、`visionOS`、`Android`、`web`。 | | **Content-Type** | API がリクエストを処理するために `application/json` に設定してください。 | **ボディ** API はリクエストに必要なデータを含む JSON 形式のボディを想定しています。 ## レート制限 \{#rate-limits\} スロットリングを避けるために、(アプリごとの)リクエスト数を 1 分あたり 40,000 件以下に抑えてください。 この制限を超えると、すべてのユーザーに最適なパフォーマンスを維持するために、システムが低速化したり、リクエストが一時的にブロックされる場合があります。 ## API キーのローテーション \{#rotate-api-keys\} シークレット API キーをローテーションする必要がある場合: 1. **Settings → General** で **Generate new key** をクリックし、古いキーの横にあるゴミ箱アイコンをクリックします。 2. アプリで使用しているキーを更新します。 --- **次のステップ: リクエスト:** - [プロファイルの取得](api-adapty/operations/getProfile) - [プロファイルの作成](api-adapty/operations/createProfile) - [プロファイルの更新](api-adapty/operations/updateProfile) - [プロファイルの削除](api-adapty/operations/deleteProfile) - [アクセスレベルの付与](api-adapty/operations/grantAccessLevel) - [アクセスレベルの取り消し](api-adapty/operations/revokeAccessLevel) - [トランザクションの設定](api-adapty/operations/setTransaction) - [購入の検証、顧客へのアクセスレベルの付与、およびトランザクション履歴のインポート](api-adapty/operations/validateStripePurchase) - [ペイウォールの取得](api-adapty/operations/getPaywall) - [ペイウォール一覧の取得](api-adapty/operations/listPaywalls) - [ペイウォールの更新](api-adapty/operations/updatePaywall) --- # File: server-side-api-specs --- --- title: "サーバーサイドAPIリクエスト" description: "高度な統合のためのAdaptyのサーバーサイドAPI仕様を探索してください。" --- AdaptyのサーバーサイドAPIを使用すると、サブスクリプションデータにプログラムでアクセスして管理でき、既存のサービスやインフラとのシームレスな統合が可能です。プラットフォーム間のデータ同期、アクセスレベルの付与、Stripeでの購入検証など、システムを同期させてユーザーエンゲージメントを維持するためのツールを提供します。 ## Postmanコレクションと環境 \{#postman-collection-and-environment\} サーバーサイドAPIの利用を簡単にするため、PostmanにダウンロードしてインポートできるPostmanコレクションと環境ファイルを用意しました。 - **リクエストコレクション**: AdaptyサーバーサイドAPIで利用可能なすべてのリクエストが含まれています。環境で定義できる変数を使用していることに注意してください。 - **環境**: 値を一度定義できる変数のリストが含まれています。サーバーサイドAPI、Web API、アナリティクスエクスポートAPIに対応した統合環境を用意しており、作業を簡単に進められます。この環境をアクティブにすると、Postmanがリクエスト内の定義済み変数値を自動的に置換します。 :::tip [コレクションと環境をダウンロード](https://raw.githubusercontent.com/adaptyteam/adapty-docs/refs/heads/main/Downloads/Adapty_server_side_API_postman_collection.zip) ::: PostmanへのコレクションおよびEnvironmentのインポート方法については、[Postmanドキュメント](https://learning.postman.com/docs/getting-started/importing-and-exporting/importing-data/)を参照してください。 ### 使用される変数 \{#variables-used\} サーバーサイドAPI、Web API、アナリティクスエクスポートAPIのワークフローを簡略化するため、統合環境を作成しました。以下はサーバーサイドAPI固有の変数です: | 変数 | 説明 | 値の例 | | ----------------------- | ------------------------------------------------------------ | ------------------------------------------------------- | | secret_api_key | [**App settings**](https://app.adapty.io/settings/general)の **Secret key** フィールドで確認できます。 | `secret_live_Pj1P1xzM.2CvSvE1IalQRFjsWy6csBVNpH33atnod` | | adapty-customer-user-id | あなたのシステムで使用しているユーザーID。Adapty ダッシュボードでは、プロファイルの **Customer user ID** フィールドで確認できます。 | `john.doe@example.com` | | adapty-profile-id | Adaptyが割り当てたユーザーID。Adapty ダッシュボードでは、プロファイルの **Adapty ID** フィールドで確認できます。 | `3286abd3-48b0-4e9c-a5f6-ac0a006333a6` | | Adapty-platform | ユーザーがアプリに使用するプラットフォーム。使用可能な値: `iOS`, `macOS`, `iPadOS`, `visionOS`, `Android`, `web`。 | `iOS` | | stripe_token | サブスクリプション(`sub_XXX`)やPayment Intent(`pi_XXX`)などの一意の購入を表すStripeオブジェクトのトークン。 | `sub_1JY8xLLy6P12345a` | **次のステップ:リクエスト:** - [プロファイルを取得](api-adapty/operations/getProfile) - [プロファイルを作成](api-adapty/operations/createProfile) - [プロファイルを更新](api-adapty/operations/updateProfile) - [プロファイルを削除](api-adapty/operations/deleteProfile) - [アクセスレベルを付与](api-adapty/operations/grantAccessLevel) - [アクセスレベルを失効](api-adapty/operations/revokeAccessLevel) - [トランザクションを設定](api-adapty/operations/setTransaction) - [購入を検証し、顧客にアクセスレベルを付与して、トランザクション履歴をインポート](api-adapty/operations/validateStripePurchase) - [統合識別子を追加](api-adapty/operations/setIntegrationIdentifiers) - [ペイウォールを取得](api-adapty/operations/getPaywall) - [ペイウォールを一覧表示](api-adapty/operations/listPaywalls) - [ペイウォールを更新](api-adapty/operations/updatePaywall) --- # File: api-guides --- --- title: "API guides" description: "Learn how to perform specific tasks using the server-side API." --- In this section, you can find guides that cover different use cases and help you perform specific tasks using the server-side API and the Adapty SDK. <CustomDocCardList /> --- # File: sync-subscribers-from-web --- --- title: "WebとモバイルのサブスクリプションをSync Purchasesで同期する" description: "WebとモバイルのサブスクライバーをSync Purchasesで同期します。" --- ユーザーが**ウェブサイト**でプロダクトを購入できる場合、**モバイルアプリ**とのアクセスレベルを自動的に同期できます。 このガイドでは、Adapty の API と SDK を使ってその方法を説明します。 #### ユースケースの例 例えば、アプリでユーザーがモバイルとウェブの両方でフリーミアムプランにサインアップできるとします。ウェブサイト上で Stripe や Chargebee を使って Premium プランへのアップグレードを許可している場合、ユーザーがウェブでサブスクリプションを購入したら、再ログインや待機なしにモバイルアプリでも即座に Premium アクセスを利用できるようにしたいはずです。 それを Adapty で自動化できます。 ## ステップ 1. ユーザーを識別する \{#step-1-identify-users\} Adapty はプラットフォーム間でユーザーを識別するために `customer_user_id` を使用します。 この ID は一度だけ作成し、モバイル SDK とウェブバックエンドの両方に渡してください。 ### ウェブからのサインアップ \{#sign-up-from-web\} ユーザーがウェブサイトでサインアップした際、サーバーサイド API を使って Adapty にプロファイルを作成する必要があります。 メソッドのリファレンスは[こちら](api-adapty/operations/createProfile)をご覧ください。 ```bash curl --request POST \ --url https://api.adapty.io/api/v2/server-side-api/profile/ \ --header 'Accept: application/json' \ --header 'Authorization: Api-Key YOUR_SECRET_API_KEY' \ --header 'Content-Type: application/json' \ --header 'adapty-customer-user-id: YOUR_CUSTOMER_USER_ID' ``` ### アプリからのサインアップ \{#sign-up-from-app\} ユーザーがアプリから初めてサインアップする場合、SDK のアクティベーション時に customer user ID を渡すか、サインアップ前に Adapty SDK をアクティベートしている場合は `identify` メソッドを使って新しいプロファイルを作成し、customer user ID を割り当てます。 :::important SDK のアクティベーション後にユーザーを識別する場合、SDK はプロファイルなしでは動作できないため、まず匿名プロファイルが作成されます。その後、ユーザーを識別して新しい customer user ID を割り当てると、新しいプロファイルが作成されます。 この動作は完全に正常であり、分析の精度には影響しません。詳しくは[こちら](ios-quickstart-identify)をご覧ください。 ::: <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS" default> ```swift showLineNumbers do { try await Adapty.identify("YOUR_USER_ID") // Unique for each user } catch { // handle the error } ``` </TabItem> <TabItem value="swift-callback" label="iOS (Swift-Callback)" default> ```swift showLineNumbers // User IDs must be unique for each user Adapty.identify("YOUR_USER_ID") { error in if let error { // handle the error } } ``` </TabItem> <TabItem value="android" label="Android (Kotlin)" default> ```kotlin showLineNumbers Adapty.identify("YOUR_USER_ID") { error -> // Unique for each user if (error == null) { // successful identify } } ``` </TabItem> <TabItem value="java" label="Android (Java)" default> ```java showLineNumbers // User IDs must be unique for each user Adapty.identify("YOUR_USER_ID", error -> { if (error == null) { // successful identify } }); ``` </TabItem> <TabItem value="react-native" label="React Native" default> ```typescript showLineNumbers try { await adapty.identify("YOUR_USER_ID"); // Unique for each user // successfully identified } catch (error) { // handle the error } ``` </TabItem> <TabItem value="flutter" label="Flutter" default> ```dart showLineNumbers try { await Adapty().identify(customerUserId); // Unique for each user } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` </TabItem> <TabItem value="unity" label="Unity" default> ```csharp showLineNumbers Adapty.Identify("YOUR_USER_ID", (error) => { // Unique for each user if(error == null) { // successful identify } }); ``` </TabItem> <TabItem value="kmp" label="Kotlin Multiplatform" default> ```kotlin showLineNumbers Adapty.identify("YOUR_USER_ID") // Unique for each user .onSuccess { // successful identify } .onError { error -> // handle the error } ``` </TabItem> <TabItem value="capacitor" label="Capacitor" default> ```typescript showLineNumbers try { await adapty.identify({ customerUserId: "YOUR_USER_ID" }); // successfully identified } catch (error) { // handle the error } ``` </TabItem> </Tabs> ## ステップ 2. API でサブスクリプションのステータスを確認する \{#step-2-check-subscription-status-via-api\} ユーザーがウェブサイトにログインしたら、API を使って Adapty プロファイルを取得します。 アクティブなサブスクリプションがない場合は、ペイウォールを表示できます。 メソッドのリファレンスは[こちら](api-adapty/operations/getProfile)をご覧ください。 ```bash curl --request GET \ --url https://api.adapty.io/api/v2/server-side-api/profile/ \ --header 'Accept: application/json' \ --header 'Authorization: Api-Key YOUR_SECRET_API_KEY' \ --header 'adapty-customer-user-id: YOUR_USER_ID' \ ``` ## ステップ 3. ウェブサイトにペイウォールを表示する \{#step-3-display-a-paywall-on-your-website\} フリーミアムユーザー向けにウェブサイトでペイウォールを表示します。 決済プロバイダーは任意のものが使用できます(Stripe、Chargebee、LemonSqueezy など)。 ## ステップ 4. Adapty のサブスクリプションステータスを更新する \{#step-4-update-subscription-status-in-adapty\} ウェブサイトでの支払いが完了したら、Adapty API を呼び出して、ユーザーが購入したプロダクトに応じてアクセスレベルを更新します。 メソッドのリファレンスは[こちら](api-adapty/operations/grantAccessLevel)をご覧ください。 ```bash curl --request POST \ --url https://api.adapty.io/api/v2/server-side-api/purchase/profile/grant/access-level/ \ --header 'Accept: application/json' \ --header 'Authorization: Api-Key YOUR_SECRET_API_KEY' \ --header 'Content-Type: application/json' \ --header 'adapty-customer-user-id: YOUR_USER_ID' \ --data '{ "access_level_id": "YOUR_ACCESS_LEVEL" }' ``` ## ステップ 5. アプリでステータスを同期する \{#step-5-sync-status-in-the-app\} ユーザーがモバイルアプリを開いたら、更新されたプロファイルを取得して有料機能を解放します。 プロファイルを手動で取得するか、自動で同期する必要があります。その後、プロファイルからアクセスレベルを取得します。 以下では、プロファイルを取得してそのステータスを確認する方法を示します。詳細は[こちら](ios-check-subscription-status)をご覧ください。 <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS" default> ```swift showLineNumbers do { let profile = try await Adapty.getProfile() if profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false { // grant access to premium features } } catch { // handle the error } ``` </TabItem> <TabItem value="swift-callback" label="iOS (Swift-Callback)" default> ```swift showLineNumbers Adapty.getProfile { result in if let profile = try? result.get() { // check the access if profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false { // grant access to premium features } } } ``` </TabItem> <TabItem value="android" label="Android (Kotlin)" default> ```kotlin showLineNumbers Adapty.getProfile { result -> when (result) { is AdaptyResult.Success -> { val profile = result.value // check the access if (profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive == true) { // grant access to premium features } } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` </TabItem> <TabItem value="java" label="Android (Java)" default> ```java showLineNumbers Adapty.getProfile(result -> { if (result instanceof AdaptyResult.Success) { AdaptyProfile profile = ((AdaptyResult.Success<AdaptyProfile>) result).getValue(); // check the access if (profile.getAccessLevels().get("YOUR_ACCESS_LEVEL") != null && profile.getAccessLevels().get("YOUR_ACCESS_LEVEL").getIsActive()) { // grant access to premium features } } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // handle the error } }); ``` </TabItem> <TabItem value="react-native" label="React Native" default> ```typescript showLineNumbers try { const profile = await adapty.getProfile(); // check the access if (profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive) { // grant access to premium features } } catch (error) { // handle the error } ``` </TabItem> <TabItem value="flutter" label="Flutter" default> ```dart showLineNumbers try { final profile = await Adapty().getProfile(); // check the access if (profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false) { // grant access to premium features } } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` </TabItem> <TabItem value="unity" label="Unity" default> ```csharp showLineNumbers Adapty.GetProfile((profile, error) => { if (error != null) { // handle the error return; } // check the access if (profile.AccessLevels["YOUR_ACCESS_LEVEL"]?.IsActive ?? false) { // grant access to premium features } }); ``` </TabItem> <TabItem value="kmp" label="Kotlin Multiplatform" default> ```kotlin showLineNumbers Adapty.getProfile() .onSuccess { profile -> // check the access if (profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive == true) { // grant access to premium features } } .onError { error -> // handle the error } ``` </TabItem> <TabItem value="capacitor" label="Capacitor" default> ```typescript showLineNumbers try { const profile = await adapty.getProfile(); // check the access if (profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive) { // grant access to premium features } } catch (error) { // handle the error } ``` </TabItem> </Tabs> --- # File: sync-purchases-from-custom-stores --- --- title: "カスタムストアのトランザクションを同期する" description: "カスタムストアのトランザクションを Adapty に同期して、アクセス管理と収益追跡を行います。" --- Amazon Appstore、Microsoft Store、または独自の決済プラットフォームなど、**カスタムストア**でサブスクリプションやアプリ内課金を販売している場合、それらのトランザクションを Adapty に同期することで、アクセスレベルの自動管理と収益のアナリティクス追跡が可能になります。 このガイドでは、SDK と API を使ってカスタムストアの購入を Adapty に連携する方法を説明します。 #### ユースケースの例 Amazon Appstore でアプリを配信している場合や、直接購入用の独自 Web ストアを構築している場合を考えてみましょう。ユーザーがこれらのプラットフォームで購入を完了したとき、次のことを実現したいはずです。 - モバイルアプリのプレミアム機能へのアクセスを自動的に付与する - App Store や Google Play の収益と並べて、Adapty アナリティクスでトランザクションを追跡する - 他のサブスクリプションと同様に、インテグレーションやウェブフックをトリガーする この連携によってそれらが実現できます。 ## ステップ 1. ユーザーを識別する \{#step-1-identify-users\} Adapty はプラットフォーム横断でユーザーを識別するために `customer_user_id` を使用します。 この ID はあらかじめ作成し、モバイル SDK とバックエンドの両方に渡す必要があります。ユーザーがアプリから初めてサインアップする際に SDK の起動時にカスタマーユーザー ID を渡すか、サインアップ前に Adapty SDK を起動済みの場合は `identify` メソッドを使って新しいプロファイルを作成し、カスタマーユーザー ID を割り当ててください。 :::important SDK 起動後に新しいユーザーを識別する場合、SDK はまず匿名プロファイルを作成します(SDK はプロファイルなしでは動作できません)。カスタマーユーザー ID を指定して `identify` を呼び出すと、新しいプロファイルが作成されます。 この動作は正常であり、アナリティクスの精度に影響しません。詳しくは[こちら](ios-quickstart-identify)をご覧ください。 ::: <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS" default> ```swift showLineNumbers do { try await Adapty.identify("YOUR_USER_ID") // Unique for each user } catch { // handle the error } ``` </TabItem> <TabItem value="swift-callback" label="iOS (Swift-Callback)" default> ```swift showLineNumbers // User IDs must be unique for each user Adapty.identify("YOUR_USER_ID") { error in if let error { // handle the error } } ``` </TabItem> <TabItem value="android" label="Android (Kotlin)" default> ```kotlin showLineNumbers Adapty.identify("YOUR_USER_ID") { error -> // Unique for each user if (error == null) { // successful identify } } ``` </TabItem> <TabItem value="java" label="Android (Java)" default> ```java showLineNumbers // User IDs must be unique for each user Adapty.identify("YOUR_USER_ID", error -> { if (error == null) { // successful identify } }); ``` </TabItem> <TabItem value="react-native" label="React Native" default> ```typescript showLineNumbers try { await adapty.identify("YOUR_USER_ID"); // Unique for each user // successfully identified } catch (error) { // handle the error } ``` </TabItem> <TabItem value="flutter" label="Flutter" default> ```dart showLineNumbers try { await Adapty().identify(customerUserId); // Unique for each user } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` </TabItem> <TabItem value="unity" label="Unity" default> ```csharp showLineNumbers Adapty.Identify("YOUR_USER_ID", (error) => { // Unique for each user if(error == null) { // successful identify } }); ``` </TabItem> <TabItem value="kmp" label="Kotlin Multiplatform" default> ```kotlin showLineNumbers Adapty.identify("YOUR_USER_ID") // Unique for each user .onSuccess { // successful identify } .onError { error -> // handle the error } ``` </TabItem> <TabItem value="capacitor" label="Capacitor" default> ```typescript showLineNumbers try { await adapty.identify({ customerUserId: "YOUR_USER_ID" }); // successfully identified } catch (error) { // handle the error } ``` </TabItem> </Tabs> ## ステップ 2. Adapty ダッシュボードでカスタムストアのプロダクトを作成する \{#step-2-create-products-in-a-custom-store-in-adapty-dashboard\} Adapty がカスタムストアのトランザクションをプロダクトと照合できるよう、プロダクトを追加してカスタムストアの詳細を設定する必要があります。 1. Adapty ダッシュボードの左メニューから [**Products**](https://app.adapty.io/settings/general) に移動し、**Create product** をクリックします。または、既存のプロダクトをクリックして編集します。 2. ユーザーがプロダクトを購入した際に付与する[アクセスレベル](access-level)が選択されていることを確認します。 3. **+** をクリックして **Add a custom store** を選択します。 4. **Create new custom store** をクリックします。 5. ストアの名前(例:「Amazon Appstore」「Microsoft Store」「Web Store」)と ID を入力し、**Create custom store** をクリックします。 6. **Save changes** をクリックして、プロダクトをカスタムストアに紐付けます。 7. そのストア内のプロダクトと対応付けるために **Store product ID** を入力し、**Save** をクリックします。 ## ステップ 3. API 経由でトランザクションを同期する \{#step-3-sync-transactions-via-api\} カスタムストアで購入が完了したら、サーバーサイド API を使って Adapty にその情報を同期する必要があります。 この API 呼び出しによって以下が実行されます。 - Adapty にトランザクションを記録する - 対応するアクセスレベルをユーザーに付与する - 設定済みのインテグレーションやウェブフックをトリガーする - アナリティクスにトランザクションを表示する メソッドの完全なリファレンスは[こちら](api-adapty/operations/setTransaction)をご覧ください。 ```bash curl --request POST \ --url https://api.adapty.io/api/v2/server-side-api/purchase/set/transaction/ \ --header 'Accept: application/json' \ --header 'Authorization: Api-Key YOUR_SECRET_API_KEY' \ --header 'Content-Type: application/json' \ --header 'adapty-customer-user-id: YOUR_CUSTOMER_USER_ID' \ --data '{ "purchase_type": "PRODUCT_PERIOD", "store": "YOUR_CUSTOM_STORE", "environment": "production", "store_product_id": "YOUR_STORE_PRODUCT_ID", "store_transaction_id": "STORE_TRANSACTION_ID", "store_original_transaction_id": "ORIGINAL_TRANSACTION_ID", "price": { "country": "COUNTRY_CODE", "currency": "CURRENCY_CODE", "value": "YOUR_PRICE" }, "purchased_at": "2024-01-15T10:30:00Z" }' ``` :::important 重要なパラメーター: - **store**: ステップ 2 で設定したカスタムストアの ID - **store_product_id**: ステップ 2 で設定したストアプロダクト ID - **store_transaction_id**: このトランザクションの一意の識別子 - **purchased_at**: 購入が発生した ISO 8601 形式のタイムスタンプ - **price**: ユーザーが支払った金額 ::: ## ステップ 4. アプリでアクセスを確認する \{#step-4-verify-access-in-the-app\} トランザクションが同期されると、ユーザーのプロファイルに新しいアクセスレベルが自動的に反映されます。 ユーザーがモバイルアプリを開いたら、プロファイルを取得してサブスクリプションの状態を確認し、プレミアム機能のロックを解除します。 <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS" default> ```swift showLineNumbers do { let profile = try await Adapty.getProfile() if profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false { // grant access to premium features } } catch { // handle the error } ``` </TabItem> <TabItem value="swift-callback" label="iOS (Swift-Callback)" default> ```swift showLineNumbers Adapty.getProfile { result in if let profile = try? result.get() { // check the access if profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false { // grant access to premium features } } } ``` </TabItem> <TabItem value="android" label="Android (Kotlin)" default> ```kotlin showLineNumbers Adapty.getProfile { result -> when (result) { is AdaptyResult.Success -> { val profile = result.value // check the access if (profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive == true) { // grant access to premium features } } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` </TabItem> <TabItem value="java" label="Android (Java)" default> ```java showLineNumbers Adapty.getProfile(result -> { if (result instanceof AdaptyResult.Success) { AdaptyProfile profile = ((AdaptyResult.Success<AdaptyProfile>) result).getValue(); // check the access if (profile.getAccessLevels().get("YOUR_ACCESS_LEVEL") != null && profile.getAccessLevels().get("YOUR_ACCESS_LEVEL").getIsActive()) { // grant access to premium features } } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // handle the error } }); ``` </TabItem> <TabItem value="react-native" label="React Native" default> ```typescript showLineNumbers try { const profile = await adapty.getProfile(); // check the access if (profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive) { // grant access to premium features } } catch (error) { // handle the error } ``` </TabItem> <TabItem value="flutter" label="Flutter" default> ```dart showLineNumbers try { final profile = await Adapty().getProfile(); // check the access if (profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false) { // grant access to premium features } } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` </TabItem> <TabItem value="unity" label="Unity" default> ```csharp showLineNumbers Adapty.GetProfile((profile, error) => { if (error != null) { // handle the error return; } // check the access if (profile.AccessLevels["YOUR_ACCESS_LEVEL"]?.IsActive ?? false) { // grant access to premium features } }); ``` </TabItem> <TabItem value="kmp" label="Kotlin Multiplatform" default> ```kotlin showLineNumbers Adapty.getProfile() .onSuccess { profile -> // check the access if (profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive == true) { // grant access to premium features } } .onError { error -> // handle the error } ``` </TabItem> <TabItem value="capacitor" label="Capacitor" default> ```typescript showLineNumbers try { const profile = await adapty.getProfile(); // check the access if (profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive) { // grant access to premium features } } catch (error) { // handle the error } ``` </TabItem> </Tabs> --- # File: grant-access-level --- --- title: "アクセスレベルを手動で付与する" description: "特定のユーザーまたはユーザーグループに対して、有料機能を手動でアンロックする" --- 特定のユーザーやユーザーグループに対して**プレミアム機能を手動でアンロック**したい場合、Adapty API を使って行うことができます。プロモーションキャンペーン、投資家へのアクセス付与、カスタマーサポートの特別対応などに役立ちます。 このガイドでは、ユーザーを識別してプログラムからアクセスレベルを付与する方法を説明します。 #### 利用シナリオの例 - **プロモコード**: ユーザーがアプリ内で有効なプロモコードを入力した際に、プレミアム機能へのアクセスを自動的に付与する。 - **投資家・ベータテスター向けアクセス**: カスタム属性を確認して、投資家やベータテスターにプレミアムアクセスを提供する。 :::note **Google Play プロモコード**: Google Play のプロモコードを使用した購入は、`orderId` なしで届く場合があります。Adapty の買い切り購入(サブスクリプション以外)のバリデーションには `orderId` が必要なため、こうしたコード引き換えは自動的にバリデーション・付与されません。以下の手順で手動でアクセスを付与してください。Server-Side API は `orderId` に依存しません。 ::: ## ステップ 1. ユーザーを識別する \{#step-1-identify-users\} Adapty はプラットフォームやデバイスをまたいでユーザーを識別するために `customer_user_id` を使用します。これにより、アプリの再インストールやデバイス切り替え後もユーザーのアクセスを継続させることができます。 この ID は一度だけ作成します。ユーザーがアプリから初めてサインアップする際に、SDK アクティベーション時に customer user ID を渡すか、サインアップ前に SDK をアクティベートした場合は `identify` メソッドを使用します。 :::important SDK アクティベーション後に新規ユーザーを識別する場合、SDK はまず匿名プロファイルを作成します(SDK は必ずプロファイルが必要です)。その後 `identify` を customer user ID で呼び出すと、新しいプロファイルが作成されます。 この動作は正常であり、アナリティクスの精度には影響しません。詳細は[こちら](ios-quickstart-identify)をご覧ください。 ::: <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS" default> ```swift showLineNumbers do { try await Adapty.identify("YOUR_USER_ID") // Unique for each user } catch { // handle the error } ``` </TabItem> <TabItem value="swift-callback" label="iOS (Swift-Callback)" default> ```swift showLineNumbers // User IDs must be unique for each user Adapty.identify("YOUR_USER_ID") { error in if let error { // handle the error } } ``` </TabItem> <TabItem value="android" label="Android (Kotlin)" default> ```kotlin showLineNumbers Adapty.identify("YOUR_USER_ID") { error -> // Unique for each user if (error == null) { // successful identify } } ``` </TabItem> <TabItem value="java" label="Android (Java)" default> ```java showLineNumbers // User IDs must be unique for each user Adapty.identify("YOUR_USER_ID", error -> { if (error == null) { // successful identify } }); ``` </TabItem> <TabItem value="react-native" label="React Native" default> ```typescript showLineNumbers try { await adapty.identify("YOUR_USER_ID"); // Unique for each user // successfully identified } catch (error) { // handle the error } ``` </TabItem> <TabItem value="flutter" label="Flutter" default> ```dart showLineNumbers try { await Adapty().identify(customerUserId); // Unique for each user } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` </TabItem> <TabItem value="unity" label="Unity" default> ```csharp showLineNumbers Adapty.Identify("YOUR_USER_ID", (error) => { // Unique for each user if(error == null) { // successful identify } }); ``` </TabItem> <TabItem value="kmp" label="Kotlin Multiplatform" default> ```kotlin showLineNumbers Adapty.identify("YOUR_USER_ID") // Unique for each user .onSuccess { // successful identify } .onError { error -> // handle the error } ``` </TabItem> <TabItem value="capacitor" label="Capacitor" default> ```typescript showLineNumbers try { await adapty.identify({ customerUserId: "YOUR_USER_ID" }); // successfully identified } catch (error) { // handle the error } ``` </TabItem> </Tabs> ## ステップ 2. API でアクセスレベルを付与する \{#step-2-grant-access-level-via-api\} ユーザーが `customer_user_id` で識別されたら、サーバーサイド API を使ってアクセスレベルを付与できます。この API 呼び出しにより、ユーザーは実際に購入することなく有料機能にアクセスできるようになります。 メソッドの完全なリファレンスは[こちら](api-adapty/operations/grantAccessLevel)をご覧ください。 :::tip Adapty ダッシュボードでカスタム属性(例:Beta tester や Investor)を追加することで、ユーザーアクセスを管理できます。 アプリ起動時に[ユーザープロファイルのこの属性を確認](subscription-status)してアクセスを自動的に付与します。 アクセスを更新するには、ダッシュボードで属性を変更するだけです。 ::: ```bash curl --request POST \ --url https://api.adapty.io/api/v2/server-side-api/purchase/profile/grant/access-level/ \ --header 'Accept: application/json' \ --header 'Authorization: Api-Key YOUR_SECRET_API_KEY' \ --header 'Content-Type: application/json' \ --header 'adapty-customer-user-id: CUSTOMER_USER_ID' \ --data '{ "access_level_id": "YOUR_ACCESS_LEVEL" }' ``` ## ステップ 3. アプリ内でアクセスを確認する \{#step-3-verify-access-in-the-app\} API でアクセスを付与すると、ユーザーのプロファイルは自動的に更新されます。プロファイルを取得してサブスクリプションの状態を確認し、プレミアム機能をアンロックしてください。 <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS" default> ```swift showLineNumbers do { let profile = try await Adapty.getProfile() if profile.accessLevels["YOUR_ACCESS_LEVEL_ID"]?.isActive ?? false { // grant access to premium features } } catch { // handle the error } ``` </TabItem> <TabItem value="swift-callback" label="iOS (Swift-Callback)" default> ```swift showLineNumbers Adapty.getProfile { result in if let profile = try? result.get() { // check the access if profile.accessLevels["YOUR_ACCESS_LEVEL_ID"]?.isActive ?? false { // grant access to premium features } } } ``` </TabItem> <TabItem value="android" label="Android (Kotlin)" default> ```kotlin showLineNumbers Adapty.getProfile { result -> when (result) { is AdaptyResult.Success -> { val profile = result.value // check the access if (profile.accessLevels["YOUR_ACCESS_LEVEL_ID"]?.isActive == true) { // grant access to premium features } } is AdaptyResult.Error -> { val error = result.error // handle the error } } } ``` </TabItem> <TabItem value="java" label="Android (Java)" default> ```java showLineNumbers Adapty.getProfile(result -> { if (result instanceof AdaptyResult.Success) { AdaptyProfile profile = ((AdaptyResult.Success<AdaptyProfile>) result).getValue(); // check the access if (profile.getAccessLevels().get("YOUR_ACCESS_LEVEL_ID") != null && profile.getAccessLevels().get("YOUR_ACCESS_LEVEL_ID").getIsActive()) { // grant access to premium features } } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // handle the error } }); ``` </TabItem> <TabItem value="react-native" label="React Native" default> ```typescript showLineNumbers try { const profile = await adapty.getProfile(); // check the access if (profile.accessLevels["YOUR_ACCESS_LEVEL_ID"]?.isActive) { // grant access to premium features } } catch (error) { // handle the error } ``` </TabItem> <TabItem value="flutter" label="Flutter" default> ```dart showLineNumbers try { final profile = await Adapty().getProfile(); // check the access if (profile.accessLevels["YOUR_ACCESS_LEVEL_ID"]?.isActive ?? false) { // grant access to premium features } } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` </TabItem> <TabItem value="unity" label="Unity" default> ```csharp showLineNumbers Adapty.GetProfile((profile, error) => { if (error != null) { // handle the error return; } // check the access if (profile.AccessLevels["YOUR_ACCESS_LEVEL_ID"]?.IsActive ?? false) { // grant access to premium features } }); ``` </TabItem> <TabItem value="kmp" label="Kotlin Multiplatform" default> ```kotlin showLineNumbers Adapty.getProfile() .onSuccess { profile -> // check the access if (profile.accessLevels["YOUR_ACCESS_LEVEL_ID"]?.isActive == true) { // grant access to premium features } } .onError { error -> // handle the error } ``` </TabItem> <TabItem value="capacitor" label="Capacitor" default> ```typescript showLineNumbers try { const profile = await adapty.getProfile(); // check the access if (profile.accessLevels["YOUR_ACCESS_LEVEL_ID"]?.isActive) { // grant access to premium features } } catch (error) { // handle the error } ``` </TabItem> </Tabs> --- # File: web-api --- --- title: Adapty Web API description: "" --- Web APIは、Webアプリで使用するためのサーバーサイドAPIの拡張機能です。関連するプレースメントIDを使用して正しいペイウォールを取得し、正確なコンバージョン追跡のためのペイウォール表示を記録できます。これにより、Adaptyで利用可能なA/Bテストとペイウォールのパーソナライゼーションを活用し、どのペイウォールが最も効果的かを追跡できます。 ## ユースケース:Webアプリからトランザクションを記録し、使用したペイウォールに紐付ける \{#use-case-record-a-transaction-from-your-web-app-and-link-it-to-the-used-paywall\} Webアプリでプロダクトを販売しているとしましょう。ユーザーにペイウォールを表示し、プロダクトを購入してもらい、その後トランザクションの詳細をAdaptyに追加する必要があります。アナリティクスが正確なデータを反映できるよう、これらのトランザクションをユーザーが購入した特定のペイウォールに紐付けることが重要です。これはAdapty APIを使って簡単に実現できます。 ### 前提条件 \{#prerequisites\} 1. Adapty ダッシュボードで、ペイウォールで使用する[プロダクトを作成](create-product)します。 2. Adapty ダッシュボードで[ペイウォールを作成](create-paywall)します。[リモートコンフィグを使用](customize-paywall-with-remote-config)して、WebペイウォールのデザインをカスタマイズしてURL。 3. Adapty ダッシュボードで[プレースメントを設定](create-placement)し、ペイウォールを紐付けます。 ### Adapty APIを使った手順 \{#steps-with-adapty-api\} 1. **ユーザープロファイルの作成:** Adaptyはペイウォールをリクエストする前にプロファイルを必要とし、リクエストしたユーザーに合わせて結果をパーソナライズします。[プロファイルの作成](api-adapty/operations/createProfile)リクエストを使用してユーザープロファイルを作成してください。 2. **ペイウォールの取得と表示:** ユーザーがWebアプリ内のペイウォールを表示すべきプレースメントに到達したら、[ペイウォールを取得](api-web/operations/getPaywall)リクエストを使用して[プレースメントID](placements)経由でペイウォールを取得します。結果として、ユーザーに対応する[オーディエンス](audience)のペイウォールが返されます。返されたプロダクトと(任意で)このペイウォールの[リモートコンフィグ](customize-paywall-with-remote-config)を使って、自分のコードでペイウォールを表示します。 3. **ペイウォール表示の記録:** [ペイウォール表示の記録](api-web/operations/recordPaywallView)を使用して、アナリティクスがイベントを正確に反映できるよう、ペイウォールの表示をAdaptyに記録します。これはコンバージョンを正しく追跡するために不可欠です。 4. **購入の記録:** ユーザーが購入を完了した場合、Adapty APIを使用してトランザクションの詳細をAdaptyに送信します。表示された特定のペイウォールにトランザクションを紐付けるために、このリクエストに**バリエーションID**を含めてください。詳細については、[モバイルアプリでのペイウォールとトランザクションの関連付け](report-transactions-observer-mode)のページを参照してください—同じアプローチがWebアプリにも適用されます。 5. **マーケティングアトリビューションデータの追加(該当する場合):** マーケティングアトリビューションデータ(キャンペーンや広告の詳細など)がある場合は、[アトリビューションの追加](api-web/operations/addAttribution)を使用してユーザープロファイルにマージし、アナリティクスを充実させ、Adaptyでの広告効果をより深く把握できます。 --- **次のステップ:** - [Web API認証](web-api-authorization)に進む - リクエスト: - [アトリビューションの追加](api-web/operations/addAttribution) - [ペイウォールの取得](api-web/operations/getPaywall) - [ペイウォール表示の記録](api-web/operations/recordPaywallView) --- # File: web-api-authorization --- --- title: Authorization and Request format for Web API description: "" --- ## 認証 \{#authorization\} APIリクエストは、公開APIキーを使って認証する必要があります。**Authorization** ヘッダーに `Api-Key {your_public_api_key}` という形式で値を設定してください(例: `Api-Key public_live_...`)。このキーは [Adapty Dashboard -> **App Settings** -> **General** タブ -> **API keys** セクション](https://app.adapty.io/settings/general) で確認できます。 :::important APIキーはアプリごとに固有です。複数のアプリを運用している場合は、それぞれ異なるキーを使用してください。 ::: ## リクエスト形式 \{#request-format\} - **Content-Type ヘッダー**: APIがリクエストを正しく処理できるよう、**Content-Type** ヘッダーを `application/json` に設定してください。 - **ボディ**: APIはリクエストボディをJSON形式で受け付けます。 --- # File: web-api-requests --- --- title: " Web API リクエスト" description: "" --- Adapty のサーバーサイド API を使うと、サブスクリプションデータにプログラムからアクセスして管理できます。既存のサービスやインフラとシームレスに統合し、プラットフォーム間のデータ同期、アクセスレベルの付与、Stripe での購入検証などをまとめて行えます。 ## Postman コレクションと環境 \{#postman-collection-and-environment\} Web API を手軽に使えるよう、Postman にインポートして使える Postman コレクションと環境ファイルを用意しました。 - **リクエストコレクション**: Adapty Web API で使用できるすべてのリクエストが含まれています。環境で定義できる変数を使用しています。 - **環境**: 変数の一覧が含まれており、値を一度設定するだけで使いまわせます。サーバーサイド API・Web API・アナリティクスエクスポート API を統合した環境を用意しているので、設定の手間を省けます。この環境をアクティブにすると、Postman がリクエスト内の変数値を自動的に置き換えます。 :::tip [コレクションと環境をダウンロード](https://raw.githubusercontent.com/adaptyteam/adapty-docs/refs/heads/main/Downloads/Adapty_Web_API_postman_collection.zip) ::: Postman へのコレクションと環境のインポート方法については、[Postman ドキュメント](https://learning.postman.com/docs/getting-started/importing-and-exporting/importing-data/)を参照してください。 ## 使用する変数 \{#variables-used\} サーバーサイド API・Web API・アナリティクスエクスポート API を統合した環境を用意し、ワークフローを簡略化しています。Web API に固有の変数は以下のとおりです。 | 変数 | 説明 | 値の例 | | ----------------------- | ------------------------------------------------------------ | ------------------------------------------------------- | | public_api_key | [**App settings**](https://app.adapty.io/settings/general) の **Public SDK key** フィールドで確認できます。 | `public_live_Pj1P1xzM.2CvSvE1IalQRFjsWy6csBVNpH33atnod` | | adapty-customer-user-id | お使いのシステムで使用するユーザー ID です。Adapty ダッシュボードでは、プロファイルの **Customer user ID** フィールドで確認できます。 | `john.doe@example.com` | | adapty-profile-id | Adapty が割り当てるユーザー ID です。Adapty ダッシュボードでは、プロファイルの **Adapty ID** フィールドで確認できます。 | `3286abd3-48b0-4e9c-a5f6-ac0a006333a6` | **次のステップ: リクエスト:** - [ペイウォールを取得する](api-web/operations/getPaywall) - [ペイウォール表示を記録する](api-web/operations/recordPaywallView) - [アトリビューションを追加する](api-web/operations/addAttribution) --- # File: export-analytics-api --- --- title: APIによるアナリティクスのエクスポート --- アナリティクスデータをCSVにエクスポートすることで、アプリのパフォーマンス指標をより深く分析し、レポートをカスタマイズして、時系列でのトレンドを把握できます。Adapty APIを使えば、詳細なアナリティクスデータを簡単にCSV形式で取得でき、データインサイトの追跡・共有・改善がスムーズに行えます。 :::tip AIエージェントやLLMでアナリティクスを取得したい場合は、[AIエージェントでアナリティクスをエクスポートする](export-analytics-with-ai)をご覧ください。 ::: ## アナリティクスエクスポート用APIをはじめる \{#getting-started-with-the-api-for-analytics-export\} アナリティクスエクスポートAPIでできることの例を紹介します。 1. **マーケティングキャンペーンのMRR分析**: 昨年のマーケティングキャンペーンが特定の国にどのような影響を与えたかを週次で測定し、最も高い収益をもたらしたキャンペーンを特定します。[アナリティクスデータの取得](api-export-analytics/operations/retrieveAnalyticsData)メソッドを使用してください。 2. **コホート別のリテンション追跡**: コホートごとにリテンションを追跡してドロップオフポイントを把握し、コホート間の比較を通じてトレンドやエンゲージメント施策が効果を発揮しやすいタイミングを明らかにします。特定のアプリストア・国・プロダクトに絞った分析が可能です。[コホートデータの取得](api-export-analytics/operations/retrieveCohortData)メソッドを使用してください。 3. **チャネル別のコンバージョン率評価**: 主要な獲得チャネルのコンバージョン率を分析し、初回購入を最も効果的に促進しているチャネルを特定します。これにより、パフォーマンスの高いチャネルへのマーケティング投資を優先できます。[コンバージョンデータの取得](api-export-analytics/operations/retrieveConversionData)メソッドを使用してください。 4. **チャーン率の確認**: ユーザーの解約ペースを監視してチャーンのパターンを把握したり、リテンション施策の効果を測定したりします。特定の国・プロダクトに絞った分析が可能です。[ファネルデータの取得](api-export-analytics/operations/retrieveFunnelData)メソッドを使用してください。 5. **ユーザーセグメント別のLTV評価**: 異なるユーザーセグメントのライフタイムバリューを特定し、どのグループが長期的に最も高い収益をもたらすかを把握します。長期サブスクライバーなど価値の高いセグメントに焦点を当て、その結果を獲得戦略の改善に活用してください。[LTVデータの取得](api-export-analytics/operations/retrieveLTVData)メソッドを使用してください。 6. **国別のリテンション確認**: 地域別のリテンション率を分析してエンゲージメントの高い市場を見つけ、ローカライズや地域戦略の指針にします。[リテンションデータの取得](api-export-analytics/operations/retrieveRetentionData)メソッドを使用してください。 --- **次のステップ**: - [認証とリクエスト形式](export-analytics-api-authorization) - [アナリティクスエクスポートのAPIリクエスト](export-analytics-api-requests) --- # File: export-analytics-api-authorization --- --- title: エクスポートアナリティクス API の認証とリクエスト形式 --- ## 認証 \{#authorization\} API リクエストの認証には、シークレット API キーを Authorization ヘッダーとして使用します。キーは [App Settings](https://app.adapty.io/settings/general) で確認できます。形式は `Api-Key {YOUR_SECRET_API_KEY}` で、例として `Api-Key secret_live_...` のように指定します。 :::important API キーはアプリごとに固有です。複数のアプリをお持ちの場合は、それぞれ異なるキーを使用してください。 ::: ## リクエスト形式 \{#request-format\} **ヘッダー** サーバーサイド API リクエストには、特定のヘッダーと JSON ボディが必要です。以下の内容を参考にリクエストを構成してください。 | ヘッダー | 説明 | | ------------ | ------------------------------------------------------------ | | Content-Type | (必須)API がリクエストを処理するために `application/json` を指定します。 | | Adapty-Tz | (任意)データのグループ化と表示に使用するタイムゾーンを設定します。[IANA タイムゾーンデータベース形式](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones)(例: `Europe/Berlin`)を使用してください。 | ## ボディ \{#body\} API はリクエストに必要なデータを含む JSON 形式のボディを受け取ります。 ## レート制限 \{#rate-limits\} API キーごとに 1 秒あたり最大 2 リクエストまで送信できます。この制限を超えると `429 Too Many Requests` エラーが返されます。 ## API キーのローテーション \{#rotate-api-keys\} シークレット API キーをローテーションする必要がある場合は、以下の手順に従ってください。 1. **Settings → General** で **Generate new key** をクリックし、古いキーの横にあるゴミ箱アイコンをクリックします。 2. アプリで使用しているキーを更新します。 --- **次のステップ:リクエスト:** - [アナリティクスデータの取得](api-export-analytics/operations/retrieveAnalyticsData) - [コホートデータの取得](api-export-analytics/operations/retrieveCohortData) - [コンバージョンデータの取得](api-export-analytics/operations/retrieveConversionData) - [ファネルデータの取得](api-export-analytics/operations/retrieveFunnelData) - [LTV(ライフタイムバリュー)データの取得](api-export-analytics/operations/retrieveLTVData) - [リテンションデータの取得](api-export-analytics/operations/retrieveRetentionData) --- # File: export-analytics-api-requests --- --- title: アナリティクスAPIリクエストのエクスポート --- アナリティクスデータをCSV形式でエクスポートすると、アプリのパフォーマンス指標をより深く分析したり、レポートをカスタマイズしたり、時系列のトレンドを把握したりできます。Adapty APIを使えば、詳細なアナリティクスデータを簡単にCSV形式で取得でき、データインサイトの追跡・共有・改善が手軽に行えます。 ## Postmanコレクションと環境 \{#postman-collection-and-environment\} アナリティクスデータのエクスポートAPIを使いやすくするため、PostmanにインポートできるPostmanコレクションと環境ファイルを用意しました。 - **リクエストコレクション**: AdaptyアナリティクスエクスポートAPIで利用可能なすべてのリクエストを含みます。環境で定義できる変数を使用しています。 - **環境**: 変数の一覧を含んでおり、値を一度定義するだけで使い回せます。サーバーサイドAPI、Web API、アナリティクスエクスポートAPIを統合した環境を用意しており、この環境をアクティブにするとPostmanがリクエスト内の変数値を自動的に置換します。 :::tip [コレクションと環境をダウンロード](https://raw.githubusercontent.com/adaptyteam/adapty-docs/refs/heads/main/Downloads/Adapty_export_analytics_API_postman_collection.zip) ::: PostmanへのコレクションおよびEnvironmentのインポート方法については、[Postmanドキュメント](https://learning.postman.com/docs/getting-started/importing-and-exporting/importing-data/)を参照してください。 ### 使用する変数 \{#variables-used\} サーバーサイドAPI、Web API、アナリティクスエクスポートAPIのワークフローを簡略化するため、統合環境を作成しました。以下はアナリティクスエクスポートAPIに固有の変数です: | 変数 | 説明 | 値の例 | | ----------------------- | ------------------------------------------------------------ | --------------------------------------------------------- | | secret_api_key | [**App settings**](https://app.adapty.io/settings/general) の **Secret key** フィールドで確認できます。 | `secret_live_Pj1P1xzM.2CvSvE1IalQRFjsWy6csBVNpH33atnod` | **リクエスト:** - [アナリティクスデータの取得](api-export-analytics/operations/retrieveAnalyticsData) - [コホートデータの取得](api-export-analytics/operations/retrieveCohortData) - [コンバージョンデータの取得](api-export-analytics/operations/retrieveConversionData) - [ファネルデータの取得](api-export-analytics/operations/retrieveFunnelData) - [LTV(ライフタイムバリュー)データの取得](api-export-analytics/operations/retrieveLTVData) - [リテンションデータの取得](api-export-analytics/operations/retrieveRetentionData) --- # End of Documentation _Generated on: 2026-06-24T14:36:28.470Z_ _Successfully processed: 17/18 files_ # CAPACITOR - Adapty Documentation (Full Content) This file contains the complete content of all documentation pages for this platform. Locale: ja Generated on: 2026-06-24T14:36:28.471Z Total files: 43 --- # File: capacitor-sdk-overview --- --- title: "Capacitor SDK overview" description: "Learn about Adapty Capacitor SDK and its key features." --- [![Release](https://img.shields.io/github/v/release/adaptyteam/AdaptySDK-Capacitor.svg?style=flat&logo=capacitor)](https://github.com/adaptyteam/AdaptySDK-Capacitor/releases) Welcome! We're here to make in-app purchases a breeze 🚀 We've built the [Adapty Capacitor SDK](https://github.com/adaptyteam/AdaptySDK-Capacitor/) to take the headache out of in-app purchases so you can focus on what you do best – building amazing apps. Here's what we handle for you: - Handle purchases, receipt validation, and subscription management out of the box - Create and test paywalls without app updates - Get detailed purchase analytics with zero setup - cohorts, LTV, churn, and funnel analysis included - Keep the user subscription status always up to date across app sessions and devices - Integrate your app with marketing attribution and analytics services using just one line of code :::note Before diving into the code, you'll need to integrate Adapty with App Store Connect and Google Play Console, then set up products in the dashboard. Check out our [quickstart guide](quickstart) to get everything configured first. ::: ## Get started For a fully automated integration, use the [adapty-sdk-integration skill](https://github.com/adaptyteam/adapty-sdk-integration-skill): it runs the whole integration from your AI coding tool in one command. Here's what we'll cover in the integration guide: 1. [Install & configure SDK](sdk-installation-capacitor): Add the SDK as a [dependency](https://www.npmjs.com/package/@adapty/capacitor) to your project and activate it in the code. 2. [Enable purchases through paywalls](capacitor-quickstart-paywalls): Set up the purchase flow so users can buy products. 3. [Check the subscription status](capacitor-check-subscription-status): Automatically check the user's subscription state and control their access to paid content. 4. [Identify users (optional)](capacitor-quickstart-identify): Associate users with their Adapty profiles to ensure their data is stored consistently across devices. ### See it in action Want to see how it all comes together? We've got you covered: **Sample apps**: Check out our complete examples that demonstrate the full setup: - [React](https://github.com/adaptyteam/AdaptySDK-Capacitor/tree/master/examples/basic-react-example) - [Vue.js](https://github.com/adaptyteam/AdaptySDK-Capacitor/tree/master/examples/basic-vue-example) - [Angular](https://github.com/adaptyteam/AdaptySDK-Capacitor/tree/master/examples/basic-angular-example) - [Advanced development tools](https://github.com/adaptyteam/AdaptySDK-Capacitor/tree/master/examples/adapty-devtools) ## Main concepts Before diving into the code, let's get familiar with the key concepts that make Adapty work. The beauty of Adapty's approach is that only placements are hardcoded in your app. Everything else – products, paywall designs, pricing, and offers – can be managed flexibly from the Adapty dashboard without app updates: 1. **Product** - Anything available for purchase in your app – subscription, consumable product, or lifetime access. 2. **Paywall** - The only way to retrieve products from Adapty and use it to its full power. We've designed it this way to make it easier to track how different product combinations affect your monetization metrics. A paywall in Adapty serves as both a specific set of your products and the visual configuration that accompanies them. 3. **Placement** - A strategic point in your user journey where you want to show a paywall. Think of placements as the "where" and "when" of your monetization strategy. Common placements include: - `main` - Your primary paywall location - `onboarding` - Shown during the user onboarding flow - `settings` - Accessible from your app's settings Start with the basics like `main` or `onboarding` for your first integration, then think about where else in your app users might be ready to purchase. 4. **Profile** - When users purchase a product, their profile is assigned an **access level** which you use to define access to paid features. --- # File: sdk-installation-capacitor --- --- title: "Capacitor - Adapty SDK のインストールと設定" description: "サブスクリプション型アプリ向けに Capacitor へ Adapty SDK をインストールするステップバイステップガイド。" --- Adapty SDK には、Capacitor アプリへのスムーズな統合を実現する 2 つの主要モジュールが含まれています。 - **Core Adapty**: アプリで Adapty を正しく動作させるために必須のモジュールです。 - **AdaptyUI**: クロスプラットフォームのペイウォールをノーコードで簡単に作成できるツール [Adapty ペイウォールビルダー](adapty-paywall-builder) を使用する場合に必要なモジュールです。AdaptyUI はコアモジュールと同時に自動的に有効化されます。 :::tip Adapty SDK をモバイルアプリに統合した実際の例を見たい方は、[サンプルアプリ](https://github.com/adaptyteam/AdaptySDK-Capacitor/tree/master/examples)をご確認ください。ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを確認できます。 ::: ## 要件 \{#requirements\} [Adapty Capacitor SDK](https://github.com/adaptyteam/AdaptySDK-Capacitor/) には以下のバージョン要件があります。 | Adapty SDK バージョン | Capacitor バージョン | iOS バージョン | |--------------------|-------------------|-------------| | 3.16.0+ | 8 | 15.0+ | | 3.15 | 7 | 14.0+ | Capacitor バージョン 6 以下はサポートされていません。 :::info SDK v3.17 以降、Adapty SDK はデフォルトで Google Play Billing Library v8.0.0 を使用します。 ::: --- no_index: true --- import Callout from '../../../components/Callout.astro'; <Callout type="info"> SDKのインストールは、Adaptyセットアップのステップ5です。アプリ内で課金が機能するようにするには、アプリをストアに接続し、Adapty ダッシュボードでプロダクト、ペイウォール、プレースメントを作成する必要があります。[クイックスタートガイド](quickstart)では、必要なすべての手順を説明しています。 </Callout> ## Adapty SDK のインストール \{#install-adapty-sdk\} [![Release](https://img.shields.io/github/v/release/adaptyteam/AdaptySDK-Capacitor.svg?style=flat&logo=capacitor)](https://github.com/adaptyteam/AdaptySDK-Capacitor/releases) Adapty SDK をインストールします。 ```sh npm install @adapty/capacitor npx cap sync ``` ## Adapty SDK の Adapty モジュールを有効化する \{#activate-adapty-module-of-adapty-sdk\} :::note Adapty SDK の有効化はアプリ内で一度だけ行う必要があります。 ::: **Public SDK Key** を取得するには: 1. Adapty ダッシュボードを開き、[**App settings → General**](https://app.adapty.io/settings/general) に移動します。 2. **Api keys** セクションから **Public SDK Key**(Secret Key ではない方)をコピーします。 3. コード内の `"YOUR_PUBLIC_SDK_KEY"` を置き換えます。 :::important - Adapty の初期化には必ず **Public SDK key** を使用してください。**Secret key** は[サーバーサイド API](getting-started-with-server-side-api) 専用です。 - **SDK keys** はアプリごとに固有です。複数のアプリがある場合は、正しいキーを選択してください。 ::: Adapty を有効化するために、以下のコードをアプリの任意のファイルにコピーしてください。 ```typescript showLineNumbers try { await adapty.activate({ apiKey: 'YOUR_PUBLIC_SDK_KEY', params: { // verbose logging is recommended for the development purposes and for the first production release logLevel: 'verbose', // in the development environment, use this variable to avoid multiple activation errors. Set it to your development environment variable __ignoreActivationOnFastRefresh: true, } }); console.log('Adapty activated successfully!'); } catch (error) { console.error('Failed to activate Adapty SDK:', error); } ``` :::important 他の Adapty SDK メソッドを呼び出す前に、`activate` の完了を待ってください。完全な呼び出し順序については [Capacitor SDK の呼び出し順序](capacitor-sdk-call-order) を参照してください。 ::: :::tip 開発環境での有効化エラーを避けるには、[ヒント](#development-environment-tips) を参照してください。 ::: 次に、アプリでペイウォールをセットアップします。 - [Adapty ペイウォールビルダー](adapty-paywall-builder) を使用する場合は、[ペイウォールビルダークイックスタート](capacitor-quickstart-paywalls) に従ってください。 - 独自のペイウォール UI を構築する場合は、[カスタムペイウォールのクイックスタート](capacitor-quickstart-manual) を参照してください。 ## Adapty SDK の AdaptyUI モジュールを有効化する \{#activate-adaptyui-module-of-adapty-sdk\} [ペイウォールビルダー](adapty-paywall-builder) を使用する予定がある場合は、AdaptyUI モジュールが必要です。コアモジュールを有効化すると自動的に行われるため、追加の操作は不要です。 ## オプション設定 \{#optional-setup\} ### ロギング \{#logging\} #### ロギングシステムのセットアップ \{#set-up-the-logging-system\} Adapty は何が起きているかを把握できるよう、エラーやその他の重要な情報をログに記録します。利用可能なレベルは以下の通りです。 | レベル | 説明 | | ---------- | ------------------------------------------------------------ | | `error` | エラーのみがログに記録されます | | `warn` | 重大なエラーは発生しないが注意すべき SDK のエラーやメッセージがログに記録されます | | `info` | エラー、警告、および各種情報メッセージがログに記録されます | | `verbose` | 関数呼び出し、API クエリなど、デバッグ時に役立つ追加情報がすべてログに記録されます | ログレベルは Adapty の設定前または設定中にアプリで指定できます。 ```typescript showLineNumbers // Set log level before activation adapty.setLogLevel({ logLevel: 'verbose' }); // Or set it during configuration await adapty.activate({ apiKey: 'YOUR_PUBLIC_SDK_KEY', params: { logLevel: 'verbose', } }); ``` ### データポリシー \{#data-policies\} Adapty は明示的に送信しない限りユーザーの個人データを保存しませんが、ストアや国のガイドラインに準拠するための追加のデータセキュリティポリシーを実装できます。 #### IP アドレスの収集と共有を無効にする \{#disable-ip-address-collection-and-sharing\} Adapty モジュールを有効化する際に `ipAddressCollectionDisabled` を `true` に設定すると、ユーザーの IP アドレスの収集と共有が無効になります。デフォルト値は `false` です。 IP ベースの機能がアプリに必要でない場合や、GDPR や CCPA などの地域データ保護規制に準拠する必要がある場合、あるいは不必要なデータ収集を減らしたい場合に使用してください。 ```typescript showLineNumbers await adapty.activate({ apiKey: 'YOUR_PUBLIC_SDK_KEY', params: { ipAddressCollectionDisabled: true, } }); ``` #### 広告 ID の収集と共有を無効にする \{#disable-advertising-id-collection-and-sharing\} Adapty モジュールを有効化する際に `ios.idfaCollectionDisabled`(iOS)または `android.adIdCollectionDisabled`(Android)を `true` に設定すると、広告識別子の収集が無効になります。デフォルト値は `false` です。 App Store/Play Store ポリシーへの準拠、アプリトラッキングの透明性プロンプトの非表示、または広告 ID に基づくアトリビューションや分析がアプリに不要な場合に使用してください。 ```typescript showLineNumbers await adapty.activate({ apiKey: 'YOUR_PUBLIC_SDK_KEY', params: { ios: { idfaCollectionDisabled: true, }, android: { adIdCollectionDisabled: true, }, } }); ``` #### AdaptyUI のメディアキャッシュ設定をセットアップする \{#set-up-media-cache-configuration-for-adaptyui\} デフォルトでは、AdaptyUI はパフォーマンス向上とネットワーク使用量削減のために画像や動画などのメディアをキャッシュします。カスタム設定を指定してキャッシュ設定を変更できます。 デフォルトのキャッシュ設定を上書きするには `mediaCache` を使用してください。 ```typescript showLineNumbers await adapty.activate({ apiKey: 'YOUR_PUBLIC_SDK_KEY', params: { mediaCache: { memoryStorageTotalCostLimit: 200 * 1024 * 1024, // Optional: memory cache size in bytes memoryStorageCountLimit: 2147483647, // Optional: max number of items in memory diskStorageSizeLimit: 200 * 1024 * 1024, // Optional: disk cache size in bytes }, } }); ``` パラメータ: | パラメータ | 必須 | 説明 | |-----------|----------|-------------| | memoryStorageTotalCostLimit | 任意 | メモリ内のキャッシュサイズ(バイト単位)。プラットフォーム固有のデフォルト値が使用されます。 | | memoryStorageCountLimit | 任意 | メモリストレージのアイテム数制限。プラットフォーム固有のデフォルト値が使用されます。 | | diskStorageSizeLimit | 任意 | ディスク上のファイルサイズ制限(バイト単位)。プラットフォーム固有のデフォルト値が使用されます。 | ### ローカルアクセスレベルを有効にする(Android) \{#enable-local-access-levels-android\} デフォルトでは、[ローカルアクセスレベル](local-access-levels) は iOS では有効で Android では無効です。Android でも有効にするには、`localAccessLevelAllowed` を `true` に設定してください。 ```typescript showLineNumbers await adapty.activate({ apiKey: 'YOUR_PUBLIC_SDK_KEY', params: { android: { localAccessLevelAllowed: true, }, } }); ``` ### バックアップ復元時のデータクリア \{#clear-data-on-backup-restore\} `clearDataOnBackup` を `true` に設定すると、アプリが iCloud バックアップから復元された際に SDK が検出し、キャッシュされたプロファイル情報、プロダクト詳細、ペイウォールを含むすべてのローカル SDK データを削除します。SDK はクリーンな状態で初期化されます。デフォルト値は `false` です。 :::note 削除されるのはローカルの SDK キャッシュのみです。Apple とのトランザクション履歴および Adapty サーバー上のユーザーデータは変更されません。 ::: ```swift showLineNumbers await adapty.activate({ apiKey: 'YOUR_PUBLIC_SDK_KEY', params: { ios: { clearDataOnBackup: true, }, } }); ``` ## 開発環境のヒント \{#development-environment-tips\} #### Capacitor のライブリロードでの SDK 有効化エラーのトラブルシューティング \{#troubleshoot-sdk-activation-errors-on-capacitors-live-reload\} Capacitor で Adapty SDK を開発中に、次のエラーが発生することがあります: `Adapty can only be activated once. Ensure that the SDK activation call is not made more than once.` これは Capacitor のライブリロード機能が開発中に複数回の有効化呼び出しをトリガーするために発生します。これを防ぐには、`__ignoreActivationOnFastRefresh` オプションを Capacitor の開発モードフラグに設定してください。使用するバンドルによって異なります。 ```typescript showLineNumbers try { await adapty.activate({ apiKey: 'YOUR_PUBLIC_SDK_KEY', params: { // Set your development environment variable __ignoreActivationOnFastRefresh: true, } }); } catch (error) { console.error('Failed to activate Adapty SDK:', error); // Handle the error appropriately for your app } ``` ## トラブルシューティング \{#troubleshooting\} #### iOS の最低バージョンエラー \{#minimum-ios-version-error\} iOS の最低バージョンエラーが発生した場合は、Podfile を更新してください。 ```diff -platform :ios, min_ios_version_supported +platform :ios, '14.0' # For core features only # OR +platform :ios, '15.0' # If using paywalls created in the paywall builder ``` #### Android のバックアップルール(Auto Backup の設定) \{#android-backup-rules-auto-backup-configuration\} 一部のSDK(Adaptyを含む)には、独自のAndroid Auto Backup設定が含まれています。バックアップルールを定義する複数のSDKを使用している場合、Androidのマニフェストマージャーが `android:fullBackupContent`、`android:dataExtractionRules`、または `android:allowBackup` に関するエラーで失敗することがあります。 よくあるエラーの症状: `Manifest merger failed: Attribute application@dataExtractionRules value=(@xml/your_data_extraction_rules) is also present at [com.other.sdk:library:1.0.0] value=(@xml/other_sdk_data_extraction_rules)` :::note これらの変更は、Androidプラットフォームのディレクトリ(通常はプロジェクトの `android/` フォルダー内)で行う必要があります。 ::: この問題を解決するには、以下が必要です: - バックアップ関連の属性に対して、アプリの値を使用するようマニフェストマージャーに指示する。 - AdaptyのルールとほかのSDKのルールをマージしたバックアップルールファイルを作成する。 #### 1. マニフェストに `tools` 名前空間を追加する \{#1-add-the-tools-namespace-to-your-manifest\} `AndroidManifest.xml` ファイルのルートの `<manifest>` タグに tools が含まれていることを確認してください: ```xml <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="com.example.app"> ... </manifest> ``` #### 2. `<application>` でバックアップ属性を上書きする \{#2-override-backup-attributes-in-application\} 同じ `AndroidManifest.xml` ファイルで、`<application>` タグを更新して、アプリが最終的な値を提供し、マニフェストマージャーにライブラリの値を置き換えるよう指示します: ```xml <application android:name=".App" android:allowBackup="true" android:fullBackupContent="@xml/sample_backup_rules" android:dataExtractionRules="@xml/sample_data_extraction_rules" tools:replace="android:fullBackupContent,android:dataExtractionRules"> ... </application> ``` いずれかのSDKが `android:allowBackup` も設定している場合は、`tools:replace` に含めてください: ```xml tools:replace="android:allowBackup,android:fullBackupContent,android:dataExtractionRules" ``` #### 3. マージしたバックアップルールファイルを作成する \{#3-create-merged-backup-rules-files\} AndroidプロジェクトのAdaptyのルールとほかのSDKのルールを組み合わせた `res/xml/` ディレクトリにXMLファイルを作成します。AndroidはOSのバージョンによって異なるバックアップルール形式を使用するため、両方のファイルを作成することで、アプリがサポートするすべてのAndroidバージョンとの互換性が確保されます。 :::note 以下の例では、サンプルのサードパーティSDKとしてAppsFlyerを使用しています。アプリで使用しているほかのSDKのルールに置き換えるか、追加してください。 ::: **Android 12以降**(新しいデータ抽出ルール形式を使用): ```xml title="sample_data_extraction_rules.xml" <?xml version="1.0" encoding="utf-8"?> <data-extraction-rules> <cloud-backup> <exclude domain="sharedpref" path="appsflyer-data"/> <exclude domain="sharedpref" path="appsflyer-purchase-data"/> <exclude domain="database" path="afpurchases.db"/> <exclude domain="sharedpref" path="AdaptySDKPrefs.xml"/> </cloud-backup> <device-transfer> <exclude domain="sharedpref" path="appsflyer-data"/> <exclude domain="sharedpref" path="appsflyer-purchase-data"/> <exclude domain="database" path="afpurchases.db"/> <exclude domain="sharedpref" path="AdaptySDKPrefs.xml"/> </device-transfer> </data-extraction-rules> ``` **Android 11以前**(従来のフルバックアップコンテンツ形式を使用): ```xml title="sample_backup_rules.xml" <?xml version="1.0" encoding="utf-8"?> <full-backup-content> <exclude domain="sharedpref" path="appsflyer-data"/> <exclude domain="sharedpref" path="AdaptySDKPrefs.xml"/> :::tip ネイティブ Android ファイルを変更した後は、`npx cap sync android` を実行してプラットフォームを再生成した際に Capacitor が更新されたリソースを取得できるようにしてください。 ::: #### Android で別のアプリから戻った後に購入が失敗する \{#purchases-fail-after-returning-from-another-app-in-android\} 購入フローを開始する Activity が非デフォルトの `launchMode` を使用している場合、ユーザーが Google Play、銀行アプリ、またはブラウザから戻ったときに Android がその Activity を誤って再作成または再利用することがあります。これにより、購入結果が失われたりキャンセルとして処理されたりすることがあります。 購入が正しく機能するようにするには、購入フローを開始する Activity に `standard` または `singleTop` の起動モードのみを使用し、他のモードは避けてください。 `AndroidManifest.xml` で、購入フローを開始する Activity が `standard` または `singleTop` に設定されていることを確認してください。 ```xml <activity android:name=".MainActivity" android:launchMode="standard" /> ``` #### Podfile の SWIFT_VERSION 上書きによる Swift 6 ビルドエラー \{#swift-6-build-errors-caused-by-podfile-swift_version-override\} iOS 向けに Capacitor アプリをビルドする際に、Adapty pod ターゲットで Swift 6 のコンパイルエラーが発生することがあります。典型的な症状としては、`AdaptyUIBuilderLogic` での `@Sendable` の不一致、Adapty 型での `Sendable` 適合の欠如、またはアクター分離エラーなどがあります。 Adapty pods は `s.swift_version = '6.0'` を宣言しており、ビルドに Swift 6 が必要です。アプリ独自のコードは Swift 5 のままでも構いません。Swift 6 でのビルドが必要なのは Adapty pod ターゲット(`Adapty`、`AdaptyUI`、`AdaptyUIBuilder`、`AdaptyLogger`、`AdaptyPlugin`)のみです。 最もよくある原因は、`ios/App/Podfile` の `post_install` フックがすべての pod ターゲットの `SWIFT_VERSION` を上書きしていることです。 ```ruby showLineNumbers title="ios/App/Podfile" post_install do |installer| installer.pods_project.targets.each do |target| target.build_configurations.each do |config| config.build_settings['SWIFT_VERSION'] = '5.9' end end end ``` **修正方法**: Adapty pod ターゲットを上書きから除外してください。 ```ruby showLineNumbers title="ios/App/Podfile" post_install do |installer| installer.pods_project.targets.each do |target| next if %w[Adapty AdaptyUI AdaptyUIBuilder AdaptyLogger AdaptyPlugin].include?(target.name) target.build_configurations.each do |config| config.build_settings['SWIFT_VERSION'] = '5.9' end end end ``` その後、`npx cap sync ios` を実行してリビルドしてください。 確認するには、`ios/App/Pods/Pods.xcodeproj` を開き、`Adapty` pod ターゲットを選択して **Build Settings** → **Swift Language Version** を確認します。**Swift 6** になっている必要があります。 --- # File: capacitor-quickstart-paywalls --- --- title: "Capacitor SDKでペイウォールを使って購入を有効にする" description: "Adapty SDKを使用してCapacitorアプリにペイウォールを表示する方法を学びましょう。" --- アプリ内課金を有効にするには、次の3つの主要な概念を理解する必要があります。 - **プロダクト** – ユーザーが購入できるもの(サブスクリプション、消耗型アイテム、永続アクセス) - **ペイウォール** – どのプロダクトを提供するかを定義する設定です。Adaptyではペイウォールを通じてのみプロダクトを取得できますが、この設計によりアプリのコードを変更せずにオファー内容、価格、プロダクトの組み合わせを変更できます。 - **プレースメント** – アプリ内でペイウォールをどこでいつ表示するか(`main`、`onboarding`、`settings` など)。ダッシュボードでプレースメントにペイウォールを設定し、コード内ではプレースメントIDで取得します。これによりA/Bテストの実行や、ユーザーごとに異なるペイウォールの表示が簡単になります。 Adaptyではアプリに購入機能を実装するための方法を3つ提供しています。アプリの要件に応じて選択してください。 | 実装方法 | 複雑さ | 使うタイミング | |-------------------------------|------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Adapty ペイウォールビルダー** | ✅ 簡単 | [ノーコードビルダーで購入対応ペイウォールを作成します](quickstart-paywalls)。Adaptyが自動的にレンダリングし、複雑な購入フロー、レシート検証、サブスクリプション管理をすべて裏側で処理します。 | | `makePurchase` | 🟡 中程度 | アプリのコードでペイウォールUIを実装しますが、プロダクトオファーの柔軟性を保つためにAdaptyからペイウォールオブジェクトを取得します。[ガイド](capacitor-quickstart-manual)をご覧ください。 | | オブザーバーモード | 🔴 難しい | 購入フローを完全に自分で実装します。[ガイド](implement-observer-mode-capacitor)をご覧ください。 | :::important **以下の手順は、Adaptyペイウォールビルダーで作成したペイウォールの実装方法を示しています。** ペイウォールビルダーを使用しない場合は、[手動作成ペイウォールでの購入処理ガイド](capacitor-making-purchases)をご覧ください。 ::: Adaptyペイウォールビルダーで作成したペイウォールを表示するには、アプリのコードで次の3つの手順のみ必要です。 1. **ペイウォールを取得する**: AdaptyからペイウォールのObjectを取得します。 2. **ペイウォールを表示する(購入はAdaptyが処理)**: 取得したペイウォールコンテナをアプリに表示します。 3. **ボタンアクションを処理する**: ペイウォール上のユーザー操作とアプリの応答を関連付けます。たとえば、ユーザーがボタンをクリックしたときにリンクを開いたりペイウォールを閉じたりします。 ## 始める前に \{#before-you-start\} 始める前に、次の手順を完了してください。 1. Adaptyダッシュボードでアプリを[App Store](initial_ios)または[Google Play](initial-android)(あるいはその両方)に接続します。 2. Adaptyで[プロダクトを作成します](create-product)。 3. [ペイウォールを作成してプロダクトを追加します](create-paywall)。 4. [プレースメントを作成してペイウォールを追加します](create-placement)。 5. アプリのコードに[Adapty SDKをインストールして有効化します](sdk-installation-capacitor)。 :::tip これらの手順を最速で完了するには、[クイックスタートガイド](quickstart)に従うか、[Developer CLI](developer-cli-quickstart)を使ってペイウォールとプレースメントを作成してください。 ::: ## 1. ペイウォールを取得する \{#1-get-the-paywall\} ペイウォールはダッシュボードで設定したプレースメントに関連付けられています。プレースメントを使うことで、異なるオーディエンスに異なるペイウォールを表示したり、[A/Bテスト](ab-tests)を実行したりできます。 Adaptyペイウォールビルダーで作成したペイウォールを取得するには、次の手順が必要です。 1. `getPaywall` メソッドを使って[プレースメント](placements)IDで `paywall` オブジェクトを取得し、`hasViewConfiguration` プロパティでビルダーで作成したペイウォールかどうかを確認します。 2. `createPaywallView` メソッドを使ってペイウォールビューを作成します。このビューにはペイウォールを表示するためのUI要素とスタイリングが含まれています。 :::important ビュー設定を取得するには、ペイウォールビルダーで **Show on device** トグルをオンにする必要があります。そうしないと、空のビュー設定が返され、ペイウォールが表示されません。 ::: ```typescript showLineNumbers title="Capacitor" try { const paywall = await adapty.getPaywall({ placementId: 'YOUR_PLACEMENT_ID', }); // the requested paywall } catch (error) { // handle the error } if (paywall.hasViewConfiguration) { try { const view = await createPaywallView(paywall); } catch (error) { // handle the error } } else { // use your custom logic } ``` ## 2. ペイウォールを表示する \{#2-display-the-paywall\} ペイウォールの設定を取得したら、数行のコードを追加するだけでペイウォールを表示できます。 ペイウォールを表示するには、`createPaywallView` メソッドで作成した `view` に対して `view.present()` メソッドを呼び出します。各 `view` は一度しか使用できません。再度ペイウォールを表示する必要がある場合は、`createPaywallView` をもう一度呼び出して新しい `view` インスタンスを作成してください。 ```typescript showLineNumbers title="Capacitor" try { await view.present(); } catch (error) { // handle the error } ``` :::tip ペイウォールの表示方法についての詳細は、[ガイド](capacitor-present-paywalls)をご覧ください。 ::: ## 3. ボタンアクションを処理する \{#3-handle-button-actions\} ユーザーがペイウォール内のボタンをクリックすると、Capacitor SDKは購入、復元、ペイウォールのクローズを自動的に処理します。 ただし、カスタムまたは事前定義のIDを持つボタンはコード内でアクションを処理する必要があります。また、デフォルトの動作をオーバーライドしたい場合もあります。 たとえば、ユーザーがWebリンクを開いた後もペイウォールを開いたままにしたい場合があります。実装でどのように処理できるか見てみましょう。 :::tip ボタンの[アクション](capacitor-handle-paywall-actions)と[イベント](capacitor-handling-events)の処理方法については、各ガイドをご覧ください。 ::: ```typescript showLineNumbers title="Capacitor" const unsubscribe = view.setEventHandlers({ onUrlPress(url) { window.open(url, '_blank'); return false; }, }); ``` ## 次のステップ \{#next-steps\} --- no_index: true --- import Callout from '../../../components/Callout.astro'; <Callout type="tip"> ご質問やお困りのことがあれば、[サポートフォーラム](https://adapty.featurebase.app/)をご覧ください。よくある質問への回答を見つけたり、ご自身の質問を投稿することができます。チームとコミュニティがサポートいたします! </Callout> ペイウォールをアプリに表示する準備ができました。[App Storeのサンドボックス](test-purchases-in-sandbox)または[Google Play Store](testing-on-android)でテスト購入を行い、ペイウォールからのテスト購入が正常に完了することを確認してください。 次に、適切なユーザーにペイウォールを表示したり有料機能へのアクセスを付与したりするため、[ユーザーのアクセスレベルを確認する](capacitor-check-subscription-status)必要があります。 ## 完全なサンプル \{#full-example\} 以下は、これらすべての手順をアプリに統合した例です。 ```typescript showLineNumbers title="Capacitor" export default function PaywallScreen() { const showPaywall = async () => { try { const paywall = await adapty.getPaywall({ placementId: 'YOUR_PLACEMENT_ID', }); if (!paywall.hasViewConfiguration) { // use your custom logic return; } const view = await createPaywallView(paywall); view.setEventHandlers({ onUrlPress(url) { window.open(url, '_blank'); return false; }, }); await view.present(); } catch (error) { // handle any error that may occur during the process console.warn('Error showing paywall:', error); } }; return ( <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100vh' }}> <button onClick={showPaywall}>Show Paywall</button> </div> ); } ``` --- # File: capacitor-check-subscription-status --- --- title: "Capacitor SDKでサブスクリプションステータスを確認する" description: "AdaptyでCapacitorアプリのサブスクリプションステータスを確認する方法を学びましょう。" --- ユーザーが有料コンテンツにアクセスできるか、またはペイウォールを表示するかを決めるには、プロファイルの[アクセスレベル](access-level)を確認する必要があります。 この記事では、ユーザーにペイウォールを表示するか、有料機能へのアクセスを許可するかを判断するために、プロファイルの状態を取得する方法を説明します。 ## サブスクリプションステータスを取得する \{#get-subscription-status\} ペイウォールまたは有料コンテンツを表示するかどうかを判断する際、ユーザーのプロファイルにある[アクセスレベル](access-level)を確認します。方法は2つあります: - アプリ起動時など、すぐに最新のプロファイルデータが必要な場合や強制的に更新したい場合は`getProfile`を呼び出します。 - サブスクリプションのステータスが変わるたびに自動的に更新されるローカルコピーを保持するには、**自動プロファイル更新**を設定します。 ### プロファイルを取得する \{#get-profile\} サブスクリプションステータスを取得する最も簡単な方法は、`getProfile`メソッドを使ってプロファイルにアクセスすることです: ```typescript showLineNumbers try { const profile = await adapty.getProfile(); } catch (error) { // handle the error } ``` ### サブスクリプション更新をリッスンする \{#listen-to-subscription-updates\} アプリでプロファイルの更新を自動的に受け取るには: 1. `adapty.addListener('onLatestProfileLoad')`を使ってプロファイルの変化をリッスンします。ユーザーのサブスクリプションステータスが変わるたびに、Adaptyが自動的にこのメソッドを呼び出します。 2. このメソッドが呼び出されたときに更新されたプロファイルデータを保存しておくと、追加のネットワークリクエストなしにアプリ全体で利用できます。 ```typescript showLineNumbers class SubscriptionManager { private currentProfile: any = null; constructor() { // Listen for profile updates adapty.addListener('onLatestProfileLoad', (data) => { this.currentProfile = data.profile; // Update UI, unlock content, etc. }); } // Use stored profile instead of calling getProfile() hasAccess(): boolean { return this.currentProfile?.accessLevels?.['YOUR_ACCESS_LEVEL']?.isActive ?? false; } } ``` :::note Adaptyはアプリ起動時に自動的に`onLatestProfileLoad`イベントリスナーを呼び出し、デバイスがオフラインの場合でもキャッシュされたサブスクリプションデータを提供します。 ::: ## プロファイルとペイウォールのロジックを連携させる \{#connect-profile-with-paywall-logic\} ペイウォールの表示や有料機能へのアクセス許可をすぐに判断する必要がある場合は、ユーザーのプロファイルを直接確認できます。このアプローチは、アプリ起動時、プレミアムセクションへの入室時、特定コンテンツの表示前などのシナリオに役立ちます。 ```typescript showLineNumbers const checkAccessLevel = async () => { try { const profile = await adapty.getProfile(); return profile?.accessLevels?.['YOUR_ACCESS_LEVEL']?.isActive === true; } catch (error) { console.warn('Error checking access level:', error); return false; // Show paywall if access check fails } }; const getAccessLevel = () => { return profile?.accessLevels?.['YOUR_ACCESS_LEVEL']; }; const initializePaywall = async () => { try { await loadPaywall(); const hasAccess = await checkAccessLevel(); if (!hasAccess) { // Show paywall if no access } } catch (error) { console.warn('Error initializing paywall:', error); } }; ``` ## 次のステップ \{#next-steps\} サブスクリプションステータスの確認方法がわかったら、次は[ユーザープロファイルの操作](capacitor-quickstart-identify)について学び、ユーザーが購入したコンテンツに確実にアクセスできるようにしましょう。 --- # File: capacitor-quickstart-identify --- --- title: "Capacitor SDKでユーザーを識別する" description: "Capacitorでのアプリ内サブスクリプション管理のためのAdaptyセットアップ クイックスタートガイド。" --- ユーザーの購入管理方法は、アプリの認証モデルによって異なります: - アプリでバックエンド認証を使用せず、ユーザーデータを保存しない場合は、[匿名ユーザーに関するセクション](#anonymous-users)をご覧ください。 - アプリにバックエンド認証がある(または予定している)場合は、[識別済みユーザーに関するセクション](#identified-users)をご覧ください。 :::tip **主な概念**: - **プロファイル**は、SDKが機能するために必要なエンティティです。Adaptyが自動的に作成します。匿名(カスタマーユーザーIDなし)または識別済み(カスタマーユーザーIDあり)のいずれかになります。 - **カスタマーユーザーID**は、**あなたが作成する**オプションの識別子で、ユーザーをAdaptyプロファイルに紐付けるために使用します。 ::: 匿名ユーザーと識別済みユーザーの違いは次のとおりです: | | 匿名ユーザー | 識別済みユーザー | |-------------------------|------------------------------------------------------|-------------------------------------------------------------------------| | **購入管理** | ストアレベルの購入復元 | カスタマーユーザーIDを通じてデバイスをまたいで購入履歴を維持 | | **プロファイル管理** | 再インストールごとに新しいプロファイルが作成される | セッションやデバイスをまたいで同じプロファイルを使用 | | **データの永続性** | 匿名ユーザーのデータはデバイス/インストールに紐付けられる | 識別済みユーザーのデータはデバイスやセッションをまたいで保持される | ## 匿名ユーザー \{#anonymous-users\} バックエンド認証がない場合、**アプリのコードで認証を処理する必要はありません**: 1. アプリの初回起動時にSDKが有効化されると、Adaptyが**ユーザーの新しいプロファイルを作成**します。 2. ユーザーがアプリ内で何かを購入すると、その購入は**そのユーザーのAdaptyプロファイルとストアアカウントに関連付け**られます。 3. ユーザーがアプリを**再インストール**したり、**新しいデバイス**にインストールしたりすると、Adaptyは有効化時に**新しい空のプロファイルを作成**します。 4. ユーザーがアプリで以前に購入をしていた場合、デフォルトでは、SDKの有効化時にApp Storeから購入が自動的に同期されます。 :::note バックアップからの復元は、再インストールとは動作が異なります。デフォルトでは、ユーザーがバックアップから復元した場合、SDKはキャッシュされたデータを保持し、新しいプロファイルを作成しません。この動作は`clearDataOnBackup`設定で変更できます。[詳細はこちら](sdk-installation-capacitor#clear-data-on-backup-restore)。 ::: ## 識別済みユーザー \{#identified-users\} - プロファイルにまだカスタマーユーザーIDがない場合(つまり、**ユーザーがサインインしていない**場合)、カスタマーユーザーIDを送信すると、そのプロファイルに関連付けられます。 - **再インストール、サインイン、または新しいデバイスからのインストール**で、以前にそのカスタマーユーザーIDを送信したことがある場合、新しいプロファイルは作成されません。代わりに、そのカスタマーユーザーIDに関連付けられた既存のプロファイルに切り替わります。 アプリでユーザーを識別する方法は2つあります: - [**ログイン/サインアップ時:**](#during-loginsignup) アプリ起動後にユーザーがサインインする場合、認証時に`identify()`をカスタマーユーザーIDとともに呼び出します。 - [**SDK有効化時:**](#during-the-sdk-activation) アプリ起動時にすでにカスタマーユーザーIDが保存されている場合、`activate()`を呼び出す際に送信します。 :::important デフォルトでは、Adaptyが現在別のカスタマーユーザーIDに関連付けられているカスタマーユーザーIDからの購入を受け取った場合、アクセスレベルは共有され、両方のプロファイルが有料アクセスを持ちます。この設定を変更して、有料アクセスを1つのプロファイルから別のプロファイルに移動したり、共有を完全に無効にしたりすることができます。詳細は[こちらの記事](general#6-sharing-paid-access-between-user-accounts)をご覧ください。 ::: <img src="/assets/shared/img/identify-diagram.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### ログイン/サインアップ時 \{#during-loginsignup\} アプリ起動後にユーザーを識別する場合(例:アプリへのログインやサインアップ後)は、`identify`メソッドを使用してカスタマーユーザーIDを設定します。 - **このカスタマーユーザーIDを以前に使用したことがない**場合、Adaptyは自動的にそれを現在のプロファイルに紐付けます。 - **このカスタマーユーザーIDを以前にユーザーの識別に使用したことがある**場合、AdaptyはそのカスタマーユーザーIDに関連付けられたプロファイルに切り替えます。 :::tip カスタマーユーザーIDを作成する際は、ユーザーデータと一緒に保存しておくと、新しいデバイスからログインした場合やアプリを再インストールした際に同じIDを送信できます。 ::: 他のSDKメソッドを呼び出す前に、必ず`identify`を`await`してください。並行して呼び出すと`#3006 profileWasChanged`が発生するか、匿名プロファイルに対して操作が行われます。[Capacitor SDKの呼び出し順序](capacitor-sdk-call-order)を参照してください。 ```typescript showLineNumbers try { await adapty.identify({ customerUserId: "YOUR_USER_ID" }); // successfully identified } catch (error) { // handle the error } ``` ### SDK有効化時 \{#during-the-sdk-activation\} SDKを有効化するときにすでにカスタマーユーザーIDがわかっている場合は、`identify`を別途呼び出す代わりに、`activate`メソッドで送信できます。 カスタマーユーザーIDがわかっていても、有効化後にのみ設定する場合、有効化時にAdaptyは新しい空のプロファイルを作成し、`identify`を呼び出した後にのみ既存のプロファイルに切り替わります。 既存のカスタマーユーザーID(以前に使用したもの)と新しいもののどちらでも渡すことができます。新しいものを渡した場合、有効化時に作成された新しいプロファイルが自動的にそのカスタマーユーザーIDに紐付けられます。 :::tip 作成された空のプロファイルをダッシュボードのアナリティクスから除外するには、**App settings**に移動して[**Installs definition for analytics**](general#4-installs-definition-for-analytics)を設定してください。 ::: ```typescript showLineNumbers await adapty.activate({ apiKey: "YOUR_PUBLIC_SDK_KEY", params: { customerUserId: "YOUR_USER_ID" } }); ``` ### ユーザーをログアウトする \{#log-users-out\} ユーザーをログアウトするボタンがある場合は、`logout`メソッドを使用します。これにより、ユーザーに新しい匿名プロファイルIDが作成されます。 ```typescript showLineNumbers try { await adapty.logout(); // successful logout } catch (error) { // handle the error } ``` :::info ユーザーをアプリに再度ログインさせるには、`identify`メソッドを使用してください。 ::: ### ログインせずに購入を許可する \{#allow-purchases-without-login\} ユーザーがアプリにログインする前後の両方で購入できる場合、追加の設定は不要です: 仕組みは次のとおりです: 1. ログアウト状態のユーザーが購入を行うと、Adaptyはその購入を匿名プロファイルIDに紐付けます。 2. ユーザーがアカウントにログインすると、Adaptyは識別済みプロファイルに切り替えます。 - 既存のカスタマーユーザーID(すでにプロファイルに紐付けられているカスタマーユーザーID)の場合、Adaptyはトランザクションを自動的に同期します。 - 新しいカスタマーユーザーID(例:登録前に購入が行われた場合)の場合、Adaptyは現在のプロファイルにカスタマーユーザーIDを割り当て、すべての購入履歴が維持されます。 --- # File: adapty-sdk-integration-skill-capacitor --- --- title: "SDKインテグレーションスキルを使ってAdaptyをCapacitorアプリに導入する" description: "adapty-sdk-integrationスキルを使って、AIコーディングツールでCapacitorアプリにAdapty SDKをエンドツーエンドで統合する方法を説明します。" --- :::important このスキルはベータ版です。処理が止まったり予期しない動作が発生した場合は、代わりに[ステップバイステップの統合ガイド](adapty-cursor-capacitor)を参照してください。AIツールが各ステップを正しいドキュメントに沿って進められるよう案内しています。 ::: --- no_index: true --- [adapty-sdk-integration スキル](https://github.com/adaptyteam/adapty-sdk-integration-skill)は、Adapty のインテグレーションをエンドツーエンドで自動化します。ダッシュボードのセットアップ、SDK のインストール、ペイウォール、各ステージの検証まで対応しています。プラットフォームを自動検出し、各ステージで関連する Adapty ドキュメントを取得します。 **対応ツール**: Claude Code、GitHub Copilot CLI、OpenAI Codex、Gemini CLI。 インストールするには、お使いのツール向けのフォームを選択してください。完全なリストは[スキルの README](https://github.com/adaptyteam/adapty-sdk-integration-skill) をご覧ください。 **Claude Code** ``` claude plugin marketplace add adaptyteam/adapty-sdk-integration-skill claude plugin install adapty-sdk-integration@adapty ``` **GitHub Copilot CLI** ``` gh skill install adaptyteam/adapty-sdk-integration-skill ``` **Gemini CLI** ``` gemini skills install https://github.com/adaptyteam/adapty-sdk-integration-skill ``` **OpenAI Codex またはその他のツール**: リポジトリをクローンし、`plugins/adapty-sdk-integration/skills/adapty-sdk-integration/` をツールのスキルディレクトリにコピーしてください。 インストール後、プロジェクト内でスキルを実行します: ``` /adapty-sdk-integration ``` スキルがいくつかのセットアップ質問を行い、その後ダッシュボードのセットアップ、SDK のインストール、ペイウォール、検証の手順を案内します。 --- # File: adapty-cursor-capacitor --- --- title: "AIアシスタントを使ってCapacitorアプリにAdaptyを統合する" description: "Cursor、Context7、ChatGPT、Claude、その他のAIツールを使ってCapacitorアプリにAdaptyを統合するステップバイステップガイド。" --- このガイドでは、AIコーディングツールを使ってCapacitorアプリにAdaptyを段階的に統合する方法を説明します。適切なAdaptyドキュメントを適切な順序でAIに提供することで、スムーズに進められます。 For a fully automated integration, use the [adapty-sdk-integration skill](https://github.com/adaptyteam/adapty-sdk-integration-skill): it runs the whole integration from your AI coding tool in one command. ## はじめる前に:ダッシュボードの設定 \{#before-you-start-dashboard-setup\} AdaptyはSDKコードを書く前に、いくつかのダッシュボード設定が必要です。インタラクティブなLLMスキルを使うか、ダッシュボードから手動で設定できます。 ### スキルを使う方法(推奨) \{#skill-approach-recommended\} Adapty CLIスキルを使うと、LLMがアプリ、プロダクト、アクセスレベル、ペイウォール、プレースメントを直接設定できます。各ステップでダッシュボードを開く必要がありません。[ストアの接続](integrate-payments)だけダッシュボードで行う必要があります。 ``` npx skills add adaptyteam/adapty-cli --skill adapty-cli ``` スキルを追加したら、エージェントで `/adapty-cli` を実行してください。ストアの接続が必要なタイミングも含め、各ステップをガイドしてくれます。 ### ダッシュボードを使う方法 \{#dashboard-approach\} すべて手動で設定したい場合は、コードを書く前に以下の準備が必要です。LLMはダッシュボードの値を調べることはできないため、ご自身で提供する必要があります。 1. **アプリストアを接続する**: Adapty ダッシュボードで **App settings → General** に移動します。CapacitorアプリがiOSとAndroidの両方を対象とする場合は、App StoreとGoogle Playの両方を接続してください。これは購入処理に必須です。 [アプリストアを接続する](integrate-payments) 2. **パブリックSDKキーをコピーする**: Adapty ダッシュボードで **App settings → General** に移動し、**API keys** セクションを確認します。コード上では、これが `adapty.activate()` に渡す文字列です。 3. **プロダクトを少なくとも1つ作成する**: Adapty ダッシュボードの **Products** ページでプロダクトを作成します。コードからプロダクトを直接参照することはなく、Adaptyはペイウォールを通じてプロダクトを提供します。 [プロダクトを追加する](quickstart-products) 4. **ペイウォールとプレースメントを作成する**: Adapty ダッシュボードの **Paywalls** ページでペイウォールを作成し、**Placements** ページでプレースメントに割り当てます。コード上では、プレースメントIDが `adapty.getPaywall()` に渡す文字列です。 [ペイウォールを作成する](quickstart-paywalls) 5. **アクセスレベルを設定する**: Adapty ダッシュボードの **Products** ページでプロダクトごとに設定します。コード上では、`profile.accessLevels['premium']?.isActive` でチェックする文字列です。デフォルトの `premium` アクセスレベルはほとんどのアプリで機能します。プロダクトによってユーザーがアクセスできる機能が異なる場合(例:`basic` プランと `pro` プラン)は、コーディングを始める前に[追加のアクセスレベルを作成](assigning-access-level-to-a-product)してください。 :::tip この5つが揃えば、コードを書く準備ができています。LLMに「パブリックSDKキーはX、プレースメントIDはY」と伝えると、正確な初期化とペイウォール取得のコードを生成してもらえます。 ::: ### 準備ができたら設定すること \{#set-up-when-ready\} コーディングを始める前に必須ではありませんが、統合が成熟するにつれて必要になります: - **A/B テスト**: **Placements** ページで設定します。コードの変更は不要です。 [A/B テスト](ab-tests) - **追加のペイウォールとプレースメント**: 異なるプレースメントIDで `getPaywall` の呼び出しを追加します。 - **アナリティクス連携**: **Integrations** ページで設定します。セットアップは連携先によって異なります。[アナリティクス連携](analytics-integration)と[アトリビューション連携](attribution-integration)を参照してください。 ## AdaptyドキュメントをLLMに提供する \{#feed-adapty-docs-to-your-llm\} ### Context7を使う(推奨) \{#use-context7-recommended\} [Context7](https://context7.com)は、LLMが最新のAdaptyドキュメントに直接アクセスできるMCPサーバーです。質問内容に基づいて適切なドキュメントを自動的に取得するため、URLを手動で貼り付ける必要がありません。 Context7は**Cursor**、**Claude Code**、**Windsurf**、その他のMCP対応ツールで動作します。セットアップするには以下を実行してください: ``` npx ctx7 setup ``` これによりエディタが検出され、Context7サーバーが設定されます。手動セットアップの場合は[Context7 GitHubリポジトリ](https://github.com/upstash/context7)を参照してください。 設定後は、プロンプトでAdaptyライブラリを参照してください: ``` Use the adaptyteam/adapty-docs library to look up how to install the Capacitor SDK ``` :::warning Context7を使えばドキュメントのリンクを手動で貼り付ける必要はなくなりますが、実装の順序は重要です。すべてが正しく動作するよう、以下の[実装ウォークスルー](#implementation-walkthrough)をステップごとに確認してください。 ::: ### プレーンテキストのドキュメントを使う \{#use-plain-text-docs\} Adaptyのドキュメントはプレーンテキストのマークダウンとして取得できます。URLの末尾に `.md` を追加するか、記事タイトルの下にある **Copy for LLM** をクリックしてください。例:[adapty-cursor-capacitor.md](https://adapty.io/docs/ja/adapty-cursor-capacitor.md) 以下の[実装ウォークスルー](#implementation-walkthrough)の各ステージには、貼り付け用の `.md` リンクが含まれた「LLMに送るもの」ブロックがあります。 一度に複数のドキュメントが必要な場合は、以下の[インデックスファイルとプラットフォーム別サブセット](#plain-text-doc-index-files)を参照してください。 ## 実装ウォークスルー \{#implementation-walkthrough\} このガイドの残りでは、実装順序に沿ってAdapty統合を進めていきます。各ステージには、LLMに送るドキュメント、完了時に確認できること、よくある問題が含まれています。 ### 統合を計画する \{#plan-your-integration\} コードに取り掛かる前に、LLMにプロジェクトを分析して実装計画を立てるよう依頼してください。AIツールが計画モードをサポートしている場合(CursorやClaude Codeのプランモードなど)、LLMがコードを書く前にプロジェクト構造とAdaptyドキュメントの両方を確認できるよう、そのモードを使用してください。 購入処理のアプローチをLLMに伝えてください。これによって参照すべきガイドが変わります: - [**Adapty ペイウォールビルダー**](adapty-paywall-builder): Adaptyのノーコードビルダーでペイウォールを作成し、SDKが自動的にレンダリングします。 - [**手動作成のペイウォール**](capacitor-making-purchases): コードで独自のペイウォールUIを構築しますが、プロダクトの取得と購入処理にはAdaptyを使います。 - [**オブザーバーモード**](observer-vs-full-mode): 既存の購入インフラを維持し、アナリティクスと連携にのみAdaptyを使います。 どれを選べばよいかわからない場合は、[クイックスタートの比較表](capacitor-quickstart-paywalls)を参照してください。 ### SDKをインストールして設定する \{#install-and-configure-the-sdk\} npmでAdapty SDKの依存関係を追加し、パブリックSDKキーで有効化します。これが基盤となるため、これなしでは他の機能は動作しません。 **ガイド:** [Adapty SDKのインストールと設定](sdk-installation-capacitor) LLMに送るもの: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/sdk-installation-capacitor.md ``` :::tip[チェックポイント] - **期待される結果:** iOSとAndroidの両方でアプリがビルド・起動し、コンソールにAdaptyのアクティベーションログが表示される。 - **注意点:** "Public API key is missing" → **App settings** の実際のキーでプレースホルダーを置き換えているか確認してください。 ::: ### ペイウォールを表示して購入を処理する \{#show-paywalls-and-handle-purchases\} プレースメントIDでペイウォールを取得し、表示して、購入イベントを処理します。必要なガイドは購入処理の方法によって異なります。 進めながら各購入をサンドボックスでテストしてください — 最後まで待つ必要はありません。セットアップ手順については[サンドボックスでの購入テスト](test-purchases-in-sandbox)を参照してください。 <Tabs groupId="paywall-approach"> <TabItem value="builder" label="Paywall Builder" default> **ガイド:** - [ペイウォールを使って購入を有効化する(クイックスタート)](capacitor-quickstart-paywalls) - [ペイウォールビルダーのペイウォールと設定を取得する](capacitor-get-pb-paywalls) - [ペイウォールを表示する](capacitor-present-paywalls) - [ペイウォールイベントを処理する](capacitor-handling-events) - [ボタンアクションに応答する](capacitor-handle-paywall-actions) LLMに送るもの: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/capacitor-quickstart-paywalls.md - https://adapty.io/docs/ja/capacitor-get-pb-paywalls.md - https://adapty.io/docs/ja/capacitor-present-paywalls.md - https://adapty.io/docs/ja/capacitor-handling-events.md - https://adapty.io/docs/ja/capacitor-handle-paywall-actions.md ``` :::tip[チェックポイント] - **期待される結果:** 設定したプロダクトとともにペイウォールが表示される。プロダクトをタップするとサンドボックス購入ダイアログが表示される。 - **注意点:** ペイウォールが空か `getPaywall` エラー → プレースメントIDがダッシュボードと完全に一致しているか、プレースメントにオーディエンスが割り当てられているか確認してください。 ::: </TabItem> <TabItem value="manual" label="Manual paywalls"> **ガイド:** - [カスタムペイウォールで購入を有効化する(クイックスタート)](capacitor-quickstart-manual) - [ペイウォールとプロダクトを取得する](fetch-paywalls-and-products-capacitor) - [リモートコンフィグで設計されたペイウォールをレンダリングする](present-remote-config-paywalls-capacitor) - [購入を行う](capacitor-making-purchases) - [購入を復元する](capacitor-restore-purchase) LLMに送るもの: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/capacitor-quickstart-manual.md - https://adapty.io/docs/ja/fetch-paywalls-and-products-capacitor.md - https://adapty.io/docs/ja/present-remote-config-paywalls-capacitor.md - https://adapty.io/docs/ja/capacitor-making-purchases.md - https://adapty.io/docs/ja/capacitor-restore-purchase.md ``` :::tip[チェックポイント] - **期待される結果:** カスタムペイウォールにAdaptyから取得したプロダクトが表示される。プロダクトをタップするとサンドボックス購入ダイアログが表示される。 - **注意点:** プロダクト配列が空 → ダッシュボードでペイウォールにプロダクトが割り当てられているか、プレースメントにオーディエンスが設定されているか確認してください。 ::: </TabItem> <TabItem value="observer" label="Observer mode"> **ガイド:** - [オブザーバーモードの概要](observer-vs-full-mode) - [オブザーバーモードを実装する](implement-observer-mode-capacitor) - [オブザーバーモードでトランザクションを報告する](report-transactions-observer-mode-capacitor) LLMに送るもの: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/observer-vs-full-mode.md - https://adapty.io/docs/ja/implement-observer-mode-capacitor.md - https://adapty.io/docs/ja/report-transactions-observer-mode-capacitor.md ``` :::tip[チェックポイント] - **期待される結果:** 既存の購入フローでサンドボックス購入を行った後、Adapty ダッシュボードの **Event Feed** にトランザクションが表示される。 - **注意点:** イベントが表示されない → Adaptyにトランザクションを報告しているか、両ストアのサーバー通知が設定されているか確認してください。 ::: </TabItem> </Tabs> ### サブスクリプションステータスを確認する \{#check-subscription-status\} 購入後、ユーザープロファイルのアクティブなアクセスレベルを確認して、プレミアムコンテンツへのアクセスを制御します。 **ガイド:** [サブスクリプションステータスを確認する](capacitor-check-subscription-status) LLMに送るもの: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/capacitor-check-subscription-status.md ``` :::tip[チェックポイント] - **期待される結果:** サンドボックス購入後、`profile.accessLevels['premium']?.isActive` が `true` を返す。 - **注意点:** 購入後に `accessLevels` が空 → ダッシュボードでプロダクトにアクセスレベルが割り当てられているか確認してください。 ::: ### ユーザーを識別する \{#identify-users\} アプリのユーザーアカウントをAdaptyプロファイルにリンクし、デバイスをまたいで購入が引き継がれるようにします。 :::important アプリに認証機能がない場合はこのステップをスキップしてください。 ::: **ガイド:** [ユーザーを識別する](capacitor-quickstart-identify) LLMに送るもの: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/capacitor-quickstart-identify.md ``` :::tip[チェックポイント] - **期待される結果:** `adapty.identify()` を呼び出した後、ダッシュボードの **Profiles** セクションにカスタムユーザーIDが表示される。 - **注意点:** 匿名プロファイルへのアトリビューションを避けるため、アクティベーション後、ペイウォールの取得前に `identify` を呼び出してください。 ::: ### リリース準備をする \{#prepare-for-release\} サンドボックスで統合が正常に動作したら、リリースチェックリストを確認してすべてが本番環境に対応できているか確認しましょう。 **ガイド:** [リリースチェックリスト](release-checklist) LLMに送るもの: ``` Read these Adapty docs before releasing: - https://adapty.io/docs/ja/release-checklist.md ``` :::tip[チェックポイント] - **期待される結果:** すべてのチェックリスト項目を確認済み:ストア接続、サーバー通知、購入フロー、アクセスレベルのチェック、プライバシー要件。 - **注意点:** サーバー通知が未設定 → **App settings → iOS SDK** でApp Store Server Notificationsを設定し、**App settings → Android SDK** でGoogle Play Real-Time Developer Notificationsを設定してください。 ::: ## プレーンテキストのドキュメントインデックスファイル \{#plain-text-doc-index-files\} 個別のページを超えてLLMにより広いコンテキストを提供する必要がある場合、Adaptyのすべてのドキュメントを一覧表示または統合したインデックスファイルを提供しています: - [`llms.txt`](https://adapty.io/docs/ja/llms.txt): `.md` リンク付きですべてのページを一覧表示します。LLMがウェブサイトにアクセスできるようにするための[新しい標準](https://llmstxt.org/)です。一部のAIエージェント(ChatGPTなど)では `llms.txt` をダウンロードしてチャットにファイルとしてアップロードする必要があります。 - [`llms-full.txt`](https://adapty.io/docs/ja/llms-full.txt): Adaptyのドキュメントサイト全体を1つのファイルにまとめたものです。非常に大きなファイルなので、全体像が必要な場合にのみ使用してください。 - Capacitor専用の [`capacitor-llms.txt`](https://adapty.io/docs/ja/capacitor-llms.txt) と [`capacitor-llms-full.txt`](https://adapty.io/docs/ja/capacitor-llms-full.txt): サイト全体と比べてトークンを節約できる、プラットフォーム別のサブセットです。 --- # File: capacitor-paywalls --- --- title: "Paywalls" description: "Learn how to work with paywalls in your Capacitor app with Adapty SDK." --- ## Display paywalls ### Adapty Paywall Builder <CustomDocCardList ids={['capacitor-get-pb-paywalls', 'capacitor-present-paywalls', 'capacitor-handling-events', 'capacitor-handle-paywall-actions']} /> :::tip To get started with the Adapty Paywall Builder paywalls quickly, see our [quickstart guide](capacitor-quickstart-paywalls). ::: ### Implement paywalls manually <CustomDocCardList ids={['capacitor-quickstart-manual', 'fetch-paywalls-and-products-capacitor', 'present-remote-config-paywalls-capacitor', 'capacitor-making-purchases']} /> For more guides on implementing paywalls and handling purchases manually, see the [category](capacitor-implement-paywalls-manually). ## Useful features <CustomDocCardList ids={['capacitor-use-fallback-paywalls', 'capacitor-web-paywall']} /> --- # File: capacitor-get-pb-paywalls --- --- title: "Capacitor SDKでペイウォールビルダーのペイウォールとその設定を取得する" description: "Capacitorアプリでサブスクリプション管理を強化するために、AdaptyでPBペイウォールを取得する方法を学びましょう。" --- Adapty ダッシュボードの新しいペイウォールビルダーで[ペイウォールのビジュアルデザインを作成](adapty-paywall-builder)したら、モバイルアプリに表示できます。まず、プレースメントに紐づくペイウォールとそのビュー設定を取得する必要があります。 このトピックはペイウォールビルダーでカスタマイズされたペイウォールについて説明しています。リモートコンフィグペイウォールの取得については、[モバイルアプリでリモートコンフィグペイウォールのペイウォールとプロダクトを取得する](fetch-paywalls-and-products-capacitor)トピックをご参照ください。 <details> <summary>モバイルアプリにペイウォールを表示する前に(クリックして展開)</summary> 1. Adapty ダッシュボードで[プロダクトを作成](create-product)します。 2. Adapty ダッシュボードで[ペイウォールを作成してプロダクトを追加](create-paywall)します。 3. Adapty ダッシュボードで[プレースメントを作成してペイウォールを追加](create-placement)します。 4. モバイルアプリに[Adapty SDK](sdk-installation-capacitor)をインストールします。 </details> ## ペイウォールビルダーで作成されたペイウォールを取得する \{#fetch-paywall-designed-with-paywall-builder\} [ペイウォールビルダーでペイウォールをデザイン](adapty-paywall-builder)した場合、ユーザーに表示するためにモバイルアプリコードでレンダリングを心配する必要はありません。このようなペイウォールには、表示する内容と表示方法の両方が含まれています。ただし、プレースメントを通じてそのIDを取得し、ビュー設定を取得してからモバイルアプリに表示する必要があります。 最適なパフォーマンスを確保するには、ペイウォールと[ビュー設定](capacitor-get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder)をできるだけ早く取得し、ユーザーに表示する前に画像のダウンロードが完了する時間を十分に確保することが重要です。 ペイウォールを取得するには、`getPaywall` メソッドを使用します: ```typescript showLineNumbers try { const paywall = await adapty.getPaywall({ placementId: 'YOUR_PLACEMENT_ID', locale: 'en', }); // the requested paywall } catch (error) { // handle the error } ``` パラメーター: | パラメーター | 必須 | 説明 | |---------|--------|-----------| | **placementId** | 必須 | 取得したい[プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** | <p>任意</p><p>デフォルト: `en`</p> | <p>[ペイウォールのローカライゼーション](add-paywall-locale-in-adapty-paywall-builder)の識別子。このパラメーターはマイナス(**-**)文字で区切られた1つまたは2つのサブタグで構成される言語コードを指定します。最初のサブタグは言語、2番目はリージョンを表します。</p><p></p><p>例:`en` は英語、`pt-br` はブラジルポルトガル語を表します。</p><p>ロケールコードとその推奨使用方法については[ローカライゼーションとロケールコード](localizations-and-locale-codes)をご参照ください。</p> | | **params** | 任意 | ペイウォール取得のための追加パラメーター。 | **プロダクトIDをハードコードしないでください。** ハードコードすべき唯一のIDはプレースメントIDです。ペイウォールはリモートで設定されるため、プロダクト数や利用可能なオファーはいつでも変更される可能性があります。アプリはこれらの変更を動的に処理する必要があります。今日2つのプロダクトを返すペイウォールが明日3つを返しても、コードを変更せずにすべてを表示できるようにしてください。 レスポンスパラメーター: | パラメーター | 説明 | | :-------- |:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Paywall | プロダクトIDのリスト、ペイウォール識別子、リモートコンフィグ、その他のプロパティを含む[`AdaptyPaywall`](https://capacitor.adapty.io/interfaces/adaptypaywall)オブジェクト。 | ## ペイウォールビルダーで作成されたペイウォールのビュー設定を取得する \{#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder\} :::important ペイウォールビルダーの **Show on device** トグルを有効にしてください。このオプションがオンになっていない場合、ビュー設定を取得できません。 ::: ペイウォールを取得したら、`ViewConfiguration` が含まれているかどうかを確認します。これはペイウォールビルダーで作成されたことを示します。`ViewConfiguration` がある場合はペイウォールビルダーのペイウォールとして扱い、ない場合は[リモートコンフィグペイウォールとして処理](present-remote-config-paywalls-capacitor)します。 Capacitor SDKでは、ビュー設定を手動で取得せずに直接 `createPaywallView` メソッドを呼び出します。 :::warning `createPaywallView` メソッドの結果は一度しか使用できません。再度使用する場合は、`createPaywallView` メソッドを新たに呼び出してください。 ::: ```typescript showLineNumbers if (paywall.hasViewConfiguration) { try { const view = await createPaywallView(paywall); } catch (error) { // handle the error } } else { // use your custom logic } ``` パラメーター: | パラメーター | 必須 | 説明 | | :------------------- | :------- | :----------------------------------------------------------- | | **paywall** | 必須 | 目的のペイウォールのコントローラーを取得するための `AdaptyPaywall` オブジェクト。 | | **customTags** | 任意 | カスタムタグとその解決された値の辞書を定義します。カスタムタグはペイウォールコンテンツのプレースホルダーとして機能し、ペイウォール内のパーソナライズされたコンテンツのために特定の文字列に動的に置き換えられます。詳細はペイウォールビルダーのカスタムタグのトピックをご参照ください。 | | **prefetchProducts** | 任意 | 画面上のプロダクト表示タイミングを最適化するために有効にします。`true` の場合、AdaptyUIが必要なプロダクトを自動的に取得します。デフォルト: `false`。 | :::note 複数の言語を使用している場合は、[ペイウォールビルダーのローカライゼーション](add-paywall-locale-in-adapty-paywall-builder)の追加方法と、ロケールコードの正しい使用方法を[こちら](capacitor-localizations-and-locale-codes)で確認してください。 ::: ビューを取得したら、[ペイウォールを表示](capacitor-present-paywalls)します。 ## デフォルトオーディエンスのペイウォールをより早く取得する \{#get-a-paywall-for-a-default-audience-to-fetch-it-faster\} 通常、ペイウォールはほぼ瞬時に取得されるため、このプロセスを高速化することを心配する必要はありません。しかし、多数のオーディエンスとペイウォールがあり、ユーザーのインターネット接続が弱い場合、ペイウォールの取得に想定以上の時間がかかることがあります。そのような状況では、ペイウォールをまったく表示しないよりも、スムーズなユーザー体験を確保するためにデフォルトのペイウォールを表示したい場合があります。 これに対応するために、`getPaywallForDefaultAudience` メソッドを使用できます。このメソッドは **All Users** オーディエンス用に指定されたプレースメントのペイウォールを取得します。ただし、推奨されるアプローチは上記の[ペイウォール情報を取得する](#fetch-paywall-designed-with-paywall-builder)セクションで詳しく説明されている `getPaywall` メソッドでペイウォールを取得することです。 :::warning `getPaywall` の使用を推奨する理由 `getPaywallForDefaultAudience` メソッドには以下のような重大な欠点があります: - **後方互換性の問題**: 異なるアプリバージョン(現在と将来)で異なるペイウォールを表示する必要がある場合、現在(レガシー)バージョンをサポートするペイウォールを設計するか、現在(レガシー)バージョンのユーザーがレンダリングされないペイウォールに遭遇する可能性を受け入れる必要があります。 - **ターゲティングの喪失**: すべてのユーザーが **All Users** オーディエンス向けに設計された同じペイウォールを見ることになり、国、マーケティングアトリビューション、独自のカスタム属性などに基づいたパーソナライズされたターゲティングが失われます。 ペイウォールの取得を高速化するためにこれらの欠点を受け入れる場合は、以下のように `getPaywallForDefaultAudience` メソッドを使用してください。そうでない場合は[上記](#fetch-paywall-designed-with-paywall-builder)で説明した `getPaywall` を使用してください。 ::: ```typescript showLineNumbers try { const paywall = await adapty.getPaywallForDefaultAudience({ placementId: 'YOUR_PLACEMENT_ID', locale: 'en', }); // the requested paywall } catch (error) { // handle the error } ``` :::note `getPaywallForDefaultAudience` メソッドは Capacitor SDK バージョン 2.11.2 以降で利用可能です。 ::: | パラメーター | 必須 | 説明 | |---------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **placementId** | 必須 | [プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** | <p>任意</p><p>デフォルト: `en`</p> | <p>[ペイウォールのローカライゼーション](add-remote-config-locale)の識別子。このパラメーターはマイナス(**-**)文字で区切られた1つ以上のサブタグで構成される言語コードを指定します。最初のサブタグは言語、2番目はリージョンを表します。</p><p></p><p>例:`en` は英語、`pt-br` はブラジルポルトガル語を表します。</p><p></p><p>ロケールコードとその推奨使用方法については[ローカライゼーションとロケールコード](capacitor-localizations-and-locale-codes)をご参照ください。</p> | | **params** | 任意 | ペイウォール取得のための追加パラメーター。 | ## アセットをカスタマイズする \{#customize-assets\} ペイウォール内の画像や動画をカスタマイズするには、カスタムアセットを実装します。 ヒーロー画像と動画には `hero_image` と `hero_video` という事前定義されたIDがあります。カスタムアセットバンドルでは、これらの要素をIDで指定して動作をカスタマイズします。 その他の画像や動画については、Adapty ダッシュボードで[カスタムIDを設定](custom-media)する必要があります。 例えば、以下のことができます: - 一部のユーザーに異なる画像や動画を表示する。 - リモートのメイン画像が読み込まれている間にローカルのプレビュー画像を表示する。 - 動画を再生する前にプレビュー画像を表示する。 :::important この機能を使用するには、Adapty Capacitor SDK をバージョン 3.8.0 以上にアップデートしてください。 ::: シンプルな辞書を使ってカスタムアセットを提供する例を示します: ```typescript showLineNumbers const customAssets: Record<string, AdaptyCustomAsset> = { 'custom_image': { type: 'image', relativeAssetPath: 'custom_image.png' }, 'hero_video': { type: 'video', fileLocation: { ios: { fileName: 'custom_video.mp4' }, android: { relativeAssetPath: 'videos/custom_video.mp4' } } } }; view = await createPaywallView(paywall, { customAssets }); ``` :::note アセットが見つからない場合、ペイウォールはデフォルトの外観にフォールバックします。 ::: --- # File: capacitor-present-paywalls --- --- title: "Capacitor SDKでペイウォールビルダーのペイウォールを表示する" description: "Adaptyを使用してCapacitorアプリにペイウォールを表示します。" --- ペイウォールビルダーを使ってペイウォールをカスタマイズした場合、モバイルアプリのコードでレンダリングを行う必要はありません。ペイウォールビルダーのペイウォールには、表示内容と表示方法の両方が含まれているためです。 :::warning このガイドは**ペイウォールビルダーのペイウォール**専用です。リモートコンフィグのペイウォールを表示する場合は、手順が異なります。**リモートコンフィグのペイウォール**の表示については、[リモートコンフィグで設計されたペイウォールのレンダリング](present-remote-config-paywalls)を参照してください。 ::: ペイウォールを表示するには、[`createPaywallView`](capacitor-get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder)メソッドで作成した`view`に対して`view.present()`メソッドを呼び出します。各`view`は一度しか使用できません。ペイウォールを再度表示する必要がある場合は、`createPaywallView`を再度呼び出して新しい`view`インスタンスを作成してください。 :::warning `view`を再作成せずに再利用すると、エラーが発生する場合があります。 ::: ```typescript showLineNumbers const view = await createPaywallView(paywall); view.setEventHandlers({ onUrlPress(url) { window.open(url, '_blank'); return false; }, }); try { await view.present(); } catch (error) { // handle the error } ``` ## デベロッパー定義タイマーの使用 \{#use-developer-defined-timer\} モバイルアプリでデベロッパー定義タイマーを使用するには、`timerId`を指定します。この例では`CUSTOM_TIMER_NY`が、Adaptyダッシュボードで設定したデベロッパー定義タイマーの**Timer ID**です。これにより、アプリは`13d 09h 03m 34s`のような正しい値(タイマーの終了時刻(例:元日)から現在時刻を引いた値)でタイマーを動的に更新できます。 ```typescript showLineNumbers const customTimers = { 'CUSTOM_TIMER_NY': new Date(2025, 0, 1) }; const view = await createPaywallView(paywall, { customTimers }); ``` この例では、`CUSTOM_TIMER_NY`はAdaptyダッシュボードで設定したデベロッパー定義タイマーの**Timer ID**です。タイマーにより、アプリは`13d 09h 03m 34s`のような正しい値(タイマーの終了時刻(例:元日)から現在時刻を引いた値)でタイマーを動的に更新します。 ## ダイアログの表示 \{#show-dialog\} Androidでペイウォールビューが表示されている場合は、ネイティブのアラートダイアログの代わりにこのメソッドを使用してください。Androidでは通常のアラートがペイウォールビューの背後に表示されるため、ユーザーには見えません。このメソッドを使用することで、すべてのプラットフォームでペイウォールの上に適切にダイアログが表示されます。 ```typescript showLineNumbers title="Capacitor" try { const action = await view.showDialog({ title: 'Close paywall?', content: 'You will lose access to exclusive offers.', primaryActionTitle: 'Stay', secondaryActionTitle: 'Close', }); if (action === 'secondary') { // User confirmed - close the paywall await view.dismiss(); } // If primary - do nothing, user stays } catch (error) { // handle error } ``` ## iOSプレゼンテーションスタイルの設定 \{#configure-ios-presentation-style\} `present()`メソッドに`iosPresentationStyle`パラメーターを渡すことで、iOSでのペイウォールの表示方法を設定できます。パラメーターには`'full_screen'`(デフォルト)または`'page_sheet'`を指定できます。 ```typescript showLineNumbers await view.present({ iosPresentationStyle: 'page_sheet' }); ``` --- # File: capacitor-handle-paywall-actions --- --- title: "Capacitor SDKでボタンアクションに応答する" description: "CapacitorでAdaptyを使用してペイウォールのボタンアクションを処理し、アプリの収益化を改善します。" --- Adaptyのペイウォールビルダーを使ってペイウォールを構築する場合、ボタンを正しく設定することが重要です: 1. [ペイウォールビルダーにボタンを追加し](paywall-buttons)、既存のアクションを割り当てるか、カスタムアクションIDを作成します。 2. 割り当てた各アクションを処理するコードをアプリに記述します。 このガイドでは、コード内でカスタムアクションや既存のアクションを処理する方法を説明します。 ## ペイウォールを閉じる \{#close-paywalls\} ペイウォールを閉じるボタンを追加するには: 1. ペイウォールビルダーでボタンを追加し、**Close** アクションを割り当てます。 2. アプリのコードに、ペイウォールを閉じる `close` アクションのハンドラーを実装します。 :::info Capacitor SDKでは、`close` アクションはデフォルトでペイウォールを閉じる動作をトリガーします。ただし、必要に応じてコードでこの動作をオーバーライドできます。たとえば、あるペイウォールを閉じたときに別のペイウォールを開くようにすることもできます。 ::: ```typescript showLineNumbers const view = await createPaywallView(paywall); const unsubscribe = view.setEventHandlers({ onCloseButtonPress() { console.log('User closed paywall'); return true; // Allow the paywall to close } }); ``` ## ペイウォールからURLを開く \{#open-urls-from-paywalls\} :::tip リンクのグループ(利用規約や購入の復元など)を追加したい場合は、ペイウォールビルダーで **Link** 要素を追加し、**Open URL** アクションが割り当てられたボタンと同じ方法で処理してください。 ::: ペイウォールからリンクを開くボタン(**Terms of use** や **Privacy policy** など)を追加するには: 1. ペイウォールビルダーでボタンを追加し、**Open URL** アクションを割り当てて、開きたいURLを入力します。 2. アプリのコードに、受け取ったURLをブラウザで開く `openUrl` アクションのハンドラーを実装します。 :::info Capacitor SDKでは、`window.open` アクションはデフォルトでURLを開く動作をトリガーします。ただし、必要に応じてコードでこの動作をオーバーライドできます。 ::: ```typescript showLineNumbers const view = await createPaywallView(paywall); const unsubscribe = view.setEventHandlers({ onUrlPress(url) { window.open(url, '_blank'); return false; // Don't close the paywall }, }); ``` ## アプリにログインする \{#log-into-the-app\} ユーザーをアプリにログインさせるボタンを追加するには: 1. ペイウォールビルダーでボタンを追加し、**Login** アクションを割り当てます。 2. アプリのコードに、ユーザーを識別する `login` アクションのハンドラーを実装します。 ```typescript showLineNumbers const view = await createPaywallView(paywall); const unsubscribe = view.setEventHandlers({ onCustomAction(actionId) { if (actionId === 'login') { // Navigate to login screen console.log('User requested login'); } } }); ``` ## カスタムアクションを処理する \{#handle-custom-actions\} その他のアクションを処理するボタンを追加するには: 1. ペイウォールビルダーでボタンを追加し、**Custom** アクションを割り当てて、IDを設定します。 2. アプリのコードに、作成したアクションIDのハンドラーを実装します。 たとえば、別のサブスクリプションオファーや買い切り購入がある場合、別のペイウォールを表示するボタンを追加できます: ```typescript showLineNumbers const unsubscribe = view.setEventHandlers({ onCustomAction(actionId) { if (actionId === 'openNewPaywall') { // Display another paywall console.log('User requested new paywall'); } }, }); ``` --- # File: capacitor-handling-events --- --- title: "Capacitor - ペイウォールイベントの処理" description: "Adapty の SDK を使って Capacitor でサブスクリプションイベントを処理する方法。" --- :::important このガイドでは、購入・復元・プロダクト選択・ペイウォールレンダリングに関するイベント処理を説明します。ボタン操作(ペイウォールを閉じる、リンクを開くなど)の処理も別途実装する必要があります。詳細は[ボタンアクションの処理に関するガイド](capacitor-handle-paywall-actions)をご覧ください。 ::: [ペイウォールビルダー](adapty-paywall-builder)で設定したペイウォールは、購入と復元を行うために追加のコードは不要です。ただし、アプリが応答できるいくつかのイベントが発生します。これらのイベントには、ボタン操作(閉じるボタン、URL、プロダクト選択など)やペイウォール上での購入関連アクションの通知が含まれます。以下でこれらのイベントへの対応方法を説明します。 モバイルアプリ内のペイウォール画面で発生するプロセスを制御・監視するには、`view.setEventHandlers` メソッドを実装してください。 ```typescript showLineNumbers const view = await createPaywallView(paywall); const unsubscribe = view.setEventHandlers({ onCloseButtonPress() { console.log('User closed paywall'); return true; // Allow the paywall to close }, onAndroidSystemBack() { console.log('User pressed back button'); return true; // Allow the paywall to close }, onAppeared() { console.log('Paywall appeared'); return false; // Don't close the paywall }, onDisappeared() { console.log('Paywall disappeared'); }, onPurchaseCompleted(purchaseResult, product) { console.log('Purchase completed:', purchaseResult); return purchaseResult.type !== 'user_cancelled'; // Close if not cancelled }, onPurchaseStarted(product) { console.log('Purchase started:', product); return false; // Don't close the paywall }, onPurchaseFailed(error, product) { console.error('Purchase failed:', error); return false; // Don't close the paywall }, onRestoreCompleted(profile) { console.log('Restore completed:', profile); return true; // Close the paywall after successful restore }, onRestoreFailed(error) { console.error('Restore failed:', error); return false; // Don't close the paywall }, onProductSelected(productId) { console.log('Product selected:', productId); return false; // Don't close the paywall }, onRenderingFailed(error) { console.error('Rendering failed:', error); return false; // Don't close the paywall }, onLoadingProductsFailed(error) { console.error('Loading products failed:', error); return false; // Don't close the paywall }, onUrlPress(url) { window.open(url, '_blank'); return false; // Don't close the paywall }, }); ``` <Details> <summary>イベントの例(クリックして展開)</summary> ```typescript // onCloseButtonPress { "event": "close_button_press" } // onAndroidSystemBack { "event": "android_system_back" } // onAppeared { "event": "paywall_shown" } // onDisappeared { "event": "paywall_closed" } // onUrlPress { "event": "url_press", "url": "https://example.com/terms" } // onCustomAction { "event": "custom_action", "actionId": "login" } // onProductSelected { "event": "product_selected", "productId": "premium_monthly" } // onPurchaseStarted { "event": "purchase_started", "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" } } // onPurchaseCompleted - Success { "event": "purchase_completed", "purchaseResult": { "type": "success", "profile": { "accessLevels": { "premium": { "id": "premium", "isActive": true, "expiresAt": "2024-02-15T10:30:00Z" } } } }, "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" } } // onPurchaseCompleted - Cancelled { "event": "purchase_completed", "purchaseResult": { "type": "user_cancelled" }, "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" } } // onPurchaseFailed { "event": "purchase_failed", "error": { "code": "purchase_failed", "message": "Purchase failed due to insufficient funds", "details": { "underlyingError": "Insufficient funds in account" } } } // onRestoreCompleted { "event": "restore_completed", "profile": { "accessLevels": { "premium": { "id": "premium", "isActive": true, "expiresAt": "2024-02-15T10:30:00Z" } }, "subscriptions": [ { "vendorProductId": "premium_monthly", "isActive": true, "expiresAt": "2024-02-15T10:30:00Z" } ] } } // onRestoreFailed { "event": "restore_failed", "error": { "code": "restore_failed", "message": "Purchase restoration failed", "details": { "underlyingError": "No previous purchases found" } } } // onRenderingFailed { "event": "rendering_failed", "error": { "code": "rendering_failed", "message": "Failed to render paywall interface", "details": { "underlyingError": "Invalid paywall configuration" } } } // onLoadingProductsFailed { "event": "loading_products_failed", "error": { "code": "products_loading_failed", "message": "Failed to load products from the server", "details": { "underlyingError": "Network timeout" } } } ``` </Details> 必要なイベントハンドラーだけを登録し、不要なものは省略できます。省略した場合、そのイベントリスナーは作成されません。必須のイベントハンドラーはありません。 イベントハンドラーはブール値を返します。`true` を返すと表示プロセスが完了したとみなされ、ペイウォール画面が閉じられてこのビューのイベントリスナーが削除されます。 一部のイベントハンドラーにはデフォルトの動作があり、必要に応じてオーバーライドできます。 - `onCloseButtonPress`:閉じるボタンが押されたときにペイウォールを閉じます。 - `onAndroidSystemBack`:**戻る**ボタンが押されたときにペイウォールを閉じます。 - `onRestoreCompleted`:復元が成功した後にペイウォールを閉じます。 - `onPurchaseCompleted`:ユーザーがキャンセルした場合を除いてペイウォールを閉じます。 - `onRenderingFailed`:レンダリングに失敗した場合にペイウォールを閉じます。 - `onUrlPress`:URL をシステムブラウザで開き、ペイウォールは開いたままにします。 ### イベントハンドラー \{#event-handlers\} | イベントハンドラー | 説明 | |:----------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **onCustomAction** | ユーザーがカスタムアクションを実行したとき(例:[カスタムボタン](paywall-buttons)をクリックしたとき)に呼び出されます。 | | **onUrlPress** | ユーザーがペイウォール内の URL をクリックしたときに呼び出されます。 | | **onAndroidSystemBack** | ユーザーが Android のシステム**戻る**ボタンをタップしたときに呼び出されます。 | | **onCloseButtonPress** | 閉じるボタンが表示されており、ユーザーがタップしたときに呼び出されます。このハンドラーでペイウォール画面を閉じることを推奨します。 | | **onPurchaseCompleted** | 購入が完了したとき(成功、ユーザーによるキャンセル、または承認待ちの場合)に呼び出されます。購入が成功した場合は更新された `AdaptyProfile` が提供されます。ユーザーのキャンセルや保留中の支払い(保護者の承認が必要な場合など)は `onPurchaseFailed` ではなくこのイベントをトリガーします。 | | **onPurchaseStarted** | ユーザーが「購入」アクションボタンをタップして購入プロセスを開始したときに呼び出されます。 | | **onPurchaseCancelled** | ユーザーが購入プロセスを開始した後、手動で中断(支払いダイアログをキャンセル)したときに呼び出されます。 | | **onPurchaseFailed** | エラーにより購入が失敗したとき(支払い制限、無効なプロダクト、ネットワーク障害、トランザクション検証失敗など)に呼び出されます。ユーザーのキャンセルや保留中の支払いでは呼び出されず、それらは `onPurchaseCompleted` をトリガーします。 | | **onRestoreStarted** | ユーザーが購入の復元プロセスを開始したときに呼び出されます。 | | **onRestoreCompleted** | 購入の復元が成功し、更新された `AdaptyProfile` が提供されたときに呼び出されます。ユーザーが必要な `accessLevel` を持っている場合は画面を閉じることを推奨します。確認方法については[サブスクリプションのステータス](capacitor-listen-subscription-changes)をご覧ください。 | | **onRestoreFailed** | 復元プロセスが失敗し、`AdaptyError` が提供されたときに呼び出されます。 | | **onProductSelected** | ペイウォールビュー内のいずれかのプロダクトが選択されたときに呼び出されます。購入前にユーザーが何を選択しているかを監視できます。 | | **onAppeared** | ペイウォールビューが画面に表示されたときに呼び出されます。iOS では、ユーザーがペイウォール内の[ウェブペイウォールボタン](web-paywall#step-2a-add-a-web-purchase-button)をタップしてアプリ内ブラウザでウェブペイウォールが開いたときにも呼び出されます。 | | **onDisappeared** | ペイウォールビューが画面から消えたときに呼び出されます。iOS では、ペイウォールからアプリ内ブラウザで開いた[ウェブペイウォール](web-paywall#step-2a-add-a-web-purchase-button)が画面から消えたときにも呼び出されます。 | | **onRenderingFailed** | ビューのレンダリング中にエラーが発生し、`AdaptyError` が提供されたときに呼び出されます。このようなエラーは本来発生しないため、遭遇した場合はお知らせください。 | | **onLoadingProductsFailed** | プロダクトの読み込みに失敗し、`AdaptyError` が提供されたときに呼び出されます。ビュー作成時に `prefetchProducts: true` を設定していない場合、AdaptyUI が必要なオブジェクトをサーバーから自動的に取得します。 | --- # File: capacitor-use-fallback-paywalls --- --- title: "Capacitor - フォールバックペイウォールを使用する" description: "ユーザーがオフラインの場合やAdaptyサーバーが利用できない場合の対応方法" --- スムーズなユーザー体験を維持するために、フロー、[ペイウォール](paywalls)、[オンボーディング](onboardings)に[フォールバック](/fallback-paywalls)を設定することが重要です。この対策により、インターネット接続が部分的または完全に失われた場合でも、アプリケーションの機能を維持できます。 * **アプリケーションが Adapty サーバーにアクセスできない場合:** フォールバックのフローまたはペイウォールを表示し、ローカルのオンボーディング設定にアクセスできます。 * **アプリケーションがインターネットにアクセスできない場合:** フォールバックのフローまたはペイウォールを表示できます。オンボーディングはリモートコンテンツを含むため、動作にはインターネット接続が必要です。 :::important このガイドの手順を進める前に、Adapty からフォールバック設定ファイルを[ダウンロード](/local-fallback-paywalls)してください。 ::: ## 設定 \{#configuration\} ### Android 1. フォールバック設定ファイルをアプリケーションに追加します。以下のディレクトリのいずれかを選択してください: * **android/app/src/main/assets/** * **android/app/src/main/res/raw/** 注意:`res/raw` フォルダにはファイル命名規則があります(先頭は英字、大文字不可、アンダースコア以外の特殊文字不可、スペース不可)。 2. `FileLocation` 定数の `android` プロパティを更新します: * ファイルが `assets` ディレクトリにある場合は、そのディレクトリからの相対パスを指定します。 * ファイルが `res/raw` ディレクトリにある場合は、拡張子を除いたファイル名を指定します。 ### iOS 1. フォールバックJSONファイルをプロジェクトバンドルに追加します:XCodeの **File** メニューを開き、**Add Files to "YourProjectName"** を選択します。 2. 設定ファイルの名前を `FileLocation` 定数の `ios` プロパティに指定します。 ## 例 \{#example\} ```typescript showLineNumbers const fileLocation = { ios: { fileName: 'ios_fallback.json' }, android: { //if the file is located in 'android/app/src/main/assets/' relativeAssetPath: 'android_fallback.json' } }; await adapty.setFallback({ fileLocation }); ``` パラメータ: | パラメータ | 説明 | | :------------------- | :------------------------------------------------------- | | **fileLocation** | フォールバック設定ファイルの場所を表すオブジェクト。 | --- # File: capacitor-localizations-and-locale-codes --- --- title: "Capacitor SDKでローカライズとロケールコードを使用する" description: "Adapty SDKを使ってCapacitorアプリのペイウォールをローカライズする方法を学びましょう。" --- ## なぜこれが重要なのか \{#why-this-is-important\} ロケールコードが関係するシナリオはいくつかあります。たとえば、アプリの現在のローカライズに対応した正しいペイウォールを取得しようとする場合などです。 ロケールコードは複雑で、プラットフォームによって異なることがあるため、Adaptyでは対応するすべてのプラットフォームに共通の内部標準を採用しています。ただし、コードが複雑なため、サーバーに何を送信しているか、そして次に何が起こるかを正確に理解しておくことが非常に重要です。そうすることで、常に期待どおりの結果が得られます。 ## AdaptyのロケールコードLSの標準 \{#locale-code-standard-at-adapty\} ロケールコードについて、Adaptyは少し修正した[BCP 47標準](https://en.wikipedia.org/wiki/IETF_language_tag)を使用しています。各コードは小文字のサブタグで構成され、ハイフンで区切られます。例:`en`(英語)、`pt-br`(ポルトガル語(ブラジル))、`zh`(簡体字中国語)、`zh-hant`(繁体字中国語)。 ## ロケールコードのマッチング \{#locale-code-matching\} Adaptyがクライアント側SDKからロケールコードの呼び出しを受け取り、ペイウォールの対応するローカライズを検索するとき、以下のことが起こります: 1. 受信したロケール文字列が小文字に変換され、アンダースコア(`_`)がすべてハイフン(`-`)に置換されます 2. 完全に一致するロケールコードのローカライズを検索します 3. 一致するものが見つからなかった場合、最初のハイフンの前の部分文字列(`pt-br`の場合は`pt`)を取得し、一致するローカライズを検索します 4. それでも一致するものが見つからなかった場合、デフォルトの`en`ローカライズを返します これにより、`'pt_BR'`を送信したiOSデバイス、`pt-BR`を送信したAndroidデバイス、`pt-br`を送信した別のデバイスはすべて同じ結果を得られます。 ## ローカライズの実装:推奨する方法 \{#implementing-localizations-recommended-way\} ローカライズについて検討しているなら、すでにプロジェクト内のローカライズ済み文字列ファイルを扱っている可能性があります。その場合は、各ローカライズに対応するAdaptyのロケールコードをキーと値のペアとしてファイルに記述することをおすすめします。そして、SDKを呼び出す際にそのキーの値を取り出して使用します: ```javascript showLineNumbers // 1. Modify your localization files (e.g., using react-i18next) /* en.json */ { "adapty_paywalls_locale": "en" } /* es.json */ { "adapty_paywalls_locale": "es" } /* pt-BR.json */ { "adapty_paywalls_locale": "pt-br" } // 2. Extract and use the locale code const MyComponent = () => { const { t } = useTranslation(); const fetchPaywall = async () => { const locale = t('adapty_paywalls_locale'); // pass locale code to adapty.getPaywall or adapty.getPaywallForDefaultAudience method const paywall = await adapty.getPaywallForDefaultAudience('placement_id', locale); }; }; ``` これにより、アプリのすべてのユーザーに対してどのローカライズが取得されるかを完全にコントロールできます。 ## ローカライズの実装:別の方法 \{#implementing-localizations-the-other-way\} すべてのローカライズに対してロケールコードを明示的に定義しなくても、同様の(ただし完全に同一ではない)結果を得ることができます。それはプラットフォームが提供する別のオブジェクトからロケールコードを取り出すことを意味します: ```javascript showLineNumbers const getLocaleCode = () => { if (Capacitor.getPlatform() === 'ios') { return navigator.language || 'en'; } else { return navigator.language || 'en'; } }; const fetchPaywall = async () => { const locale = getLocaleCode(); // pass locale code to adapty.getPaywall or adapty.getPaywallForDefaultAudience method const paywall = await adapty.getPaywallForDefaultAudience('placement_id', locale); }; ``` この方法はいくつかの理由からおすすめしません: 1. iOSでは、優先言語と現在のロケールは同一ではありません。ローカライズが正しく選択されるようにするには、Appleのロジックに任せるか(推奨するローカライズ済み文字列ファイルを使用するアプローチであれば自動的に機能します)、それを自分で再現する必要があります。 2. Adaptyのサーバーが実際に何を受け取るか予測しにくいです。たとえば、iOSでは`ar_OM@numbers='latn'`のようなロケールをデバイスから取得してサーバーに送信することがあります。この場合、期待していた`ar-om`ローカライズではなく`ar`が返ってきます。これはおそらく意図しない結果です。 それでもこのアプローチを使用する場合は、関連するすべてのユースケースをカバーしていることを確認してください。 --- # File: capacitor-web-paywall --- --- title: "ウェブペイウォールの実装" description: "Adapty SDK を使用して Capacitor アプリにウェブペイウォールを実装する方法を説明します。" --- :::important 始める前に、[ダッシュボードでウェブペイウォールを設定](web-paywall)し、Adapty SDK バージョン 3.6.1 以降をインストールしていることを確認してください。 ::: ## ウェブペイウォールを開く \{#open-web-paywalls\} 自分で開発したペイウォールを使用している場合は、SDK メソッドを使ってウェブペイウォールを処理する必要があります。`.openWebPaywall` メソッドは以下を行います: 1. 特定のユーザーに表示されたペイウォールを、そのユーザーがリダイレクトされるウェブページに Adapty が紐付けるための一意の URL を生成します。 2. ユーザーがアプリに戻ったタイミングを検知し、プロファイルのアクセス権が更新されたかどうかを確認するために、短い間隔で `.getProfile` をリクエストします。 これにより、支払いが成功してアクセス権が更新されると、アプリ内でほぼ即座にサブスクリプションが有効になります。 ```typescript showLineNumbers try { await adapty.openWebPaywall({ paywallOrProduct: product }); } catch (error) { console.error('Failed to open web paywall:', error); } ``` :::note `openWebPaywall` メソッドには 2 つのバージョンがあります: 1. `openWebPaywall({ paywallOrProduct: product })` — ペイウォールに基づいて URL を生成し、プロダクトデータも URL に追加します。 2. `openWebPaywall({ paywallOrProduct: paywall })` — ペイウォールに基づいて URL を生成しますが、プロダクトデータは URL に追加しません。Adapty のペイウォールに設定されているプロダクトとウェブペイウォールのプロダクトが異なる場合に使用してください。 ::: #### エラー処理 \{#handle-errors\} | エラー | 説明 | 推奨対応 | |-----------------------------------------|--------------------------------------------------------|---------------------------------------------------------------------------| | AdaptyError.paywallWithoutPurchaseUrl | ペイウォールにウェブ購入 URL が設定されていません | Adapty ダッシュボードでペイウォールが正しく設定されているか確認してください | | AdaptyError.productWithoutPurchaseUrl | プロダクトにウェブ購入 URL が設定されていません | Adapty ダッシュボードでプロダクトの設定を確認してください | | AdaptyError.failedOpeningWebPaywallUrl | ブラウザで URL を開くことができませんでした | デバイスの設定を確認するか、代替の購入方法を提供してください | | AdaptyError.failedDecodingWebPaywallUrl | URL のパラメータのエンコードに失敗しました | URL パラメータが有効で正しい形式になっているか確認してください | ## アプリ内ブラウザでウェブペイウォールを開く \{#open-web-paywalls-in-an-in-app-browser\} :::important アプリ内ブラウザでのウェブペイウォールの表示は、Adapty SDK v3.15 以降でサポートされています。 ::: デフォルトでは、ウェブペイウォールは外部ブラウザで開きます。 シームレスなユーザー体験を提供するために、アプリ内ブラウザでウェブペイウォールを開くことができます。これにより、アプリを切り替えることなく、アプリ内でウェブ購入ページを表示してトランザクションを完了できます。 これを有効にするには、`openWebPaywall` の `openIn` に `WebPresentation.BrowserInApp` を設定します: ```typescript showLineNumbers try { await adapty.openWebPaywall({ paywallOrProduct: product, openIn: WebPresentation.BrowserInApp, // default – WebPresentation.BrowserOutApp }); } catch (error) { console.error('Failed to open web paywall:', error); } ``` --- # File: capacitor-implement-paywalls-manually --- --- title: "Implement paywalls manually" description: "Learn how to implement paywalls manually in your Capacitor app with Adapty SDK." --- ## Accept purchases If you are working with paywalls you've implemented yourself, you can delegate handling purchases to Adapty, using the `makePurchase` method. This way, we will handle all the user scenarios, and you will only need to handle the purchase results. :::important `makePurchase` works with products created in the Adapty dashboard. Make sure you configure products and ways to retrieve them in the dashboard by following the [quickstart guide](quickstart). ::: <CustomDocCardList ids={['capacitor-quickstart-manual', 'fetch-paywalls-and-products-capacitor', 'present-remote-config-paywalls-capacitor', 'capacitor-making-purchases', 'capacitor-restore-purchase']} /> ## Observer mode If you want to implement your own purchase handling logic from scratch but still want to benefit from the advanced analytics in Adapty, you can use the observer mode. :::important Consider the observer mode limitations [here](observer-vs-full-mode). ::: <CustomDocCardList ids={['implement-observer-mode-capacitor', 'report-transactions-observer-mode-capacitor']} /> --- # File: capacitor-quickstart-manual --- --- title: "Capacitor SDKのカスタムペイウォールで購入を有効にする" description: "Adapty SDKをCapacitorのカスタムペイウォールに統合して、アプリ内課金を有効にします。" --- このガイドでは、カスタムペイウォールにAdaptyを統合する方法を説明します。Adapty SDKがプロダクトの取得、新規購入の処理、過去の購入の復元を行いながら、ペイウォールの実装を完全にコントロールできます。 :::important **このガイドはカスタムペイウォールを実装する開発者向けです。** 購入を手軽に有効にしたい場合は、[Adapty ペイウォールビルダー](capacitor-quickstart-paywalls)をご利用ください。ペイウォールビルダーを使えば、ノーコードのビジュアルエディターでペイウォールを作成でき、Adaptyがすべての購入ロジックを自動的に処理するため、アプリを再公開することなく異なるデザインをテストできます。 ::: ## 始める前に \{#before-you-start\} ### プロダクトのセットアップ \{#set-up-products\} アプリ内課金を有効にするには、次の3つの主要な概念を理解する必要があります。 - [**プロダクト**](product) – ユーザーが購入できるもの(サブスクリプション、消耗型アイテム、永続アクセス) - [**ペイウォール**](paywalls) – どのプロダクトを提供するかを定義する設定。Adaptyでは、ペイウォールがプロダクトを取得する唯一の手段ですが、この設計によりアプリのコードを変更せずにプロダクト、価格、オファーを変更できます。 - [**プレースメント**](placements) – アプリ内でペイウォールを表示する場所とタイミング(`main`、`onboarding`、`settings`など)。ダッシュボードでプレースメントに対してペイウォールを設定し、コード内ではプレースメントIDで取得します。これにより、A/Bテストの実行や異なるユーザーへの異なるペイウォールの表示が簡単になります。 カスタムペイウォールを使用する場合でも、これらの概念を理解しておいてください。基本的には、アプリで販売するプロダクトを管理する方法です。 カスタムペイウォールを実装するには、**ペイウォール**を作成して**プレースメント**に追加する必要があります。この設定でプロダクトを取得できます。ダッシュボードで必要な作業を理解するには、[こちら](quickstart)のクイックスタートガイドに従ってください。 ### ユーザー管理 \{#manage-users\} バックエンド認証があってもなくても利用できます。 ただし、Adapty SDKは匿名ユーザーと識別済みユーザーを異なる方法で扱います。詳細を理解し、ユーザーを適切に扱うために[識別クイックスタートガイド](capacitor-quickstart-identify)をお読みください。 ## ステップ1. プロダクトを取得する \{#step-1-get-products\} カスタムペイウォール用のプロダクトを取得するには、次の手順に従います。 1. `getPaywall`メソッドに[プレースメント](placements)IDを渡して`paywall`オブジェクトを取得する。 2. `getPaywallProducts`メソッドを使って、このペイウォールのプロダクト配列を取得する。 ```typescript showLineNumbers async function loadPaywall() { try { const paywall: AdaptyPaywall = await adapty.getPaywall({ placementId: 'YOUR_PLACEMENT_ID' }); const products: AdaptyPaywallProduct[] = await adapty.getPaywallProducts({ paywall }); // Use products to build your custom paywall UI } catch (error) { // Handle the error } } ``` ## ステップ2. 購入を受け付ける \{#step-2-accept-purchases\} ユーザーがカスタムペイウォールのプロダクトをタップしたら、選択したプロダクトを指定して`makePurchase`メソッドを呼び出します。これにより購入フローが処理され、更新されたプロファイルが返されます。 ```typescript showLineNumbers async function purchaseProduct(product: AdaptyPaywallProduct) { try { const result: AdaptyPurchaseResult = await adapty.makePurchase({ product }); if (result.type === 'success') { // Purchase successful, profile updated } else if (result.type === 'user_cancelled') { // User canceled the purchase } else if (result.type === 'pending') { // Purchase is pending (e.g., user will pay offline with cash) } } catch (error) { // Handle the error } } ``` ## ステップ3. 購入を復元する \{#step-3-restore-purchases\} アプリストアでは、サブスクリプションを提供するすべてのアプリに対して、ユーザーが購入を復元できる手段を提供することを求めています。 ユーザーが復元ボタンをタップしたら`restorePurchases`メソッドを呼び出します。これにより購入履歴がAdaptyと同期され、更新されたプロファイルが返されます。 ```typescript showLineNumbers async function restorePurchases() { try { const profile: AdaptyProfile = await adapty.restorePurchases(); // Restore successful, profile updated } catch (error) { // Handle the error } } ``` ## 次のステップ \{#next-steps\} --- no_index: true --- import Callout from '../../../components/Callout.astro'; <Callout type="tip"> ご質問やお困りのことがあれば、[サポートフォーラム](https://adapty.featurebase.app/)をご覧ください。よくある質問への回答を見つけたり、ご自身の質問を投稿することができます。チームとコミュニティがサポートいたします! </Callout> ペイウォールをアプリに表示する準備ができました。[App Storeサンドボックス](test-purchases-in-sandbox)または[Google Play Store](testing-on-android)でテスト購入を完了できるか確認してください。本番環境に近い実装例については、サンプルアプリの[App.tsx](https://github.com/adaptyteam/AdaptySDK-Capacitor/blob/master/examples/adapty-devtools/src/screens/app/App.tsx)を参照してください。適切なエラーハンドリング、ローディング状態、包括的なSDK統合を含む購入処理の実装例を確認できます。 次に、[ユーザーが購入を完了したかどうかを確認](capacitor-check-subscription-status)して、ペイウォールを表示するか有料機能へのアクセスを許可するかを判断します。 --- # File: fetch-paywalls-and-products-capacitor --- --- title: "Capacitor SDKでリモートコンフィグペイウォールのペイウォールとプロダクトを取得する" description: "Adapty Capacitor SDKでペイウォールとプロダクトを取得し、ユーザーの収益化を向上させましょう。" --- リモートコンフィグやカスタムペイウォールを表示する前に、それらに関する情報を取得する必要があります。このトピックはリモートコンフィグおよびカスタムペイウォールに関するものです。ペイウォールビルダーでカスタマイズしたペイウォールの取得方法については、[ペイウォールビルダーのペイウォールとその設定を取得する](capacitor-get-pb-paywalls)を参照してください。 :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: <details> <summary>モバイルアプリでペイウォールとプロダクトの取得を始める前に(クリックして展開)</summary> 1. Adapty ダッシュボードで[プロダクトを作成する](create-product)。 2. Adapty ダッシュボードで[ペイウォールを作成し、プロダクトをペイウォールに組み込む](create-paywall)。 3. Adapty ダッシュボードで[プレースメントを作成し、ペイウォールをプレースメントに組み込む](create-placement)。 4. モバイルアプリに[Adapty SDKをインストールする](sdk-installation-capacitor)。 </details> ## ペイウォール情報を取得する \{#fetch-paywall-information\} Adaptyでは、[プロダクト](product)はApp StoreとGoogle Playの両方のプロダクトを組み合わせたものです。これらのクロスプラットフォームプロダクトはペイウォールに統合され、特定のモバイルアプリのプレースメント内で表示できるようになります。 プロダクトを表示するには、`getPaywall`メソッドを使って、いずれかの[プレースメント](placements)から[ペイウォール](paywalls)を取得する必要があります。 ```typescript showLineNumbers try { const paywall = await adapty.getPaywall({ placementId: 'YOUR_PLACEMENT_ID', locale: 'en', params: { fetchPolicy: 'reload_revalidating_cache_data', // Load from server, fallback to cache loadTimeoutMs: 5000 // 5 second timeout } }); // the requested paywall } catch (error) { console.error('Failed to fetch paywall:', error); } ``` | パラメータ | 必須 | 説明 | |---------|--------|-----------| | **placementId** | 必須 | [プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** | <p>任意</p><p>デフォルト: `en`</p> | <p>[ペイウォールのローカライゼーション](add-remote-config-locale)の識別子。このパラメータはマイナス(**-**)文字で区切られた1つ以上のサブタグで構成される言語コードです。最初のサブタグは言語、2番目は地域を表します。</p><p></p><p>例:`en`は英語、`pt-br`はブラジルポルトガル語を表します。</p><p></p><p>ロケールコードの詳細と推奨される使い方については、[ローカライゼーションとロケールコード](capacitor-localizations-and-locale-codes)を参照してください。</p> | | **params.fetchPolicy** | <p>任意</p><p>デフォルト: `'reload_revalidating_cache_data'`</p> | <p>デフォルトでは、SDKはサーバーからデータを読み込もうとし、失敗した場合はキャッシュデータを返します。ユーザーが常に最新のデータを取得できるため、この方法を推奨します。</p><p></p><p>ただし、ユーザーが不安定なインターネット環境を使用していると考える場合は、`'return_cache_data_else_load'`を使用して、キャッシュが存在する場合はキャッシュデータを返すようにすることを検討してください。この場合、ユーザーは最新のデータを得られない可能性がありますが、接続が不安定でも高速な読み込みを体験できます。キャッシュは定期的に更新されるため、ネットワークリクエストを避けるためにセッション中に使用しても安全です。</p><p></p><p>なお、キャッシュはアプリの再起動後も保持され、アプリの再インストールまたは手動でのクリーンアップ時にのみ削除されます。</p> | | **params.loadTimeoutMs** | <p>任意</p><p>デフォルト: 5000 ms</p> | <p>このメソッドのタイムアウト(ミリ秒)を制限します。タイムアウトに達した場合、キャッシュデータまたはローカルフォールバックが返されます。</p><p></p><p>まれに、`loadTimeoutMs`で指定した時間よりもわずかに遅くタイムアウトする場合があります。これは、この操作が内部で複数のリクエストで構成されている場合があるためです。</p> | **プロダクトIDをハードコードしないでください。** ハードコードすべき唯一のIDはプレースメントIDです。ペイウォールはリモートで設定されるため、プロダクトの数や利用可能なオファーはいつでも変わる可能性があります。アプリはこれらの変更を動的に処理する必要があります。今日ペイウォールが2つのプロダクトを返し、明日3つ返す場合でも、コードを変更せずにすべてを表示できるようにしてください。 レスポンスパラメータ: | パラメータ | 説明 | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- | | Paywall | プロダクトIDのリスト、ペイウォール識別子、リモートコンフィグ、その他いくつかのプロパティを含む[`AdaptyPaywall`](https://capacitor.adapty.io/interfaces/adaptypaywall)オブジェクト。 | ## プロダクトを取得する \{#fetch-products\} ペイウォールを取得したら、それに対応するプロダクト配列を取得できます: ```typescript showLineNumbers try { const products = await adapty.getPaywallProducts({ paywall }); // the requested products list } catch (error) { console.error('Failed to fetch products:', error); } ``` レスポンスパラメータ: | パラメータ | 説明 | | :-------- |:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Products | プロダクト識別子、プロダクト名、価格、通貨、サブスクリプション期間、その他いくつかのプロパティを含む[`AdaptyPaywallProduct`](https://capacitor.adapty.io/interfaces/adaptypaywallproduct)オブジェクトのリスト。 | 独自のペイウォールデザインを実装する際、[`AdaptyPaywallProduct`](https://capacitor.adapty.io/interfaces/adaptypaywallproduct)オブジェクトのこれらのプロパティにアクセスする必要があるでしょう。以下に最もよく使われるプロパティを示しますが、利用可能なすべてのプロパティの詳細については、リンク先のドキュメントを参照してください。 | プロパティ | 説明 | |-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **タイトル** | プロダクトのタイトルを表示するには、`product.localizedTitle`を使用します。ローカライゼーションはデバイスのロケールではなく、ユーザーが選択しているストアの国に基づいています。 | | **価格** | 価格のローカライズされた表示には、`product.price?.localizedString`を使用します。このローカライゼーションはデバイスのロケール情報に基づいています。`product.price?.amount`を使って数値として価格にアクセスすることもできます。値はローカル通貨で提供されます。関連する通貨記号を取得するには、`product.price?.currencySymbol`を使用します。 | | **サブスクリプション期間** | 期間(週、月、年など)を表示するには、`product.subscription?.localizedSubscriptionPeriod`を使用します。このローカライゼーションはデバイスのロケールに基づいています。プログラムでサブスクリプション期間を取得するには、`product.subscription?.subscriptionPeriod`を使用します。そこから`unit`プロパティにアクセスして期間の長さ('day'、'week'、'month'、'year'、'unknown'のいずれか)を取得できます。`numberOfUnits`の値で期間単位の数を取得できます。例えば、四半期サブスクリプションの場合、unitプロパティには`'month'`、numberOfUnitsには`3`が入ります。 | | **初回オファー** | サブスクリプションに初回オファーが含まれているかどうかを示すバッジなどのインジケーターを表示するには、`product.subscription?.offer?.phases`プロパティを確認してください。これは最大2つの割引フェーズ(無料トライアルフェーズと初回価格フェーズ)を含むリストです。各フェーズオブジェクトには以下の便利なプロパティがあります:<br/>• `paymentMode`:`'free_trial'`、`'pay_as_you_go'`、`'pay_up_front'`、`'unknown'`の値を持つ文字列。無料トライアルは`'free_trial'`タイプになります。<br/>• `price`:数値としての割引価格。無料トライアルの場合は`0`を確認してください。<br/>• `localizedNumberOfPeriods`:デバイスのロケールを使ってローカライズされた、オファーの長さを示す文字列。例えば、3日間のトライアルオファーの場合、このフィールドには`'3 days'`が表示されます。<br/>• `subscriptionPeriod`:代替として、このプロパティを使ってオファー期間の個別の詳細を取得できます。前のセクションで説明した方法と同様に機能します。<br/>• `localizedSubscriptionPeriod`:ユーザーのロケールに合わせてフォーマットされた割引のサブスクリプション期間。 | ## デフォルトオーディエンスのペイウォールでペイウォール取得を高速化する \{#speed-up-paywall-fetching-with-default-audience-paywall\} 通常、ペイウォールはほぼ瞬時に取得されるため、このプロセスの高速化を心配する必要はありません。ただし、オーディエンスとペイウォールが多数あり、ユーザーのインターネット接続が弱い場合、ペイウォールの取得に時間がかかることがあります。そのような状況では、ペイウォールをまったく表示しないよりも、デフォルトのペイウォールを表示してスムーズなユーザー体験を確保したい場合があります。 これに対処するために、`getPaywallForDefaultAudience`メソッドを使用できます。このメソッドは、指定したプレースメントの**All Users**オーディエンス向けペイウォールを取得します。ただし、上記の[ペイウォール情報を取得する](fetch-paywalls-and-products-capacitor#fetch-paywall-information)セクションで説明した`getPaywall`メソッドでペイウォールを取得する方法が推奨アプローチであることを理解しておくことが重要です。 :::warning `getPaywall`を推奨する理由 `getPaywallForDefaultAudience`メソッドにはいくつかの重大な欠点があります: - **後方互換性の問題の可能性**:現在のバージョンと将来のバージョンで異なるペイウォールを表示する必要がある場合、課題が生じる可能性があります。現在の(レガシー)バージョンをサポートするペイウォールを設計するか、現在の(レガシー)バージョンのユーザーがレンダリングされないペイウォールに遭遇する可能性を受け入れるかのどちらかになります。 - **ターゲティングの喪失**:すべてのユーザーが**All Users**オーディエンス向けに設計された同じペイウォールを見ることになるため、パーソナライズされたターゲティング(国、マーケティングアトリビューション、独自のカスタム属性に基づくものを含む)が失われます。 これらの欠点を受け入れてでもペイウォール取得の高速化のメリットを享受したい場合は、以下のように`getPaywallForDefaultAudience`メソッドを使用してください。そうでない場合は、[上記](fetch-paywalls-and-products-capacitor#fetch-paywall-information)で説明した`getPaywall`を使用し続けてください。 ::: ```typescript showLineNumbers try { const paywall = await adapty.getPaywallForDefaultAudience({ placementId: 'YOUR_PLACEMENT_ID', locale: 'en', params: { fetchPolicy: 'reload_revalidating_cache_data' // Load from server, fallback to cache } }); // the requested paywall } catch (error) { console.error('Failed to fetch default audience paywall:', error); } ``` :::note `getPaywallForDefaultAudience`メソッドはCapacitor SDKバージョン2.11.2以降で利用可能です。 ::: | パラメータ | 必須 | 説明 | |---------|--------|-----------| | **placementId** | 必須 | [プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** | <p>任意</p><p>デフォルト: `en`</p> | <p>[ペイウォールのローカライゼーション](add-remote-config-locale)の識別子。このパラメータはマイナス(**-**)文字で区切られた1つ以上のサブタグで構成される言語コードです。最初のサブタグは言語、2番目は地域を表します。</p><p></p><p>例:`en`は英語、`pt-br`はブラジルポルトガル語を表します。</p><p></p><p>ロケールコードの詳細と推奨される使い方については、[ローカライゼーションとロケールコード](capacitor-localizations-and-locale-codes)を参照してください。</p> | | **params.fetchPolicy** | <p>任意</p><p>デフォルト: `'reload_revalidating_cache_data'`</p> | <p>デフォルトでは、SDKはサーバーからデータを読み込もうとし、失敗した場合はキャッシュデータを返します。ユーザーが常に最新のデータを取得できるため、この方法を推奨します。</p><p></p><p>ただし、ユーザーが不安定なインターネット環境を使用していると考える場合は、`'return_cache_data_else_load'`を使用して、キャッシュが存在する場合はキャッシュデータを返すようにすることを検討してください。この場合、ユーザーは最新のデータを得られない可能性がありますが、接続が不安定でも高速な読み込みを体験できます。キャッシュは定期的に更新されるため、ネットワークリクエストを避けるためにセッション中に使用しても安全です。</p><p></p><p>なお、キャッシュはアプリの再起動後も保持され、アプリの再インストールまたは手動でのクリーンアップ時にのみ削除されます。</p> | --- # File: present-remote-config-paywalls-capacitor --- --- title: "Capacitor SDKでリモートコンフィグによるペイウォールをレンダリングする" description: "Adapty Capacitor SDKでリモートコンフィグペイウォールを表示し、ユーザー体験をパーソナライズする方法を解説します。" --- リモートコンフィグを使ってペイウォールをカスタマイズした場合、ユーザーに表示するためのレンダリングをアプリのコードに実装する必要があります。リモートコンフィグはニーズに合わせた柔軟な設定が可能なため、ペイウォールの内容と見た目はすべて自分でコントロールできます。リモート設定を取得するメソッドを用意しているので、リモートコンフィグで設定したカスタムペイウォールを自由に表示できます。 ## ペイウォールのリモートコンフィグを取得して表示する \{#get-paywall-remote-config-and-present-it\} ペイウォールのリモートコンフィグを取得するには、`remoteConfig` プロパティにアクセスして必要な値を抽出します。 ```typescript showLineNumbers try { const paywall = await adapty.getPaywall({ placementId: 'YOUR_PLACEMENT_ID', params: { fetchPolicy: 'reload_revalidating_cache_data', // Load from server, fallback to cache loadTimeoutMs: 5000 // 5 second timeout } }); const headerText = paywall.remoteConfig?.data?.['header_text']; } catch (error) { console.error('Failed to fetch paywall:', error); } ``` 必要な値をすべて取得したら、それらをまとめて見栄えのよいページとしてレンダリングします。さまざまな画面サイズや向きに対応したデザインにすることで、どのデバイスでも快適に使えるユーザー体験を提供しましょう。 :::warning Adapty アナリティクスがファネルや A/B テストの情報を正しく収集できるよう、必ず以下の手順で[ペイウォール表示イベントを記録](present-remote-config-paywalls-capacitor#track-paywall-view-events)してください。 ::: ペイウォールの表示が完了したら、購入フローの設定に進みます。ユーザーが購入する際は、ペイウォールのプロダクトを使って `.makePurchase()` を呼び出すだけです。`.makePurchase()` メソッドの詳細は[購入の実行](capacitor-making-purchases)をご覧ください。 インターネット接続がない場合やキャッシュが利用できない場合でもスムーズな体験を提供できるよう、[フォールバックペイウォールの作成](capacitor-use-fallback-paywalls)をおすすめします。 ## ペイウォール表示イベントを記録する \{#track-paywall-view-events\} Adapty はペイウォールのパフォーマンス測定をサポートしています。購入データは自動的に収集されますが、ペイウォールの表示ログはユーザーがいつペイウォールを見たかを把握しているのは開発者だけなので、手動で記録する必要があります。 ペイウォール表示イベントをログに記録するには、`.logShowPaywall(paywall)` を呼び出すだけです。ファネルや A/B テストのペイウォール指標に反映されます。 :::important [ペイウォールビルダー](adapty-paywall-builder)で作成したペイウォールを表示している場合は、`.logShowPaywall(paywall)` を呼び出す必要はありません。 ::: ```typescript showLineNumbers try { await adapty.logShowPaywall({ paywall }); } catch (error) { console.error('Failed to log paywall view:', error); } ``` リクエストパラメーター: | パラメーター | 必須 | 説明 | | :---------- | :------- | :--------------------------------------------------------- | | **paywall** | 必須 | [`AdaptyPaywall`](https://capacitor.adapty.io/interfaces/adaptypaywall) オブジェクト。 | --- # File: capacitor-making-purchases --- --- title: "Capacitor SDKでモバイルアプリ内で購入する" description: "Adaptyを使用してアプリ内課金とサブスクリプションを処理するためのガイド。" --- モバイルアプリ内でペイウォールを表示することは、ユーザーにプレミアムコンテンツやサービスへのアクセスを提供するために不可欠なステップです。ただし、[ペイウォールビルダー](adapty-paywall-builder)を使用してペイウォールをカスタマイズしている場合に限り、ペイウォールを表示するだけで購入をサポートできます。 ペイウォールビルダーを使用していない場合は、購入を完了してコンテンツをアンロックするために、`.makePurchase()` という別のメソッドを使用する必要があります。このメソッドは、ユーザーがペイウォールを操作して希望する取引を進めるためのゲートウェイとして機能します。 ペイウォールに、ユーザーが購入しようとしているプロダクトに対してアクティブなプロモーションオファーがある場合、Adaptyは購入時に自動的にそれを適用します。 [初期設定](quickstart)をすべてのステップをスキップせずに完了していることを確認してください。それがないと、購入を検証できません。 ## 購入する \{#make-purchase\} :::note **[ペイウォールビルダー](adapty-paywall-builder)を使用していますか?** 購入は自動的に処理されるため、このステップはスキップできます。 **ステップバイステップのガイダンスをお探しですか?** 全体的なコンテキストを含むエンドツーエンドの実装手順については、[クイックスタートガイド](capacitor-implement-paywalls-manually)を確認してください。 ::: ```typescript showLineNumbers try { const result = await adapty.makePurchase({ product }); if (result.type === 'success') { const isSubscribed = result.profile?.accessLevels['YOUR_ACCESS_LEVEL']?.isActive; if (isSubscribed) { // Grant access to the paid features console.log('User is now subscribed!'); } } else if (result.type === 'user_cancelled') { console.log('Purchase cancelled by user'); } else if (result.type === 'pending') { console.log('Purchase is pending'); } } catch (error) { console.error('Purchase failed:', error); } ``` リクエストパラメータ: | パラメータ | 必須/任意 | 説明 | | :---------- | :------- |:----------------------------------------------------------------------------------------------------------------------------| | **product** | 必須 | ペイウォールから取得した [`AdaptyPaywallProduct`](https://capacitor.adapty.io/interfaces/adaptypaywallproduct) オブジェクト。 | レスポンスパラメータ: | パラメータ | 説明 | |---------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **result** | 購入結果を示す `type` フィールド(`'success'`、`'user_cancelled'`、または `'pending'`)と、購入成功時に更新された [`AdaptyProfile`](https://capacitor.adapty.io/interfaces/adaptyprofile) を含む `profile` フィールドを持つ [`AdaptyPurchaseResult`](https://capacitor.adapty.io/types/adaptypurchaseresult) オブジェクト。 | ## 購入時にサブスクリプションを変更する \{#change-subscription-when-making-a-purchase\} ユーザーが現在のサブスクリプションを更新する代わりに新しいサブスクリプションを選択する場合、その動作はアプリストアによって異なります: - App Storeの場合、サブスクリプションはサブスクリプショングループ内で自動的に更新されます。ユーザーがあるグループのサブスクリプションを購入し、すでに別のグループのサブスクリプションを持っている場合、両方のサブスクリプションが同時にアクティブになります。 - Google Playの場合、サブスクリプションは自動的に更新されません。以下で説明するように、モバイルアプリのコードで切り替えを管理する必要があります。 Androidで別のサブスクリプションに切り替えるには、追加パラメータを指定して `.makePurchase()` メソッドを呼び出します: ```typescript showLineNumbers try { const result = await adapty.makePurchase({ product, params: { android: { subscriptionUpdateParams: { oldSubVendorProductId: 'old_product_id', prorationMode: 'charge_prorated_price' }, isOfferPersonalized: true } } }); if (result.type === 'success') { const isSubscribed = result.profile?.accessLevels['YOUR_ACCESS_LEVEL']?.isActive; if (isSubscribed) { // Grant access to the paid features console.log('Subscription updated successfully!'); } } else if (result.type === 'user_cancelled') { console.log('Purchase cancelled by user'); } else if (result.type === 'pending') { console.log('Purchase is pending'); } } catch (error) { console.error('Purchase failed:', error); } ``` 追加リクエストパラメータ: | パラメータ | 必須/任意 | 説明 | | :--------- | :------- | :----------------------------------------------------------- | | **params** | 任意 | プラットフォーム固有の購入パラメータを含む [`MakePurchaseParamsInput`](https://capacitor.adapty.io/types/makepurchaseparamsinput) 型のオブジェクト。 | `MakePurchaseParamsInput` の構造は以下のとおりです: ```typescript { android: { subscriptionUpdateParams: { oldSubVendorProductId: 'old_product_id', prorationMode: 'charge_prorated_price' }, isOfferPersonalized: true } } ``` サブスクリプションと置き換えモードの詳細については、Google Developerのドキュメントを参照してください: - [置き換えモードについて](https://developer.android.com/google/play/billing/subscriptions#replacement-modes) - [置き換えモードに関するGoogleの推奨事項](https://developer.android.com/google/play/billing/subscriptions#replacement-recommendations) - 置き換えモード [`CHARGE_PRORATED_PRICE`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode#CHARGE_PRORATED_PRICE())。注意: このメソッドはサブスクリプションのアップグレードにのみ使用できます。ダウングレードはサポートされていません。 - 置き換えモード [`DEFERRED`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode#DEFERRED())。注意: 実際のサブスクリプション変更は、現在のサブスクリプションの請求期間が終了した時点でのみ発生します。 ### プリペイドプランの管理(Android) \{#manage-prepaid-plans-android\} アプリユーザーが[プリペイドプラン](https://developer.android.com/google/play/billing/subscriptions#prepaid-plans)(例: 数ヶ月分の非更新型サブスクリプションを購入)を利用できる場合、プリペイドプランに対して[保留中のトランザクション](https://developer.android.com/google/play/billing/subscriptions#pending)を有効にできます。 ```typescript showLineNumbers await adapty.activate({ apiKey: 'YOUR_PUBLIC_SDK_KEY', params: { android: { enablePendingPrepaidPlans: true, }, } }); ``` ## iOSでオファーコードを使う \{#redeem-offer-codes-in-ios\} --- no_index: true --- import Callout from '../../../components/Callout.astro'; <Details> <summary>オファーコードについて</summary> オファーコードを使うと、特定のユーザーに割引や無料トライアルを提供できます。自動的に適用される通常のオファーとは異なり、オファーコードはメールキャンペーン、SNS、印刷物など、アプリの外で配布します。ユーザーはApp Storeでコードを入力するか、引き換えURLを使うか、アプリ内ダイアログから利用できます。 オファーコードを設定するには、App Store Connectでサブスクリプションを開き、**Offer Codes** セクションに移動してください。オファーコードは[3種類](https://developer.apple.com/help/app-store-connect/manage-subscriptions/set-up-subscription-offer-codes)作成できます。 - **Free** — 指定した期間はサブスクリプションが無料になり、次の更新から通常価格になります。 - **Pay as you go** — 指定した期間、各請求サイクルに割引価格が適用され、その後は通常価格で更新されます。 - **Pay up front** — オファー期間全体に対して一括で割引価格を支払い、その後は通常価格で更新されます。 オファーコードをAdaptyに追加する必要はありません。Appleはオファー期間中のすべてのトランザクションにオファーコードカテゴリのタグを付与します。これには最初の引き換えとその後の割引更新がすべて含まれます。Adaptyはこのタグを検出し、各トランザクションをオファーカテゴリ `offer_code` として記録します。オファー期間が終了してサブスクリプションが通常価格で更新されると、タグは付与されなくなります。[Adapty ダッシュボード](controls-filters-grouping-compare-proceeds)のアナリティクスで **Offer Code** オファータイプによるフィルタリングが可能です。 #### 収益の差異が生じた場合のトラブルシューティング \{#revenue-discrepancy-troubleshooting\} オファーコードのトランザクションが、割引価格ではなく通常価格でAdaptyに記録されている場合は、App Store Connectで以下を確認してください。 - オファーコードに、ユーザーが引き換え可能なすべての地域に対して正しい価格が設定されているか。 - ユーザーの特定の国や地域に対してオファー価格が設定されているか。Appleはトランザクションに地域価格を含めて送信します。その地域のオファー価格が設定されていない場合、Appleは通常価格を送信することがあります。 [Adapty ダッシュボード](controls-filters-grouping-compare-proceeds)で、**Offer Code** オファータイプと **Offer Discount Type** フィルターを使ってオファーコードのトランザクションをフィルタリング・確認できます。 #### レガシープロモコード(非推奨) \{#legacy-promo-codes-deprecated\} <Callout type="warning"> Appleは2026年3月にアプリ内課金向けのプロモコードを廃止しました。オファーコードはより多くの機能(適格性の設定、有効期限、四半期あたり最大100万コード)を備えた後継機能です。アプリ内課金にプロモコードを使用していた場合は、App Store Connectでオファーコードに移行してください。 </Callout> レガシープロモコード(アプリのバージョンごとに最大100件)は、サブスクリプションへの無料アクセスを付与していました。オファーコードとは異なり、Appleはプロモコードのトランザクションに割引情報を含めず、レシートには通常価格が記載されていました。そのため、Adaptyはこれらのトランザクションを通常価格で記録し、Adaptyアナリティクスとレポートの間に収益の差異が生じていました。 本来は無料であるべきトランザクションが通常価格で記録されている履歴がある場合、それはレガシープロモコードによるものと考えられます。これらのコードは現在廃止されているため、正確な収益追跡のためにオファーコードに移行してください。 </Details> アプリ内でコード引き換えシートを表示するには: ```typescript showLineNumbers try { await adapty.presentCodeRedemptionSheet(); } catch (error) { console.error('Failed to present code redemption sheet:', error); } ``` :::danger 私たちの観察によると、一部のアプリではオファーコード引き換えシートが正常に動作しない場合があります。ユーザーをApp Storeに直接リダイレクトすることをお勧めします。 これを行うには、以下の形式のURLを開く必要があります: `https://apps.apple.com/redeem?ctx=offercodes&id={apple_app_id}&code={code}` ::: --- # File: capacitor-restore-purchase --- --- title: "Capacitor SDK でのアプリ内購入の復元" description: "Adapty で購入を復元してシームレスなユーザー体験を実現する方法を学びましょう。" --- iOS と Android の両方における購入の復元は、ユーザーが再度料金を支払うことなく、サブスクリプションやアプリ内課金などの以前に購入したコンテンツへのアクセスを取り戻せる機能です。この機能は、アプリをアンインストールして再インストールしたり、新しいデバイスに切り替えたりして、以前に購入したコンテンツに再度アクセスしたいユーザーにとって特に便利です。 :::note [ペイウォールビルダー](adapty-paywall-builder)で作成されたペイウォールでは、追加のコードなしに購入が自動的に復元されます。その場合は、このステップをスキップできます。 ::: [ペイウォールビルダー](adapty-paywall-builder)を使用してペイウォールをカスタマイズしていない場合に購入を復元するには、`.restorePurchases()` メソッドを呼び出してください。 ```typescript showLineNumbers try { const profile = await adapty.restorePurchases(); const isSubscribed = profile.accessLevels['YOUR_ACCESS_LEVEL']?.isActive; if (isSubscribed) { // Restore access to paid features console.log('Access restored successfully!'); } else { console.log('No active subscriptions found'); } } catch (error) { console.error('Failed to restore purchases:', error); } ``` レスポンスパラメーター: | パラメーター | 説明 | |---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **profile** | [`AdaptyProfile`](https://capacitor.adapty.io/interfaces/adaptyprofile) オブジェクトです。このモデルには、アクセスレベル、サブスクリプション、および非サブスクリプション購入に関する情報が含まれます。ユーザーがアプリへのアクセス権を持っているかどうかを確認するには、**アクセスレベルのステータス**を確認してください。 | --- # File: implement-observer-mode-capacitor --- --- title: "Capacitor SDKにObserverモードを実装する" description: "Capacitor SDKでAdaptyのオブザーバーモードを実装し、ユーザーのサブスクリプションイベントを追跡します。" --- すでに独自の購入インフラを持っており、Adaptyへの完全な移行に踏み切れない場合は、[Observerモード](observer-vs-full-mode)を検討してみてください。基本的な形では、Observerモードはアトリビューションおよびアナリティクスシステムとの高度な分析とシームレスな統合を提供します。 これで要件を満たせるなら、必要な作業は以下の2点だけです: 1. `observerMode`パラメーターを`true`に設定して、Adapty SDKの設定時にObserverモードをオンにします。[Capacitor](sdk-installation-capacitor#activate-adapty-module-of-adapty-sdk)のセットアップ手順に従ってください。 2. 既存の購入インフラからAdaptyへ[トランザクションを報告](report-transactions-observer-mode-capacitor)します。 ### Observerモードのセットアップ \{#observer-mode-setup\} 購入とサブスクリプションのステータスを自分で管理し、Adaptyをサブスクリプションイベントとアナリティクスの送信にのみ使用する場合は、Observerモードをオンにしてください。 :::important Observerモードで動作している場合、Adapty SDKはトランザクションをクローズしないため、必ず自分でハンドリングするようにしてください。 ::: ```typescript showLineNumbers try { await adapty.activate({ apiKey: 'YOUR_PUBLIC_SDK_KEY', params: { observerMode: true // Enable observer mode } }); } catch (error) { console.error('Failed to activate Adapty:', error); } ``` パラメーター: | パラメーター | 説明 | | --------------------------- | ------------------------------------------------------------ | | **observerMode** | [Observerモード](observer-vs-full-mode)を制御するboolean値です。デフォルト値は`false`です。 | ## ObserverモードでAdaptyのペイウォールを使用する \{#using-adapty-paywalls-in-observer-mode\} Adaptyのペイウォールやオーディエンスベースのターゲティング機能もあわせて利用したい場合は可能ですが、Observerモードでは追加のセットアップが必要です。上記の手順に加えて、以下を行ってください: 1. [リモートコンフィグペイウォール](present-remote-config-paywalls-capacitor)の通常の方法でペイウォールを表示します。 2. 購入トランザクションに[ペイウォールを関連付け](report-transactions-observer-mode-capacitor)ます。 --- # File: report-transactions-observer-mode-capacitor --- --- title: "Capacitor SDKのオブザーバーモードでトランザクションを報告する" description: "Capacitor SDKのAdaptyオブザーバーモードで購入トランザクションを報告し、ユーザーインサイトと収益トラッキングを実現します。" --- オブザーバーモードでは、Adapty SDKは既存の購入システムを通じて行われた購入を自動で追跡できません。アプリストアからのトランザクションを手動で報告する必要があります。アナリティクスのエラーを防ぐため、アプリをリリースする**前に**この設定を行うことが重要です。 `reportTransaction` を使用して、各トランザクションをAdaptyに明示的に報告してください。 :::warning **トランザクションの報告を省略しないでください!** `reportTransaction` を呼び出さないと、Adaptyはトランザクションを認識できず、アナリティクスに表示されず、インテグレーションにも送信されません。 ::: Adaptyのペイウォールを使用している場合は、トランザクションを報告する際に `variationId` を含めてください。これにより、購入がそれを起動したペイウォールに紐付けられ、正確なペイウォールアナリティクスが確保されます。 ```typescript showLineNumbers const variationId = paywall.variationId; try { await adapty.reportTransaction({ transactionId: 'your_transaction_id', variationId: variationId }); } catch (error) { console.error('Failed to report transaction:', error); } ``` パラメーター: | パラメーター | 必須/任意 | 説明 | | ------------- | -------- | ------------------------------------------------------------ | | **transactionId** | 必須 | <ul><li>iOS の場合: トランザクションの識別子。</li><li>Android の場合: 購入の文字列識別子(`purchase.getOrderId`)。ここで purchase は、ビリングライブラリの [Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase) クラスのインスタンスです。</li></ul> | | **variationId** | 任意 | バリアントの文字列識別子。[AdaptyPaywall](https://capacitor.adapty.io/interfaces/adaptypaywall) オブジェクトの `variationId` プロパティから取得できます。 | --- # File: capacitor-user --- --- title: "Users & access" description: "Learn how to work with users and access levels in your Capacitor app with Adapty SDK." --- <CustomDocCardList /> --- # File: capacitor-identifying-users --- --- title: "Capacitor SDKでユーザーを識別する" description: "Adapty SDKを使用してCapacitorアプリでユーザーを識別する方法を学びます。" --- Adaptyはすべてのユーザーに対して内部プロファイルIDを作成します。ただし、独自の認証システムを持っている場合は、独自のCustomer User IDを設定することができます。[Profiles](profiles-crm)セクションでCustomer User IDによりユーザーを検索したり、すべてのインテグレーションに送信される[サーバーサイドAPI](getting-started-with-server-side-api)で使用したりできます。 ### 設定時にCustomer User IDを設定する \{#setting-customer-user-id-on-configuration\} 設定時にユーザーIDがある場合は、`.activate()`メソッドの`customerUserId`パラメーターとして渡すだけです: ```typescript showLineNumbers try { await adapty.activate({ apiKey: 'YOUR_PUBLIC_SDK_KEY', params: { customerUserId: 'YOUR_USER_ID' } }); } catch (error) { console.error('Failed to activate Adapty:', error); } ``` ### 設定後にCustomer User IDを設定する \{#setting-customer-user-id-after-configuration\} SDKの設定時にユーザーIDがない場合は、`.identify()`メソッドを使っていつでも後から設定できます。このメソッドの最も一般的なユースケースは、ユーザーが匿名ユーザーから認証済みユーザーに切り替わる際の登録後または認証後です。 ```typescript showLineNumbers try { await adapty.identify({ customerUserId: 'YOUR_USER_ID' }); console.log('User identified successfully'); } catch (error) { console.error('Failed to identify user:', error); } ``` リクエストパラメーター: | パラメーター | 必須/任意 | 説明 | |---------|--------|-----------| | **customerUserId** | 必須 | 文字列のユーザー識別子。 | :::warning 重要なユーザーデータの再送信 ユーザーが再度アカウントにログインする場合など、Adaptyのサーバーにすでにそのユーザーの情報が存在していることがあります。このような場合、Adapty SDKは自動的に新しいユーザーに切り替えて動作します。カスタム属性やサードパーティネットワークからのアトリビューションなど、匿名ユーザーに渡したデータがある場合は、識別されたユーザーに対してそのデータを再送信する必要があります。 また、新しいユーザーのデータが異なる可能性があるため、ユーザーを識別した後にすべてのペイウォールとプロダクトを再取得する必要があることも重要です。 ::: ### ログアウトとログイン \{#logging-out-and-logging-in\} `.logout()`メソッドを呼び出すことで、いつでもユーザーをログアウトできます: ```typescript showLineNumbers try { await adapty.logout(); console.log('User logged out successfully'); } catch (error) { console.error('Failed to logout user:', error); } ``` その後、`.identify()`メソッドを使ってユーザーをログインできます。 ## `appAccountToken`を設定する(iOS) \{#assign-appaccounttoken-ios\} [`appAccountToken`](https://developer.apple.com/documentation/storekit/product/purchaseoption/appaccounttoken(_:))は、App Storeのトランザクションを内部ユーザーIDにリンクするための**UUID**です。 StoreKitはこのトークンをすべてのトランザクションに関連付けるため、バックエンドがApp StoreのデータをユーザーIDと照合できます。 ユーザーごとに生成した安定したUUIDを使用し、同じアカウントに対してデバイスをまたいで再利用してください。 これにより、購入とApp Storeの通知が正しく紐付けられます。 トークンは2つの方法で設定できます。SDKのアクティベーション時、またはユーザーを識別する際です。 :::important `appAccountToken`は必ず`customerUserId`と一緒に渡す必要があります。 トークンのみを渡した場合、トランザクションに含まれません。 ::: ```typescript showLineNumbers // During configuration: await adapty.activate({ apiKey: 'YOUR_PUBLIC_SDK_KEY', params: { customerUserId: 'YOUR_USER_ID', ios: { appAccountToken: "YOUR_APP_ACCOUNT_TOKEN" }, } }); // Or when identifying users await adapty.identify({ customerUserId: 'YOUR_USER_ID', params: { ios: { appAccountToken: 'YOUR_APP_ACCOUNT_TOKEN' }, } }); ``` ### 難読化されたアカウントIDを設定する(Android) \{#set-obfuscated-account-ids-android\} Google Playでは、ユーザーのプライバシーとセキュリティを強化するために、特定のユースケースで難読化されたアカウントIDが必要です。これらのIDにより、Google Playはユーザー情報を匿名のまま購入を識別できます。これは不正防止や分析において特に重要です。 アプリが機密性の高いユーザーデータを扱う場合や、特定のプライバシー規制に準拠する必要がある場合は、これらのIDを設定する必要があります。難読化されたIDにより、Google Playは実際のユーザー識別子を公開せずに購入を追跡できます。 ```typescript showLineNumbers // During configuration: await adapty.activate({ apiKey: 'YOUR_PUBLIC_SDK_KEY', params: { android: { obfuscatedAccountId: 'YOUR_OBFUSCATED_ACCOUNT_ID' }, } }); // Or when identifying users await adapty.identify({ customerUserId: 'YOUR_USER_ID', params: { android: { obfuscatedAccountId: 'YOUR_OBFUSCATED_ACCOUNT_ID' }, } }); ``` ## デバイスをまたいだユーザー検出 \{#detect-users-across-devices\} --- no_index: true --- SDKが有効化されると、StoreKit(iOS)またはGoogle Play Billing(Android)からユーザーの既存のエンタイトルメントを自動的に読み取り、Adaptyバックエンドと同期します。有効なサブスクリプションは、アプリが`restorePurchases`を呼び出すことなく、Adaptyプロファイルに表示されます。 **自動では行われない**のは、新しいデバイスのプロファイルが元のデバイスと同じユーザーのものであることの認識です。AdaptyはCustomer User IDでプロファイルを照合するため、同一性の継続性はCUIDとして何を使用するかによって異なります。 **デバイス間でAdaptyが検出できること** | あなたの設定 | Adaptyが検出すること | 必要な対応 | | --- | --- | --- | | Customer User ID = `device_id`(アプリのログインなし) | 新しいデバイスは異なるCUIDを取得するため、異なるプロファイルが作成されます。サブスクリプションは**Access level updated**イベントを通じて新しいプロファイルに同期されますが、`subscription_started`は発火しません。新しいプロファイルは元の購入の継承者として扱われます。`subscription_started`に基づくアナリティクスは、リターニングユーザーをカウント不足します。 | リターニングユーザーが既存のプロファイルをデバイス間で照合できるよう、安定したアカウントIDをCustomer User IDとして使用してください。 | | Customer User ID = 安定したアカウントID(すべてのデバイスでログイン) | SDKは`activate()`でサブスクリプションを自動同期し、`identify()`がCUIDで既存のプロファイルを照合します。 | 追加の設定は不要です。IDとサブスクリプションの両方が自動的に解決されます。 | | Apple Family Sharing の継承者 | ファミリーメンバーは**Access level updated**イベントのみを通じてサブスクリプションを受け取ります。`subscription_started`は発火しません。 | **Access level updated**をリッスンしてください。完全なイベントマトリクスは[Apple Family Sharing](apple-family-sharing)を参照してください。 | | 同じApple/Googleアカウント、異なるアプリ内ユーザー | 最初に購入を記録したプロファイルが親になります。その後のプロファイルは継承者チェーンを通じてサブスクリプションを確認し、**Access level updated**イベントが1回発生します。 | ログインを必須にし、あなたのモデルに合った[共有モード](sharing-paid-access-between-user-accounts)を選択してください。 | **新しいデバイスでの購入の復元** ペイウォールにユーザーが操作できる「購入を復元」ボタンを設置してください。Apple App Review(ガイドライン3.1.1)で必須とされており、自動同期がエッジケースを見逃した場合のフォールバックとして機能します。このボタンはSDKの`restorePurchases`を呼び出す必要があります。 初回起動時にプログラムで`restorePurchases`を呼び出すことは、通常の使用では必要ありません。SDKはすでに`activate()`で同等の処理を実行しています。プログラムによる呼び出しは、`activate()`完了後にアクセスが欠落している場合のデバッグなど、強制的に新しいレシートチェックを行う場合にのみ使用してください。 --- # File: capacitor-setting-user-attributes --- --- title: "Capacitor SDKでユーザー属性を設定する" description: "Adapty SDKを使ってCapacitorアプリでユーザー属性とプロファイルデータを更新する方法を解説します。" --- メールアドレスや電話番号など、アプリのユーザーにオプションの属性を設定できます。設定した属性は、ユーザーの[セグメント](segments)作成やCRMでの閲覧に活用できます。 ### ユーザー属性の設定 \{#setting-user-attributes\} ユーザー属性を設定するには、`.updateProfile()` メソッドを呼び出します: ```typescript showLineNumbers const params = { email: 'email@email.com', phoneNumber: '+18888888888', firstName: 'John', lastName: 'Appleseed', gender: 'other', birthday: new Date().toISOString(), }; try { await adapty.updateProfile(params); console.log('Profile updated successfully'); } catch (error) { console.error('Failed to update profile:', error); } ``` `updateProfile` メソッドで以前に設定した属性はリセットされないのでご注意ください。 :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: ### 使用可能なキーの一覧 \{#the-allowed-keys-list\} `AdaptyProfileParameters` で使用可能なキーとその値は以下の通りです: | キー | 値 | |---|-----| | **email** | 文字列 | | **phoneNumber** | 文字列 | | **firstName** | 文字列 | | **lastName** | 文字列 | | **gender** | 列挙型。使用可能な値: `'female'`、`'male'`、`'other'` | | **birthday** | ISO形式の日付文字列 | ### カスタムユーザー属性 \{#custom-user-attributes\} 独自のカスタム属性を設定することもできます。通常、アプリの利用状況に関連するものです。たとえば、フィットネスアプリなら週あたりの運動回数、語学学習アプリならユーザーの習熟度レベルなどが該当します。セグメントに活用してターゲットを絞ったペイウォールやオファーを作成したり、収益に最も影響を与えるプロダクト指標を分析することもできます。 ```typescript showLineNumbers try { await adapty.updateProfile({ codableCustomAttributes: { key_1: 'value_1', key_2: 2, }, }); console.log('Custom attributes updated successfully'); } catch (error) { console.error('Failed to update custom attributes:', error); } ``` 既存のキーを削除するには、値として `null` を渡します: ```typescript showLineNumbers try { // to remove keys, pass null as their values await adapty.updateProfile({ codableCustomAttributes: { key_1: null, key_2: null, }, }); console.log('Custom attributes removed successfully'); } catch (error) { console.error('Failed to remove custom attributes:', error); } ``` 事前に設定されているカスタム属性を確認したい場合は、`AdaptyProfile` オブジェクトの `customAttributes` フィールドを使用してください。 :::warning `customAttributes` の値は最新でない可能性があります。ユーザー属性は異なるデバイスからいつでも送信される可能性があるため、最後の同期以降にサーバー上の属性が変更されている場合があります。 ::: ### 制限事項 \{#limits\} - ユーザーあたり最大30個のカスタム属性 - キー名は最大30文字。使用できる文字は英数字と `_`、`-`、`.` のいずれか - 値は文字列または浮動小数点数で、50文字以内 --- # File: capacitor-listen-subscription-changes --- --- title: "Capacitor SDKでサブスクリプションステータスを確認する" description: "Capacitorアプリでのユーザーサブスクリプションステータスの追跡と管理により、Adaptyでの顧客維持率を向上させましょう。" --- Adaptyを使えば、サブスクリプションステータスの管理が簡単になります。プロダクトIDをコードに手動で記述する必要はありません。代わりに、有効な[アクセスレベル](access-level)を確認するだけで、ユーザーのサブスクリプションステータスを手軽に把握できます。 <details> <summary>サブスクリプションステータスの確認を始める前に(クリックして展開)</summary> - iOSの場合は、[App Store Server Notifications](enable-app-store-server-notifications)を設定してください - Androidの場合は、[リアルタイムデベロッパー通知(RTDN)](enable-real-time-developer-notifications-rtdn)を設定してください </details> ## アクセスレベルとAdaptyProfileオブジェクト \{#access-level-and-the-adaptyprofile-object\} アクセスレベルは[AdaptyProfile](https://capacitor.adapty.io/interfaces/adaptyprofile)オブジェクトのプロパティです。アプリの起動時(たとえば[ユーザーを識別する](capacitor-identifying-users#setting-customer-user-id-on-configuration)タイミング)にプロファイルを取得し、変更があるたびに更新することをお勧めします。こうすることで、都度リクエストを送ることなくプロファイルオブジェクトを利用できます。 プロファイルの更新通知を受け取るには、以下の[サブスクリプションステータス更新のリッスン](capacitor-listen-subscription-changes)セクションで説明している方法でプロファイルの変更をリッスンしてください。 :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: ## サーバーからアクセスレベルを取得する \{#retrieving-the-access-level-from-the-server\} サーバーからアクセスレベルを取得するには、`.getProfile()`メソッドを使用します。 ```typescript showLineNumbers try { const profile = await adapty.getProfile(); console.log('Profile retrieved successfully'); } catch (error) { console.error('Failed to get profile:', error); } ``` レスポンスパラメーター: | パラメーター | 説明 | | --------- |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **profile** | [AdaptyProfile](https://capacitor.adapty.io/interfaces/adaptyprofile)オブジェクト。通常、ユーザーがプレミアムアクセス権を持っているかどうかを判断するには、プロファイルのアクセスレベルステータスのみを確認すれば十分です。`.getProfile`メソッドは常にAPIに問い合わせるため、最新の結果を提供します。何らかの理由(インターネット接続なし等)でAdapty SDKがサーバーから情報を取得できない場合は、キャッシュのデータが返されます。なお、Adapty SDKは`AdaptyProfile`キャッシュを定期的に更新し、情報をできる限り最新の状態に保ちます。 | `.getProfile()`メソッドはユーザープロファイルを返し、そこからアクセスレベルのステータスを取得できます。アプリごとに複数のアクセスレベルを設定できます。たとえばニュースアプリで異なるトピックのサブスクリプションを個別に販売する場合、「sports」や「science」といったアクセスレベルを作成できます。ただし、ほとんどの場合はアクセスレベルは1つで十分です。その場合はデフォルトの「premium」アクセスレベルをそのまま使用できます。 デフォルトの「premium」アクセスレベルを確認する例を以下に示します。 ```typescript showLineNumbers try { const profile = await adapty.getProfile(); const isActive = profile.accessLevels['premium']?.isActive; if (isActive) { // Grant access to premium features console.log('User has premium access'); } else { console.log('User does not have premium access'); } } catch (error) { console.error('Failed to check subscription status:', error); } ``` ### サブスクリプションステータスの更新をリッスンする \{#listening-for-subscription-status-updates\} ユーザーのサブスクリプションが変更されると、Adaptyはイベントを発火します。 Adaptyからメッセージを受け取るには、追加の設定が必要です。 ```typescript showLineNumbers // Create an "onLatestProfileLoad" event listener adapty.addListener('onLatestProfileLoad', (data) => { const profile = data.profile; const isActive = profile.accessLevels['premium']?.isActive; if (isActive) { console.log('Subscription status updated: User has premium access'); } else { console.log('Subscription status updated: User does not have premium access'); } }); ``` Adaptyはアプリ起動時にもイベントを発火します。この場合、キャッシュされたサブスクリプションステータスが渡されます。 ### サブスクリプションステータスのキャッシュ \{#subscription-status-cache\} Adapty SDKに実装されたキャッシュは、プロファイルのサブスクリプションステータスを保存します。これにより、サーバーが利用できない場合でもキャッシュデータにアクセスでき、プロファイルのサブスクリプションステータスに関する情報を提供できます。 ただし、キャッシュからデータを直接リクエストすることはできません。SDKは1分ごとに定期的にサーバーへ問い合わせ、プロファイルに関する更新や変更がないかチェックします。新しいトランザクションなどの変更があれば、サーバーと同期を保つためにキャッシュデータへ反映されます。 --- # File: capacitor-deal-with-att --- --- title: "Capacitor SDK で ATT を処理する" description: "Capacitor で Adapty を使い始めて、サブスクリプションの設定と管理を効率化しましょう。" --- アプリが AppTrackingTransparency フレームワークを使用してアプリトラッキングの認証リクエストをユーザーに表示している場合は、[認証ステータス](https://developer.apple.com/documentation/apptrackingtransparency/attrackingmanager/authorizationstatus/)を Adapty に送信する必要があります。 ```typescript showLineNumbers try { await adapty.updateProfile({ appTrackingTransparencyStatus: AppTrackingTransparencyStatus.Authorized, }); console.log('ATT status updated successfully'); } catch (error) { console.error('Failed to update ATT status:', error); } ``` :::warning この値は変更があった際にできるだけ早く送信することを強くお勧めします。そうすることで、設定済みのインテグレーションにタイムリーにデータが送信されます。 ::: --- # File: capacitor-onboardings --- --- title: "Onboardings" description: "Learn how to work with onboardings in your Capacitor app with Adapty SDK." --- <CustomDocCardList /> --- # File: capacitor-get-onboardings --- --- title: "Capacitor SDK でオンボーディングを取得する" description: "Capacitor 向け Adapty でオンボーディングを取得する方法を説明します。" --- Adapty ダッシュボードのビルダーで[オンボーディングのビジュアルをデザイン](design-onboarding)したら、Capacitor アプリに表示できます。最初のステップは、プレースメントに紐づくオンボーディングとそのビュー設定を取得することです。 始める前に、以下を確認してください: 1. [オンボーディングを作成](create-onboarding)済みであること。 2. オンボーディングを[プレースメント](placements)に追加済みであること。 ## オンボーディングの取得 \{#fetch-onboarding\} ノーコードビルダーで[オンボーディング](onboardings)を作成すると、アプリが取得・表示する必要のある設定コンテナとして保存されます。このコンテナはコンテンツの内容・表示方法・ユーザー操作(クイズの回答やフォーム入力など)の処理方法を含む、エクスペリエンス全体を管理します。また、分析イベントを自動的に追跡するため、個別のビュートラッキングを実装する必要はありません。 パフォーマンスを最適化するため、ユーザーに表示する前に画像のダウンロードが完了するよう、早めにオンボーディング設定を取得してください。 オンボーディングを取得するには、`getOnboarding` メソッドを使用します: ```typescript showLineNumbers try { const onboarding = await adapty.getOnboarding({ placementId: 'YOUR_PLACEMENT_ID', locale: 'en', params: { fetchPolicy: 'reload_revalidating_cache_data', // サーバーから読み込み、失敗時はキャッシュを使用 loadTimeoutMs: 5000 // 5秒タイムアウト } }); console.log('Onboarding fetched successfully'); } catch (error) { console.error('Failed to fetch onboarding:', error); } ``` 次に、`createOnboardingView` メソッドを呼び出してビューインスタンスを作成します。 :::warning `createOnboardingView` メソッドの結果は一度しか使用できません。再度使用する必要がある場合は、`createOnboardingView` メソッドを新たに呼び出してください。 ::: ```typescript showLineNumbers if (onboarding.hasViewConfiguration) { try { const view = await createOnboardingView(onboarding); console.log('Onboarding view created successfully'); } catch (error) { console.error('Failed to create onboarding view:', error); } } else { // Use your custom logic console.log('Onboarding does not have view configuration'); } ``` パラメーター: | パラメーター | 必須 / 任意 | 説明 | |---------|--------|-----------| | **placementId** | 必須 | 目的の[プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成した際に指定した値です。 | | **locale** | <p>任意</p><p>デフォルト: `en`</p> | <p>オンボーディングのローカライズ識別子。マイナス(**-**)区切りの 1 つまたは 2 つのサブタグで構成される言語コードを指定します。最初のサブタグは言語、2 番目は地域を表します。</p><p></p><p>例:`en` は英語、`pt-br` はブラジルポルトガル語を表します。</p><p>ロケールコードと推奨利用方法については、[ローカライズとロケールコード](localizations-and-locale-codes)を参照してください。</p> | | **params.fetchPolicy** | <p>任意</p><p>デフォルト: `'reload_revalidating_cache_data'`</p> | <p>デフォルトでは、SDK はサーバーからデータの読み込みを試み、失敗した場合はキャッシュデータを返します。常に最新データをユーザーに提供できるため、このオプションを推奨します。</p><p></p><p>ユーザーのインターネット接続が不安定だと思われる場合は、`'return_cache_data_else_load'` を使用すると、キャッシュが存在する場合はキャッシュデータを返します。この場合、最新データが得られないことがありますが、接続状況によらず読み込みが速くなります。キャッシュは定期的に更新されるため、セッション中にネットワークリクエストを避けるために使用しても安全です。</p><p></p><p>キャッシュはアプリを再起動しても保持され、アプリの再インストールまたは手動でのクリーンアップ時にのみ削除されます。</p> | | **params.loadTimeoutMs** | <p>任意</p><p>デフォルト: 5000 ms</p> | <p>このメソッドのタイムアウト(ミリ秒)を制限します。タイムアウトに達した場合、キャッシュデータまたはローカルフォールバックが返されます。</p><p>内部で複数のリクエストが発生する場合があるため、まれに `loadTimeoutMs` で指定した時間より少し遅くタイムアウトすることがあります。</p> | レスポンスパラメーター: | パラメーター | 説明 | |:----------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **onboarding** | オンボーディングの識別子・設定・リモートコンフィグなどを含む [`AdaptyOnboarding`](https://capacitor.adapty.io/interfaces/adaptyonboarding) オブジェクト。 | ## デフォルトオーディエンスオンボーディングで取得を高速化する \{#speed-up-onboarding-fetching-with-default-audience-onboarding\} 通常、オンボーディングはほぼ瞬時に取得されるため、このプロセスを速くすることを特に意識する必要はありません。ただし、オーディエンスやオンボーディングが多数あり、ユーザーのインターネット接続が弱い場合は、取得に時間がかかることがあります。そのような場合、オンボーディングを全く表示しないよりも、デフォルトのオンボーディングを表示してスムーズなユーザー体験を提供したいことがあるでしょう。 この場合、`getOnboardingForDefaultAudience` メソッドを使用できます。このメソッドは、指定したプレースメントの **All Users** オーディエンス向けオンボーディングを取得します。ただし、推奨される方法は[オンボーディングの取得](#fetch-onboarding)セクションで説明した `getOnboarding` メソッドを使用することです。 :::warning `getOnboardingForDefaultAudience` の代わりに `getOnboarding` の使用を検討してください。前者には以下の重要な制限があります: - **互換性の問題**:複数のアプリバージョンをサポートする際に問題が生じる可能性があり、後方互換性のあるデザインが必要になるか、古いバージョンで正しく表示されないことを受け入れる必要があります。 - **パーソナライズなし**:「All Users」オーディエンス向けのコンテンツのみ表示され、国・アトリビューション・カスタム属性に基づくターゲティングは行われません。 取得速度の向上がこれらのデメリットを上回る場合は、以下のように `getOnboardingForDefaultAudience` を使用してください。そうでない場合は、[上記](#fetch-onboarding)の `getOnboarding` を使用してください。 ::: ```typescript showLineNumbers try { const onboarding = await adapty.getOnboardingForDefaultAudience({ placementId: 'YOUR_PLACEMENT_ID', locale: 'en', params: { fetchPolicy: 'reload_revalidating_cache_data' // サーバーから読み込み、失敗時はキャッシュを使用 } }); console.log('Default audience onboarding fetched successfully'); } catch (error) { console.error('Failed to fetch default audience onboarding:', error); } ``` パラメーター: | パラメーター | 必須 / 任意 | 説明 | |---------|--------|-----------| | **placementId** | 必須 | 目的の[プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成した際に指定した値です。 | | **locale** | <p>任意</p><p>デフォルト: `en`</p> | <p>オンボーディングのローカライズ識別子。マイナス(**-**)区切りの 1 つまたは 2 つのサブタグで構成される言語コードを指定します。最初のサブタグは言語、2 番目は地域を表します。</p><p></p><p>例:`en` は英語、`pt-br` はブラジルポルトガル語を表します。</p><p>ロケールコードと推奨利用方法については、[ローカライズとロケールコード](localizations-and-locale-codes)を参照してください。</p> | | **params.fetchPolicy** | <p>任意</p><p>デフォルト: `'reload_revalidating_cache_data'`</p> | <p>デフォルトでは、SDK はサーバーからデータの読み込みを試み、失敗した場合はキャッシュデータを返します。常に最新データをユーザーに提供できるため、このオプションを推奨します。</p><p></p><p>ユーザーのインターネット接続が不安定だと思われる場合は、`'return_cache_data_else_load'` を使用すると、キャッシュが存在する場合はキャッシュデータを返します。この場合、最新データが得られないことがありますが、接続状況によらず読み込みが速くなります。キャッシュは定期的に更新されるため、セッション中にネットワークリクエストを避けるために使用しても安全です。</p><p></p><p>キャッシュはアプリを再起動しても保持され、アプリの再インストールまたは手動でのクリーンアップ時にのみ削除されます。</p> | --- # File: capacitor-present-onboardings --- --- title: "Capacitor SDKでのオンボーディングの表示" description: "Capacitorでオンボーディングを表示してコンバージョンと収益を向上させる方法をご紹介します。" --- ビルダーでオンボーディングをカスタマイズした場合、ユーザーに表示するためにモバイルアプリのコードでレンダリングを行う必要はありません。そのようなオンボーディングには、オンボーディング内で表示される内容とその表示方法が両方含まれています。 始める前に、以下を確認してください: 1. [オンボーディングを作成](create-onboarding)している。 2. オンボーディングを[プレースメント](placements)に追加している。 ## オンボーディングを表示する \{#present-onboarding\} オンボーディングを表示するには、`createOnboardingView` メソッドで作成した `view` に対して `view.present()` メソッドを使用します。各 `view` は一度しか使用できません。オンボーディングを再度表示する必要がある場合は、`createOnboardingView` をもう一度呼び出して新しい `view` インスタンスを作成してください。 :::warning `view` を再作成せずに再利用するとエラーが発生する可能性があります。 ::: ```typescript showLineNumbers try { const view = await createOnboardingView(onboarding); view.setEventHandlers({ onClose: (actionId, meta) => { console.log('Onboarding closed:', actionId); return true; // Allow the onboarding to close }, onCustom: (actionId, meta) => { console.log('Custom action:', actionId); return false; // Don't close the onboarding } }); await view.present(); console.log('Onboarding presented successfully'); } catch (error) { console.error('Failed to present onboarding:', error); } ``` ## iOSの表示スタイルを設定する \{#configure-ios-presentation-style\} `present()` メソッドに `iosPresentationStyle` パラメーターを渡すことで、iOSでのオンボーディングの表示方法を設定できます。このパラメーターには `'full_screen'`(デフォルト)または `'page_sheet'` を指定できます。 ```typescript showLineNumbers await view.present({ iosPresentationStyle: 'page_sheet' }); ``` ## オンボーディング内のリンクの開き方をカスタマイズする \{#customize-how-links-open-in-onboardings\} :::important オンボーディング内のリンクの開き方のカスタマイズは、Adapty SDK v3.15以降でサポートされています。 ::: デフォルトでは、オンボーディング内のリンクはアプリ内ブラウザで開きます。これにより、ユーザーがアプリを切り替えることなくアプリ内でウェブページを閲覧できるシームレスなユーザー体験が提供されます。 外部ブラウザでリンクを開くことを希望する場合は、`openIn` パラメーターを `browser_out_app` に設定することでこの動作をカスタマイズできます: ```typescript showLineNumbers await view.present({ openIn: 'browser_out_app' }); // default — browser_in_app ``` ## 次のステップ \{#next-steps\} オンボーディングを表示したら、[ユーザーのインタラクションとイベントを処理](capacitor-handling-onboarding-events)しましょう。オンボーディングイベントの処理方法を学んで、ユーザーのアクションに応答し、アナリティクスを追跡してください。 --- # File: capacitor-handling-onboarding-events --- --- title: "Capacitor SDKでオンボーディングイベントを処理する" description: "Adaptyを使用してCapacitorでオンボーディング関連のイベントを処理します。" --- ビルダーで設定されたオンボーディングは、アプリが応答できるイベントを生成します。スタンドアロン画面の表示でこれらのイベントを処理するには、`setEventHandlers` メソッドを使用してください。 始める前に、以下を確認してください: 1. [オンボーディングを作成](create-onboarding)済みであること。 2. オンボーディングを[プレースメント](placements)に追加済みであること。 ## イベントハンドラーの設定 \{#set-up-event-handlers\} オンボーディングのイベントを処理するには、`view.setEventHandlers` メソッドを使用します: ```typescript showLineNumbers try { const view = await createOnboardingView(onboarding); view.setEventHandlers({ onAnalytics(event, meta) { console.log('Analytics event:', event); }, onClose(actionId, meta) { console.log('Onboarding closed:', actionId); return true; // Allow the onboarding to close }, onCustom(actionId, meta) { console.log('Custom action:', actionId); return false; // Don't close the onboarding }, onPaywall(actionId, meta) { console.log('Paywall action:', actionId); view.dismiss().then(() => { openPaywall(actionId); }); }, onStateUpdated(action, meta) { console.log('State updated:', action); }, onFinishedLoading(meta) { console.log('Onboarding finished loading'); }, onError(error) { console.error('Onboarding error:', error); }, }); await view.present(); } catch (error) { console.error('Failed to present onboarding:', error); } ``` ## イベントの種類 \{#event-types\} 以下のセクションでは、処理できるさまざまなイベントの種類を説明します。 ### カスタムアクションの処理 \{#handle-custom-actions\} ビルダーでボタンに **custom** アクションを追加し、IDを割り当てることができます。 <img src="/assets/shared/img/ios-events-1.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> このIDをコード内で使用し、カスタムアクションとして処理できます。たとえば、ユーザーが **Login** や **Allow notifications** などのカスタムボタンをタップすると、ビルダーの **Action ID** と一致する `actionId` パラメーターを持つイベントハンドラーがトリガーされます。"allowNotifications" のような独自のIDを作成できます。 ```typescript showLineNumbers view.setEventHandlers({ onCustom(actionId, meta) { switch (actionId) { case 'login': console.log('Login action triggered'); break; case 'allow_notifications': console.log('Allow notifications action triggered'); break; } return false; // Don't close the onboarding }, }); ``` <Details> <summary>イベントの例(クリックして展開)</summary> ```json { "actionId": "allow_notifications", "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 0, "screensTotal": 3 } } ``` </Details> ### オンボーディングの読み込み完了 \{#finishing-loading-onboarding\} オンボーディングの読み込みが完了すると、このイベントがトリガーされます: ```typescript showLineNumbers view.setEventHandlers({ onFinishedLoading(meta) { console.log('Onboarding loaded:', meta.onboardingId); }, }); ``` <Details> <summary>イベントの例(クリックして展開)</summary> ```json { "meta": { "onboarding_id": "onboarding_123", "screen_cid": "welcome_screen", "screen_index": 0, "total_screens": 4 } } ``` </Details> ### オンボーディングを閉じる \{#closing-onboarding\} ユーザーが **Close** アクションが割り当てられたボタンをタップすると、オンボーディングは閉じられたと見なされます。 <img src="/assets/shared/img/ios-events-2.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> :::important ユーザーがオンボーディングを閉じたときに何が起こるかを自分で管理する必要があります。たとえば、オンボーディング自体の表示を停止する必要があります。 ::: ```typescript showLineNumbers view.setEventHandlers({ onClose(actionId, meta) { console.log('Onboarding closed:', actionId); return true; // Allow the onboarding to close }, }); ``` <Details> <summary>イベントの例(クリックして展開)</summary> ```json { "action_id": "close_button", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "final_screen", "screen_index": 3, "total_screens": 4 } } ``` </Details> ### ペイウォールを開く \{#opening-a-paywall\} :::tip オンボーディング内でペイウォールを開きたい場合は、このイベントを処理してください。オンボーディングが閉じた後にペイウォールを開きたい場合は、クローズアクションを処理してイベントデータに依存せずにペイウォールを開く、よりシンプルな方法があります。 ::: オンボーディングでペイウォールを扱う最もシームレスな方法は、アクションIDをペイウォールのプレースメントIDと同じにすることです。 iOSでは、一度に1つのビュー(ペイウォールまたはオンボーディング)のみ画面に表示できることに注意してください。オンボーディングの上にペイウォールを表示する場合、バックグラウンドのオンボーディングをプログラムで操作することはできません。オンボーディングを閉じようとすると、代わりにペイウォールが閉じられ、オンボーディングが残ったままになります。これを避けるために、ペイウォールを表示する前に必ずオンボーディングビューを閉じてください。 ```typescript showLineNumbers view.setEventHandlers({ onPaywall(actionId, meta) { // Dismiss onboarding before presenting paywall view.dismiss().then(() => { openPaywall(actionId); }); }, }); async function openPaywall(placementId: string) { // Implement your paywall opening logic here } ``` <Details> <summary>イベントの例(クリックして展開)</summary> ```json { "action_id": "premium_offer_1", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "pricing_screen", "screen_index": 2, "total_screens": 4 } } ``` </Details> ### ナビゲーションのトラッキング \{#tracking-navigation\} オンボーディングフロー中にさまざまなナビゲーション関連イベントが発生すると、アナリティクスイベントを受け取ります: ```typescript showLineNumbers view.setEventHandlers({ onAnalytics(event, meta) { console.log('Analytics event:', event.type, meta.onboardingId); }, }); ``` `event` オブジェクトは以下のいずれかの種類になります: |種類 | 説明 | |------------|-------------| | `onboardingStarted` | オンボーディングが読み込まれたとき | | `screenPresented` | 任意の画面が表示されたとき | | `screenCompleted` | 画面が完了したとき。オプションの `elementId`(完了した要素の識別子)とオプションの `reply`(ユーザーからの応答)を含む。ユーザーが画面を離れるアクションを実行したときにトリガーされる。 | | `secondScreenPresented` | 2番目の画面が表示されたとき | | `userEmailCollected` | 入力フィールドでユーザーのメールアドレスが収集されたときにトリガーされる | | `onboardingCompleted` | ユーザーが `final` IDを持つ画面に到達したときにトリガーされる。このイベントが必要な場合は、[最後の画面に `final` IDを割り当ててください](design-onboarding)。 | | `unknown` | 認識されないイベントタイプの場合。`name`(不明なイベントの名前)と `meta`(追加のメタデータ)を含む | 各イベントには以下の `meta` 情報が含まれます: | フィールド | 説明 | |------------|-------------| | `onboardingId` | オンボーディングフローの一意の識別子 | | `screenClientId` | 現在の画面の識別子 | | `screenIndex` | フロー内での現在の画面の位置 | | `screensTotal` | フロー内の画面の総数 | <Details> <summary>イベントの例(クリックして展開)</summary> ```javascript // onboardingStarted { "name": "onboarding_started", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "welcome_screen", "screen_index": 0, "total_screens": 4 } } // screenPresented { "name": "screen_presented", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "interests_screen", "screen_index": 2, "total_screens": 4 } } // screenCompleted { "name": "screen_completed", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "profile_screen", "screen_index": 1, "total_screens": 4 }, "params": { "element_id": "profile_form", "reply": "success" } } // secondScreenPresented { "name": "second_screen_presented", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "profile_screen", "screen_index": 1, "total_screens": 4 } } // userEmailCollected { "name": "user_email_collected", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "profile_screen", "screen_index": 1, "total_screens": 4 } } // onboardingCompleted { "name": "onboarding_completed", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "final_screen", "screen_index": 3, "total_screens": 4 } } ``` </Details> --- # File: capacitor-onboarding-input --- --- title: "Capacitor SDKでオンボーディングのデータを処理する" description: "Adapty SDKを使ってCapacitorアプリのオンボーディングからデータを保存・活用する方法。" --- ユーザーがクイズに回答したり入力フィールドにデータを入力したりすると、`onStateUpdatedAction` メソッドが呼び出されます。コード内でフィールドの種類を保存したり処理したりできます。 例: ```typescript view.setEventHandlers({ onStateUpdated(action, meta) { // Process data }, }); ``` アクションのフォーマットは[こちら](https://capacitor.adapty.io/types/onboardingstateupdatedaction)をご覧ください。 <Details> <summary>保存データの例(実装によってフォーマットが異なる場合があります)</summary> ```javascript // Example of a saved select action { "elementId": "preference_selector", "meta": { "onboardingId": "onboarding_123", "screenClientId": "preferences_screen", "screenIndex": 1, "screensTotal": 3 }, "params": { "type": "select", "value": { "id": "option_1", "value": "premium", "label": "Premium Plan" } } } // Example of a saved multi-select action { "elementId": "interests_selector", "meta": { "onboardingId": "onboarding_123", "screenClientId": "interests_screen", "screenIndex": 2, "screensTotal": 3 }, "params": { "type": "multiSelect", "value": [ { "id": "interest_1", "value": "sports", "label": "Sports" }, { "id": "interest_2", "value": "music", "label": "Music" } ] } } // Example of a saved input action { "elementId": "name_input", "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 0, "screensTotal": 3 }, "params": { "type": "input", "value": { "type": "text", "value": "John Doe" } } } // Example of a saved date picker action { "elementId": "birthday_picker", "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 0, "screensTotal": 3 }, "params": { "type": "datePicker", "value": { "day": 15, "month": 6, "year": 1990 } } } ``` </Details> ## ユースケース \{#use-cases\} ### ユーザープロファイルをデータで補完する \{#enrich-user-profiles-with-data\} 入力データをすぐにユーザープロファイルと紐付けて、同じ情報を二度聞かないようにするには、アクション処理時に入力データで[ユーザープロファイルを更新](capacitor-setting-user-attributes)する必要があります。 たとえば、ユーザーに `name` というIDのテキストフィールドに名前を入力してもらい、その値をユーザーの名として設定したい場合や、`email` フィールドにメールアドレスを入力してもらう場合、アプリのコードは次のようになります: ```typescript showLineNumbers view.setEventHandlers({ onStateUpdated(action, meta) { // Store user preferences or responses if (action.elementType === 'input') { const profileParams: any = {}; // Map elementId to appropriate profile field switch (action.elementId) { case 'name': if (action.value.type === 'text') { profileParams.firstName = action.value.value; } break; case 'email': if (action.value.type === 'email') { profileParams.email = action.value.value; } break; } // Update profile if we have data to update if (Object.keys(profileParams).length > 0) { adapty.updateProfile({ params: profileParams }).catch((error) => { // handle the error }); } } }, }); ``` ### 回答に基づいてペイウォールをカスタマイズする \{#customize-paywalls-based-on-answers\} オンボーディングのクイズを活用して、オンボーディング完了後にユーザーに表示するペイウォールをカスタマイズすることもできます。 たとえば、スポーツの経験について質問し、ユーザーグループごとに異なるCTAやプロダクトを表示できます。 1. オンボーディングビルダーで[クイズを追加](onboarding-quizzes)し、選択肢にわかりやすいIDを割り当てます。 2. クイズの回答をIDで処理し、ユーザーに[カスタム属性を設定](capacitor-setting-user-attributes)します。 ```typescript showLineNumbers view.setEventHandlers({ onStateUpdated(action, meta) { // Handle quiz responses and set custom attributes if (action.elementType === 'select') { const profileParams: any = {}; // Map quiz responses to custom attributes switch (action.elementId) { case 'experience': // Set custom attribute 'experience' with the selected value (beginner, amateur, pro) profileParams.codableCustomAttributes = { experience: action.value.value }; break; } // Update profile if we have data to update if (Object.keys(profileParams).length > 0) { adapty.updateProfile({ params: profileParams }).catch((error) => { // handle the error }); } } }, }); ``` 3. カスタム属性の値ごとに[セグメントを作成](segments)します。 4. [プレースメント](placements)を作成し、作成した各セグメントに[オーディエンス](audience)を追加します。 5. アプリのコードでそのプレースメントの[ペイウォールを表示](capacitor-paywalls)します。オンボーディングにペイウォールを開くボタンがある場合は、[そのボタンのアクションへのレスポンス](capacitor-handling-onboarding-events#opening-a-paywall)としてペイウォールのコードを実装してください。 --- # File: capacitor-best-practices --- --- title: "Best practices in Capacitor SDK" description: "Reference patterns for integrating Adapty SDK on Capacitor — call order, error handling, and other production-readiness rules." --- <CustomDocCardList /> --- # File: capacitor-sdk-call-order --- --- title: "Capacitor SDKの呼び出し順序" description: "Adapty SDKのメソッドを正しい順序で呼び出すことで、プレミアムアクセスの喪失、アトリビューションの欠落、断続的な#2002エラーを回避できます。" --- `adapty.activate()` が完了してから、他のAdapty SDKメソッドを呼び出してください。解決される前は、SDKに状態がありません。`activate()` の前または並行して発行されたすべての呼び出しは、[`#2002 notActivated`](capacitor-handle-errors#custom-network-codes) で失敗します。 アプリがユーザー認証を行い、起動後にカスタマーユーザーIDを取得する場合は、その時点で `adapty.identify()` を呼び出してください。`identify` が解決されるまで、ユーザーアクションメソッドを呼び出さないでください。`identify` と競合する呼び出しは、[`#3006 profileWasChanged`](capacitor-handle-errors#custom-network-codes) で失敗するか、アクティベーション時に作成された匿名プロファイルに対して実行されます。これが発生すると、アトリビューション、`appsflyer_id` などのMMP ID、インストールの帰属が識別済みプロファイルに常に転送されるとは限りません。アプリがユーザー認証を行わない場合は、`identify` をスキップして匿名プロファイルで作業を続けてください。 MMP・アナリティクスSDK(AppsFlyer、Adjust、Branch、PostHog)も同じルールに従います。まずそれらを初期化し、UIDコールバックを待ってから `adapty.activate` を呼び出してください。そうしないと、MMP IDが一時的な匿名プロファイルに紐づき、識別済みプロファイルに常に転送されるとは限りません。AppsFlyerの詳細については、[AppsFlyer](appsflyer) を参照してください。 ## 正しい呼び出し順序 \{#the-correct-order\} どのパスを取るかは、カスタマーユーザーIDをいつ取得できるか、そしてMMPやアナリティクスSDKを使用するかどうかの2点によって決まります。 - **ステップ2と5**: すべてのアプリで必須。SDKをアクティベートしてから、SDKメソッドを呼び出します。 - **ステップ1と3**: MMPやアナリティクスSDK(AppsFlyer、Adjust、Branch、PostHog)を統合する場合のみ必須。 - **ステップ4**: アプリがユーザー認証を行い、起動後にカスタマーユーザーIDを収集する場合のみ必須。 アプリ起動時にカスタマーユーザーIDが分かっている場合は、`activate()` に直接渡してください(ステップ2a)。このパスでは匿名プロファイルが作成されないため、ステップ4は不要です。 | ステップ | 呼び出し | タイミング | 備考 | |------|---------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------| | 1 | MMPまたはアナリティクスSDKを初期化する(AppsFlyer、Adjust、PostHog、Branch) | アプリ起動時、最初に | MMPのUIDコールバック(例:`getAppsFlyerUID`)を待ちます。 | | 2a | `adapty.activate({ apiKey: '...', params: { customerUserId: '...' } })` | ステップ1の後、アプリ起動時、カスタマーユーザーIDが分かっている場合 | 推奨。匿名プロファイルは一切作成されません。 | | 2b | `adapty.activate({ apiKey: '...' })` (`customerUserId` なし) | ステップ1の後、アプリ起動時、カスタマーユーザーIDが分からない場合(または収集しない場合) | Adaptyが匿名プロファイルを作成します。 | | 3 | 各MMPに対して `adapty.setIntegrationIdentifier({ key: '...', value: '...' })` | ステップ2の後、ユーザーアクション呼び出しの前 | MMP IDが正しいプロファイルに紐づくために必須。 | | 4 | `await adapty.identify({ customerUserId: 'YOUR_USER_ID' })` | ステップ3の後(MMPがない場合はステップ2の後)、ステップ5の前 — 認証ありのパス2bのみ | 必ず `await` を使用。`identify` 中の並行呼び出しは `#3006 profileWasChanged` を引き起こします。 | | 5 | `getPaywall`、`getPaywallProducts`、`restorePurchases`、`makePurchase`、`updateAttribution`、`updateProfile` | `identify` を呼び出す場合はステップ4の後、それ以外はステップ3の後(MMPがない場合はステップ2の後) | これらの呼び出しには安定したプロファイルが必要です。 | :::important これらのステップをスキップすると、復帰ユーザーのプレミアムアクセスの喪失、プロファイルへの `appsflyer_id` の欠落、誤ったオーディエンスに対するペイウォールの返却が発生します。 ::: ## Web2appとウェブファネルのインストール \{#web2app-and-web-funnel-installs\} ユーザーがウェブチェックアウト(Stripe、Paddle)で購入した後にネイティブアプリをインストールする場合、デバイスの最初の `activate()` は新しい匿名プロファイルを作成します。このプロファイルはウェブプロファイルとリンクされていません。アプリ起動前にカスタマーユーザーIDを解決できる場合(認証フローやインストールリファラーから)、`activate()` に直接渡してください。そうでない場合、ウェブ購入は `identify({ customerUserId: 'YOUR_USER_ID' })` を呼び出してから `restorePurchases` を呼び出すまで、デバイス上では表示されません。 各ウェブチェックアウトで送信するメタデータについては、以下を参照してください: - [Stripe](stripe) - [Paddle](paddle) --- # File: capacitor-optimize-paywall-fetching --- --- title: "Capacitor SDKでペイウォール取得を最適化する" description: "Capacitorでの信頼性の高いAdaptyペイウォール取得:タイミング、キャッシュ、フォールバックパターン。" --- Capacitorで信頼性の高いペイウォール取得を実現するには、次の3つが重要です。高速なレンダリング、オーディエンスターゲティングされたペイウォールの返却、そしてネットワークが遅い場合のグレースフルなフォールバックです。以下のルールでは、それを実現するためのタイミング、キャッシュ、フォールバックパターンについて説明します。 :::tip これらのルールは、`adapty.activate()` と `adapty.identify()` がすでに解決済みであることを前提としています。詳しくは[Capacitor SDKでの呼び出し順序](capacitor-sdk-call-order)を参照してください。 ::: ## ルールと注意点 \{#rules-and-pitfalls\} | 推奨 | 非推奨 | 理由 | |---|---|---| | これから表示するプレースメントのみを取得する。 | 起動時にすべてのプレースメントをまとめてプリフェッチする。 | 一括プリフェッチはメインスレッドをブロックし、その間に画面が真っ暗になる。 | | アトリビューションが解決される時間を確保してから `getPaywall` を呼び出す(例:`activate` の1〜2秒後、または `onLatestProfileLoad` リスナーが発火した後)。 | `App.tsx` のアプリ起動時に `getPaywall` を呼び出す。 | アトリビューションがまだ反映されていないため、ペイウォールがデフォルトのオーディエンスで解決され、セグメントやASAのパーソナライズが無効にバイパスされる。 | | `loadTimeoutMs` を設定し、すべてのプレースメントに[フォールバックペイウォール](fallback-paywalls)を設定する。 | `getPaywall` を無制限に待ち続ける。 | タイムアウトがないと、通信状態の悪いユーザーはネットワークが回復するまで空白画面を見続けるか、アプリを閉じてしまう。 | `fetchPolicy` と `loadTimeoutMs` パラメーターの詳細については[ペイウォールとプロダクトの取得](fetch-paywalls-and-products-capacitor)を、適切なプレースメントの選び方については[プレースメント](placements)を参照してください。 ## 通信状態が悪い場合のチューニング \{#tune-for-poor-connectivity\} 通信状態が常に悪い市場(地方エリア、移動中、ルーティングの問題がある地域)向けには: - 初回以外のすべての取得で `fetchPolicy: 'return_cache_data_else_load'` を設定する。 - Adapty ダッシュボードですべてのプレースメントに[フォールバックペイウォール](fallback-paywalls)を設定する。 - `loadTimeoutMs` を3000〜5000ミリ秒に設定し、タイムアウト時はフォールバックを受け入れる。 - `adapty.getProfile()` の完了をペイウォール表示の条件にしない。プロファイルの遅延でUIがブロックされないよう、`getPaywall` は独立して呼び出す。 --- # File: capacitor-show-aa-targeted-paywall --- --- title: "Capacitor SDKで初回起動時にAA対象のペイウォールを表示する" description: "AdaptyProfile.appliedAttributionSourcesを使用して、Capacitorで即座にペイウォールを表示し、アトリビューションが適用されたApple Adsユーザー向けにアップグレードする方法を説明します。" --- Apple Ads(AA)のアトリビューションは、`adapty.activate()` の後に非同期で届きます。初回起動時にはまだ届いていないことが多いため、`getPaywall` はデフォルトのオーディエンスに対して解決され、Apple AdsユーザーはAAセグメント向けのペイウォールを見逃してしまいます。アトリビューションが届くまでペイウォールの表示を遅らせるのではなく、まず即座に表示しておき、AAのアトリビューションが適用されたタイミングでリフレッシュしましょう。こうすることで、Apple Adsユーザーはターゲット向けのバリアントを受け取り、それ以外のユーザーは待ち時間なくペイウォールを見ることができます。`AdaptyProfile.appliedAttributionSources` を使うと、AAのアトリビューションが適用されたタイミングを把握できます。 ## 始める前に \{#before-you-start\} 必要なもの: - Adapty Capacitor SDK **3.17.1** 以降。 - AdaptyでApple Adsがアプリに設定済みであること。[Apple Ads](apple-search-ads) を参照してください。 ## 仕組み \{#how-it-works\} `adapty.activate()` の後、SDKはバックグラウンドでAppleからApple Adsのアトリビューションを取得し、Adaptyのバックエンドに転送します。AAがプロファイルのアクティブなアトリビューションソースになると、SDKは更新された `AdaptyProfile` を `onLatestProfileLoad` リスナーに配信します。この `AdaptyProfile` の `appliedAttributionSources` 配列には `'apple_search_ads'` が含まれています。 これにより、ペイウォールの読み込みを2ステップで行うことができます: 1. すぐに `getPaywall` を呼び出します。アトリビューションがまだ適用されていない状態では、Adaptyはデフォルトのオーディエンスでリクエストを解決するため、ユーザーはすぐにペイウォールを見ることができます。 2. `'apple_search_ads'` が現れたら、再度 `getPaywall` を呼び出します。AdaptyはApple Adsのオーディエンスに対してリクエストを解決し、ターゲット向けのペイウォールを返します。これが最初のペイウォールと置き換わります。 `appliedAttributionSources` は空またはない場合があります。その場合は以下のどちらかを意味します: - このプロファイルに対するApple Adsのアトリビューションがまだ処理されていない、または - アトリビューションがまったく届いていない。 いずれの場合も、ステップ1は安全です。Adaptyは現在のプロファイル状態に一致するオーディエンス(通常はデフォルトオーディエンス)でリクエストを解決します。ステップ2は `'apple_search_ads'` が現れたときにのみ実行されます。 :::important それ以降の起動では、キャッシュされたプロファイルにすでに `appliedAttributionSources` に `'apple_search_ads'` が含まれているため、最初の `getPaywall` からApple Ads向けのセグメントペイウォールが返されます。2回目のフェッチや表示の変化は発生しません。この2ステップのフローが意味を持つのは、アトリビューションがまだ処理中の初回起動時のみです。 ::: ## 実装 \{#implementation\} まずペイウォールをすぐに表示し、`'apple_search_ads'` を監視して、届いたタイミングでペイウォールをリフレッシュします。 1. **SDKを有効化します。** [Capacitor SDKのインストールと設定](sdk-installation-capacitor) を参照してください。 2. **`getPaywall` でペイウォールを読み込んで表示します。** アトリビューションを待たずに進めてください。 3. **`adapty.addListener('onLatestProfileLoad', …)` でプロファイルの更新を購読し、**`'apple_search_ads'` を監視します。現れたら再度ペイウォールを取得し、更新されたものを表示します。リスナーをまだ設定していない場合は、[サブスクリプションの更新を監視する](capacitor-check-subscription-status#listen-to-subscription-updates) を参照してください: ```typescript const listener = await adapty.addListener('onLatestProfileLoad', async ({ profile }) => { if (!profile.appliedAttributionSources?.includes('apple_search_ads')) return; const targeted = await adapty.getPaywall({ placementId }); // present the targeted paywall in place of the first one }); // Call listener.remove() after the upgrade, or after a timeout (see below). ``` 4. **タイムアウト後にリスナーを停止します。** ほとんどのユーザーはApple Adsのアトリビューションを受け取らないため、セッション全体を通じてリスナーを開いたままにせず、一定時間後に削除してください。プレースメントに[フォールバックペイウォール](capacitor-use-fallback-paywalls)を設定しておくと、リクエストが失敗した場合でも常にユーザーに何かを表示できます。 ## 完全な例 \{#complete-example\} `onAppleAdsAttribution` は、Apple Adsのアトリビューションが適用されると解決され、`timeoutMs` 後にタイムアウトで拒否されます。以下の使用例では、まずすぐにペイウォールを読み込み、アトリビューションが届いたときに再取得します。Apple Adsユーザーはターゲット向けのペイウォールを受け取り、アトリビューションが届かない場合は最初のペイウォールがそのまま表示されます: ```typescript const APPLE_ADS_SOURCE = 'apple_search_ads'; const placementId = 'YOUR_PLACEMENT_ID'; function hasAppleAdsAttribution(profile: AdaptyProfile): boolean { return profile.appliedAttributionSources?.includes(APPLE_ADS_SOURCE) ?? false; } /** * Resolves once Apple Ads attribution is applied to the profile. * Rejects with a timeout error if attribution never arrives within `timeoutMs`. * Call after `adapty.activate()`. */ export function onAppleAdsAttribution(timeoutMs: number): Promise<void> { return new Promise((resolve, reject) => { let timer: ReturnType<typeof setTimeout> | undefined; let handle: { remove: () => void } | undefined; const stop = () => { clearTimeout(timer); handle?.remove(); }; adapty .addListener('onLatestProfileLoad', ({ profile }) => { if (!hasAppleAdsAttribution(profile)) return; stop(); resolve(); }) .then(listener => { handle = listener; }); timer = setTimeout(() => { stop(); reject(new Error(`Apple Ads attribution timed out after ${timeoutMs}ms`)); }, timeoutMs); }); } let paywall = await adapty.getPaywall({ placementId }); onAppleAdsAttribution(30_000) .then(() => adapty.getPaywall({ placementId })) .then(updated => { paywall = updated; }) .catch(() => { console.log('Apple Ads attribution or loading failed'); }); ``` 初回起動時、Apple Adsユーザーはデフォルトのペイウォールをわずかな間表示した後、ターゲット向けのペイウォールに切り替わります。ペイウォールビルダーでペイウォールを表示している場合は、再表示が許容できるかどうかを検討するか、ペイウォールが表示される前にのみアップグレードを適用するようにしてください。`timeoutMs` は、リスナーをどのくらいの間維持したいかに合わせて調整してください。届くアトリビューションは通常、起動から数秒以内に届きます。 アプリが他の目的(例えば[サブスクリプションステータスの確認](capacitor-check-subscription-status#listen-to-subscription-updates))でも `onLatestProfileLoad` を監視している場合、変更は必要ありません。`adapty.addListener` は複数の独立したリスナーをサポートしているため、既存のリスナーに影響を与えることなく独自のリスナーを追加できます。 --- # File: capacitor-test --- --- title: "Test & release in Capacitor SDK" description: "Learn how to test and release your Capacitor app with Adapty SDK." --- If you've already implemented the Adapty SDK in your Capacitor app, you'll want to test that everything is set up correctly and that purchases work as expected across both iOS and Android platforms. This involves testing both the SDK integration and the actual purchase flow with Apple's sandbox environment and Google Play's testing environment. ## Test your app For comprehensive testing of your in-app purchases, see our platform-specific testing guides: [iOS testing guide](test-purchases-in-sandbox) and [Android testing guide](testing-on-android). ## Prepare for release Before submitting your app to the store, follow the [Release checklist](release-checklist) to confirm: - Store connection and server notifications are configured - Purchases complete and are reported to Adapty - Access unlocks and restores correctly - Privacy and review requirements are met --- # File: kids-mode-capacitor --- --- title: "Capacitor SDKのキッズモード" description: "AppleとGoogleのポリシーに準拠するためのキッズモードを簡単に有効化。Capacitor SDKではIDFA、GAID、広告データは収集されません。" --- Capacitorアプリが子ども向けの場合、[Apple](https://developer.apple.com/kids/)と[Google](https://support.google.com/googleplay/android-developer/answer/9893335)のポリシーに従う必要があります。Adapty SDKを使用している場合、いくつかの簡単な手順でポリシーに準拠した設定を行い、アプリストアの審査を通過できます。 ## 必要な対応 \{#whats-required\} 以下のデータ収集を無効にするよう、Adapty SDKを設定する必要があります: - [IDFA(広告識別子)](https://en.wikipedia.org/wiki/Identifier_for_Advertisers)(iOS) - [Android広告ID(AAID/GAID)](https://support.google.com/googleplay/android-developer/answer/6048248)(Android) - [IPアドレス](https://www.ftc.gov/system/files/ftc_gov/pdf/p235402_coppa_application.pdf) また、カスタマーユーザーIDの扱いには注意が必要です。`<FirstName.LastName>`形式のユーザーIDや、メールアドレスを使用することは、個人情報の収集とみなされます。キッズモードでは、コンプライアンスを確保するために、ランダム化または匿名化された識別子(ハッシュ化されたIDやデバイス生成のUUIDなど)を使用することをお勧めします。 ## キッズモードの有効化 \{#enabling-kids-mode\} ### Adapty ダッシュボードでの設定 \{#updates-in-the-adapty-dashboard\} Adapty ダッシュボードでIPアドレスの収集を無効にする必要があります。[App settings](https://app.adapty.io/settings/general)に移動し、**Collect users' IP address**の下にある**Disable IP address collection**をクリックしてください。 ### モバイルアプリのコード変更 \{#updates-in-your-mobile-app-code\} ポリシーに準拠するため、ユーザーのIDFA、GAID、およびIPアドレスの収集を無効にしてください: ```typescript showLineNumbers try { await adapty.activate({ apiKey: 'YOUR_PUBLIC_SDK_KEY', params: { // Disable IP address collection ipAddressCollectionDisabled: true, // Disable IDFA collection on iOS ios: { idfaCollectionDisabled: true }, // Disable Google Advertising ID collection on Android android: { adIdCollectionDisabled: true } } }); console.log('Adapty activated with Kids Mode enabled'); } catch (error) { console.error('Failed to activate Adapty with Kids Mode:', error); } ``` ### プラットフォーム固有の設定 \{#platform-specific-configurations\} #### iOS:CocoaPodsでキッズモードを有効にする \{#ios-enable-kids-mode-using-cocoapods\} iOSでCocoaPodsを使用している場合、ネイティブレベルでキッズモードを有効にすることもできます: 1. Podfileを更新します: - `post_install`セクションが**ない**場合は、以下のコードブロック全体を追加してください。 - `post_install`セクションが**ある**場合は、ハイライトされた行をそのセクションに追記してください。 ```ruby showLineNumbers title="Podfile" def adapty_enable_kids_mode(installer) installer.pods_project.targets.each do |target| next unless target.name == 'Adapty' target.build_configurations.each do |config| flags = config.build_settings['OTHER_SWIFT_FLAGS'] || '$(inherited)' flags = flags.join(' ') if flags.is_a?(Array) config.build_settings['OTHER_SWIFT_FLAGS'] = "#{flags} -DADAPTY_KIDS_MODE" end target.frameworks_build_phase.files.dup.each do |bf| target.frameworks_build_phase.remove_build_file(bf) if bf.display_name.to_s.include?('AdSupport') end end installer.pods_project.save Dir.glob(File.join(installer.sandbox.root, 'Target Support Files', '**', '*.xcconfig')).each do |xc| File.write(xc, File.read(xc).gsub(/\s*-framework\s+"?AdSupport"?/, '')) end end post_install do |installer| # ... keep your existing post_install body (Flutter adds one automatically) ... adapty_enable_kids_mode(installer) # <-- enable Adapty Kids Mode end ``` 2. 変更を適用するために以下のコマンドを実行します: ```sh showLineNumbers title="Shell" pod install ``` #### Android:Gradleでキッズモードを有効にする \{#android-enable-kids-mode-using-gradle\} Androidの場合、アプリの`build.gradle`に以下を追加することで、ネイティブレベルでもキッズモードを有効にできます: ```groovy showLineNumbers title="android/app/build.gradle" android { defaultConfig { // ... existing config ... // Enable Kids Mode buildConfigField "boolean", "ADAPTY_KIDS_MODE", "true" } } ``` ## 次のステップ \{#next-steps\} キッズモードを有効にしたら、以下を確認してください: 1. アプリを十分にテストし、すべての機能が正常に動作することを確認する 2. 無効にしたデータ収集を反映するよう、アプリのプライバシーポリシーを見直す 3. キッズモードのコンプライアンスに関する明確なドキュメントを添えてアプリを審査に提出する プラットフォーム固有の要件の詳細については: - [iOS SDKのキッズモード](kids-mode)(追加のiOS設定の詳細) - [Android SDKのキッズモード](kids-mode-android)(追加のAndroid設定の詳細) --- # File: capacitor-reference --- --- title: "Reference" description: "Reference documentation for Adapty Capacitor SDK." --- This page contains reference documentation for Adapty Capacitor SDK. Choose the topic you need: - **[SDK models](https://capacitor.adapty.io/)** - Data models and structures used by the SDK - **[Handle errors](capacitor-handle-errors)** - Error handling and troubleshooting --- # File: capacitor-handle-errors --- --- title: "Capacitor SDKのエラー処理" description: "Capacitor SDKのエラー処理。" --- SDKから返されるすべてのエラーは`AdaptyError`インスタンスです。以下に例を示します: :::tip **デバッグ前に詳細ログを有効にしてください。** ほとんどの`AdaptyError`は、StoreKit・Play Billing・ネットワーク・バックエンドのエラーをラップしています。詳細ログを有効にする(`adapty.setLogLevel({ logLevel: 'verbose' })`)と — [ログ](sdk-installation-capacitor#logging)を参照 — ラップされたエラーがコンソールに出力され、実際の原因を特定しやすくなります。`AdaptyError`の`detail`プロパティはログレベルに関わらず設定されますが、詳細ログを有効にすることでコンソールにも表示されます。 ::: ```typescript showLineNumbers try { const result = await adapty.makePurchase({ product }); // Handle purchase result if (result.type === 'success') { console.log('Purchase successful:', result.profile); } else if (result.type === 'user_cancelled') { console.log('User cancelled the purchase'); } else if (result.type === 'pending') { console.log('Purchase is pending'); } } catch (error) { if (error instanceof AdaptyError) { console.error('Adapty error:', error.adaptyCode, error.localizedDescription); // Handle specific error codes switch (error.adaptyCode) { case ErrorCodeName.cantMakePayments: console.log('In-app purchases are not allowed on this device'); break; case ErrorCodeName.notActivated: console.log('Adapty SDK is not activated'); break; case ErrorCodeName.productPurchaseFailed: console.log('Purchase failed:', error.detail); break; default: console.log('Other error occurred:', error.detail); } } else { console.error('Non-Adapty error:', error); } } ``` ## エラープロパティ \{#error-properties\} `AdaptyError`クラスは以下のプロパティを提供します: | プロパティ | 型 | 説明 | |----------|------|-------------| | `adaptyCode` | `number` | 数値エラーコード(例:`cantMakePayments`の場合は`1003`) | | `localizedDescription` | `string` | ユーザー向けのエラーメッセージ | | `detail` | `string \| undefined` | 追加のエラー詳細(任意) | | `message` | `string` | コードと説明を含む完全なエラーメッセージ | ## エラーコード \{#error-codes\} SDKはエラーコードを扱うための定数とユーティリティをエクスポートしています: ### ErrorCodeName定数 \{#errorcodename-constant\} 文字列識別子を数値コードにマッピングします: ```typescript ErrorCodeName.cantMakePayments // 1003 ErrorCodeName.notActivated // 2002 ErrorCodeName.networkFailed // 2005 ``` ### ErrorCode定数 \{#errorcode-constant\} 数値コードを文字列識別子にマッピングします: ```typescript ErrorCode[1003] // 'cantMakePayments' ErrorCode[2002] // 'notActivated' ErrorCode[2005] // 'networkFailed' ``` ### ヘルパー関数 \{#helper-functions\} ```typescript // Get numeric code from string name: getErrorCode('cantMakePayments') // 1003 // Get string name from numeric code: getErrorPrompt(1003) // 'cantMakePayments' ``` ### エラーコードの比較 \{#comparing-error-codes\} **重要:** `error.adaptyCode`は**数値**なので、数値コードと直接比較してください: ```typescript // Option 1: Use ErrorCodeName constant (recommended) ✅ if (error.adaptyCode === ErrorCodeName.cantMakePayments) { console.log('Cannot make payments'); } // Option 2: Compare with numeric literal ✅ if (error.adaptyCode === 1003) { console.log('Cannot make payments'); } // NOT like this ❌ - compares number to string and will never match if (error.adaptyCode === ErrorCode[1003]) { } ``` ## グローバルエラーハンドラー \{#global-error-handler\} すべてのAdaptyエラーをキャッチするグローバルエラーハンドラーを設定できます: ```typescript showLineNumbers // Set up global error handler AdaptyError.onError = (error: AdaptyError) => { console.error('Global Adapty error:', { code: error.adaptyCode, message: error.localizedDescription, detail: error.detail }); // Handle specific error types globally if (error.adaptyCode === ErrorCodeName.notActivated) { // SDK not activated - maybe retry activation console.log('SDK not activated, attempting to reactivate...'); } }; ``` ## よくあるエラー処理パターン \{#common-error-handling-patterns\} ### 購入エラーの処理 \{#handle-purchase-errors\} ```typescript showLineNumbers async function handlePurchase(product: AdaptyPaywallProduct) { try { const result = await adapty.makePurchase({ product }); if (result.type === 'success') { console.log('Purchase successful:', result.profile); } else if (result.type === 'user_cancelled') { console.log('User cancelled the purchase'); } else if (result.type === 'pending') { console.log('Purchase is pending'); } } catch (error) { if (error instanceof AdaptyError) { switch (error.adaptyCode) { case ErrorCodeName.cantMakePayments: console.log('In-app purchases not allowed'); break; case ErrorCodeName.productPurchaseFailed: console.log('Purchase failed:', error.detail); break; default: console.error('Purchase error:', error.localizedDescription); } } } } ``` ### ネットワークエラーの処理 \{#handle-network-errors\} ```typescript showLineNumbers async function fetchPaywall(placementId: string) { try { const paywall = await adapty.getPaywall({ placementId }); return paywall; } catch (error) { if (error instanceof AdaptyError) { switch (error.adaptyCode) { case ErrorCodeName.networkFailed: console.log('Network error, retrying...'); // Implement retry logic break; case ErrorCodeName.serverError: console.log('Server error:', error.detail); break; case ErrorCodeName.notActivated: console.log('SDK not activated'); break; default: console.error('Paywall fetch error:', error.localizedDescription); } } throw error; } } ``` ## システム StoreKit コード \{#system-storekit-codes\} | エラー | コード | 説明 | |-----|----|-----------| | unknown | 0 | 不明または予期しないエラーが発生したことを示します。 | | clientInvalid | 1 | クライアントが実行しようとした操作を許可されていないことを示します。 | | paymentCancelled | 2 | <p>ユーザーが支払いリクエストをキャンセルしたことを示します。</p><p>特に対応は不要ですが、ビジネスロジックの観点から、ユーザーに割引を提示したり、後でリマインドしたりすることができます。</p> | | paymentInvalid | 3 | 支払いパラメーターのいずれかがストアに認識されなかったことを示します。 | | paymentNotAllowed | 4 | <p>ユーザーが支払いを承認する権限を持っていないことを示します。考えられる原因:</p><p></p><p>- ユーザーの国では支払いがサポートされていない。</p><p>- ユーザーが未成年である。</p> | | storeProductNotAvailable | 5 | リクエストされたプロダクトが App Store に存在しないことを示します。対象国でプロダクトが利用可能になっているか確認してください。 | | cloudServicePermissionDenied | 6 | ユーザーがクラウドサービス情報へのアクセスを許可していないことを示します。 | | cloudServiceNetworkConnectionFailed | 7 | デバイスがネットワークに接続できなかったことを示します。 | | cloudServiceRevoked | 8 | ユーザーがクラウドサービスの使用許可を取り消したことを示します。 | | privacyAcknowledgementRequired | 9 | ユーザーがストアのプライバシーポリシーにまだ同意していないことを示します。 | | unauthorizedRequestData | 10 | リクエストが正しく構築されていないことを示します。 | | invalidOfferIdentifier | 11 | <p>オファー識別子が無効です。考えられる原因:</p><p></p><p>- App Store でその識別子のオファーをまだ設定していない。</p><p>- オファーを取り消している。</p><p>- オファー ID を誤って入力している。</p> | | invalidSignature | 12 | 支払いディスカウントの署名が無効であることを示します。**In-app purchase Key ID** フィールドに入力し、**In-App Purchase Private Key** ファイルをアップロードしているか確認してください。詳細は [App Store インテグレーションの設定](app-store-connection-configuration) を参照してください。 | | missingOfferParams | 13 | <p>Adapty インテグレーションまたはオファーに問題があることを示します。</p><p>設定方法の詳細は [App Store インテグレーションの設定](app-store-connection-configuration) および [オファー](offers) を参照してください。</p> | | invalidOfferPrice | 14 | ストアで指定した価格が無効になったことを示します。オファーは常に割引価格である必要があります。 | ## カスタム Android コード \{#custom-android-codes\} | エラー | コード | 説明 | |-----|----|-----------| | adaptyNotInitialized | 20 | `Adapty.activate` メソッドで Adapty SDK を正しく設定する必要があります。設定方法は [React Native 向けのガイド](sdk-installation-reactnative) を参照してください。 | | productNotFound | 22 | 購入リクエストされたプロダクトがストアで利用できないことを示します。 | | invalidJson | 23 | ペイウォールの JSON が無効です。Adapty ダッシュボードで修正してください。修正方法の詳細は [リモートコンフィグでペイウォールをカスタマイズする](customize-paywall-with-remote-config) を参照してください。 | | currentSubscriptionToUpdateNotFoundInHistory | 24 | 更新が必要な元のサブスクリプションが見つかりません。 | | pendingPurchase | 25 | 購入状態が「購入済み」ではなく「保留中」であることを示します。詳細は Android デベロッパー ドキュメントの [保留中のトランザクションの処理](https://developer.android.com/google/play/billing/integrate#pending) を参照してください。 | | billingServiceTimeout | 97 | Google Play が応答する前にリクエストが最大タイムアウトに達したことを示します。Play Billing Library の呼び出しで要求されたアクションの実行が遅延した場合などに発生します。 | | featureNotSupported | 98 | リクエストされた機能が現在のデバイスの Play Store でサポートされていません。 | | billingServiceDisconnected | 99 | `BillingClient` 経由でのクライアントアプリと Google Play Store サービスの接続が切断されたことを示す致命的なエラーです。 | | billingServiceUnavailable | 102 | Google Play Billing サービスが現在利用できないことを示す一時的なエラーです。ほとんどの場合、クライアントデバイスと Google Play Billing サービス間のどこかでネットワーク接続に問題があることを意味します。 | | billingUnavailable | 103 | <p>購入プロセス中にユーザーの課金エラーが発生したことを示します。発生する状況の例:</p><p></p><p>1. ユーザーのデバイスの Play Store アプリが古い。</p><p>2. ユーザーがサポート対象外の国にいる。</p><p>3. ユーザーがエンタープライズユーザーであり、エンタープライズ管理者が購入を無効にしている。</p><p>4. Google Play がユーザーの支払い方法に課金できない(クレジットカードの有効期限切れなど)。</p><p>5. ユーザーが Play Store アプリにログインしていない。</p> | | developerError | 105 | API の使い方が正しくないことを示す致命的なエラーです。 | | billingError | 106 | Google Play 内部の問題を示す致命的なエラーです。 | | itemAlreadyOwned | 107 | 消耗型アイテムがすでに購入済みです。 | | itemNotOwned | 108 | アイテムに対してリクエストされたアクションが失敗したことを示します。 | ## カスタム StoreKit コード \{#custom-storekit-codes\} | エラー | コード | 説明 | |-----|----|-----------| | noProductIDsFound | 1000 | <p>ペイウォール内のプロダクトがいずれもストアで利用できないことを示します。</p><p>このエラーが発生した場合は、以下の手順で解決してください:</p><p></p><p>1. すべてのプロダクトが Adapty ダッシュボードに追加されているか確認する。</p><p>2. アプリの Bundle ID が Apple Connect のものと一致しているか確認する。</p><p>3. アプリストアのプロダクト識別子がダッシュボードに追加したものと一致しているか確認する。識別子にはストアにすでに含まれている場合を除き、Bundle ID を含めないこと。</p><p>4. Apple の税務設定でアプリの有料ステータスがアクティブになっているか確認する。税務情報が最新であり、証明書が有効であることを確認する。</p><p>5. アプリに銀行口座が紐付けられており、収益化の対象になっているか確認する。</p><p>6. プロダクトがすべての地域で利用可能になっているか確認する。また、プロダクトのステータスが **"Ready to Submit"** になっていることを確認する。</p> | | productRequestFailed | 1002 | <p>現時点で利用可能なプロダクトを取得できません。考えられる原因:</p><p></p><p>- キャッシュがまだ作成されておらず、同時にインターネット接続もない。</p> | | cantMakePayments | 1003 | このデバイスではアプリ内課金が許可されていません。 | | noPurchasesToRestore | 1004 | Google Play が復元対象の購入を見つけられなかったことを示します。 | | cantReadReceipt | 1005 | <p>デバイス上に有効なレシートがありません。サンドボックステスト中に発生することがあります。</p><p>特に対応は不要ですが、ビジネスロジックの観点から、ユーザーに割引を提示したり、後でリマインドしたりすることができます。</p> | | productPurchaseFailed | 1006 | プロダクトの購入に失敗しました。このエラーは内部の StoreKit エラーをラップしています。実際の原因を確認するには、ラップされたエラーを読み取るか(または詳細ログを有効にしてコンソールで確認)してください。ラップされたエラーは通常、上記の StoreKit コード 0〜14 のいずれかで、最も多いのは `paymentCancelled`、`paymentInvalid`、`paymentNotAllowed`、`invalidOfferPrice` です。原因が特定できない場合は、新しい[サンドボックスプロファイル](test-purchases-in-sandbox)でお試しください。それでも解決しない場合は Apple サポートにお問い合わせください。 | | refreshReceiptFailed | 1010 | レシートが受信されなかったことを示します。StoreKit 1 のみ対象です。 | | receiveRestoredTransactionsFailed | 1011 | 購入の復元に失敗しました。 | ## カスタムネットワークコード \{#custom-network-codes\} | エラー | コード | 説明 | | :------------------- | :--- | :----------------------------------------------------------- | | notActivated | 2002 | `Adapty.activate` メソッドで Adapty SDK を正しく設定する必要があります。設定方法は [React Native 向けのガイド](sdk-installation-reactnative) を参照してください。 | | badRequest | 2003 | リクエストが不正です。 | | serverError | 2004 | サーバーエラーです。 | | networkFailed | 2005 | ネットワークリクエストに失敗しました。 | | decodingFailed | 2006 | レスポンスのデコードに失敗したことを示します。 | | encodingFailed | 2009 | リクエストのエンコードに失敗したことを示します。 | | analyticsDisabled | 3000 | アナリティクスをオプトアウトしているため、アナリティクスイベントを処理できません。詳細は [アナリティクスインテグレーション](analytics-integration) を参照してください。 | | wrongParam | 3001 | パラメーターの一部が正しくないことを示します(空白にできない箇所が空白になっている、型が違うなど)。 | | activateOnceError | 3005 | `.activate` メソッドを複数回呼び出すことはできません。 | | profileWasChanged | 3006 | 操作中にユーザープロファイルが変更されました。 | | fetchTimeoutError | 3101 | 設定された制限時間内にペイウォールを取得できなかったことを示します。この状況を回避するには、[ローカルフォールバックを設定](fetch-paywalls-and-products)してください。 | | operationInterrupted | 9000 | この操作はシステムによって中断されました。 | --- # File: capacitor-sdk-migration-guides --- --- title: "Capacitor SDK Migration Guides" description: "Migration guides for Adapty Capacitor SDK versions." --- This page contains all migration guides for Adapty Capacitor SDK. Choose the version you want to migrate to for detailed instructions: - [**Migrate to v3.16**](migration-to-capacitor-316) --- # File: migration-to-capacitor-316 --- --- title: "Adapty Capacitor SDK を v3.16 に移行する" description: "より良いパフォーマンスと新しいマネタイズ機能のために Adapty Capacitor SDK v3.16 に移行します。" --- Adapty SDK v3.16.0 以降、Capacitor 8 が必要です。Capacitor 7 を使用する場合は、Adapty SDK v3.15 をご利用ください。 Capacitor SDK v3.16 にアップグレードするには、プロジェクトが Capacitor 8 を使用していることを確認してください。まだ Capacitor 7 を使用している場合は、次の 2 つの選択肢があります。 1. **Capacitor 8 にアップグレードする**: [公式 Capacitor 移行ガイド](https://capacitorjs.com/docs/updating/8-0)に従ってプロジェクトを更新し、Adapty SDK v3.16 をインストールします。 2. **Adapty SDK v3.15 を使い続ける**: Capacitor 8 へのアップグレードが難しい場合は、Capacitor 7 をサポートする Adapty SDK v3.15 を引き続き使用してください。 --- # End of Documentation _Generated on: 2026-06-24T14:36:28.495Z_ _Successfully processed: 43/43 files_ # FLUTTER - Adapty Documentation (Full Content) This file contains the complete content of all documentation pages for this platform. Locale: ja Generated on: 2026-06-24T14:36:28.497Z Total files: 41 --- # File: sdk-installation-flutter --- --- title: "Flutter SDK のインストールと設定" description: "サブスクリプション型アプリ向けに Flutter へ Adapty SDK をインストールするためのステップバイステップガイド。" --- Adapty SDK には、Flutter アプリへのシームレスな統合を実現する 2 つの主要モジュールが含まれています。 - **Core Adapty**: Adapty をアプリで正しく動作させるために必須の SDK です。 - **AdaptyUI**: クロスプラットフォームのペイウォールを簡単に作成できるノーコードツール、[Adapty ペイウォールビルダー](adapty-paywall-builder)を使用する場合に必要なモジュールです。 :::tip Adapty SDK をモバイルアプリに統合した実際の例を見てみませんか?ペイウォールの表示や購入フローなど基本的な機能の完全なセットアップを示した[サンプルアプリ](https://github.com/adaptyteam/AdaptySDK-Flutter/tree/master/example)をご確認ください。 ::: ## 動作要件 \{#requirements\} Adapty SDK は iOS 13.0 以降をサポートしていますが、ペイウォールビルダーで作成したペイウォールを正しく表示するには iOS 15.0 以降が必要です。 :::info Adapty は Google Play Billing Library 8.x までに対応しています。デフォルトでは Google Play Billing Library v7.0.0 を使用しますが、より新しいバージョンを使用したい場合は、手動で[依存関係を追加](https://developer.android.com/google/play/billing/integrate#dependency)できます。 ::: --- no_index: true --- import Callout from '../../../components/Callout.astro'; <Callout type="info"> SDKのインストールは、Adaptyセットアップのステップ5です。アプリ内で課金が機能するようにするには、アプリをストアに接続し、Adapty ダッシュボードでプロダクト、ペイウォール、プレースメントを作成する必要があります。[クイックスタートガイド](quickstart)では、必要なすべての手順を説明しています。 </Callout> ## Adapty SDK のインストール \{#install-adapty-sdk\} [![Release](https://img.shields.io/github/v/release/adaptyteam/AdaptySDK-Flutter.svg?style=flat&logo=flutter)](https://github.com/adaptyteam/AdaptySDK-Flutter/releases) 1. `pubspec.yaml` ファイルに Adapty を追加します: ```yaml showLineNumbers title="pubspec.yaml" dependencies: adapty_flutter: ^<the latest SDK version> ``` 2. 以下のコマンドを実行して依存関係をインストールします: ```bash showLineNumbers title="Terminal" flutter pub get ``` 3. アプリケーションに Adapty SDK をインポートします: ```dart showLineNumbers title="main.dart" import 'package:adapty_flutter/adapty_flutter.dart'; ``` ## Adapty SDK の Adapty モジュールを有効化する \{#activate-adapty-module-of-adapty-sdk\} アプリのコードで Adapty SDK を有効化します。 :::note Adapty SDK の有効化は、アプリ内で一度だけ行う必要があります。 ::: **Public SDK Key** を取得するには: 1. Adapty ダッシュボードを開き、[**App settings → General**](https://app.adapty.io/settings/general) に移動します。 2. **Api keys** セクションから **Public SDK Key**(Secret Key ではない方)をコピーします。 3. コード内の `"YOUR_PUBLIC_SDK_KEY"` を置き換えます。 :::important - Adapty の初期化には必ず **Public SDK key** を使用してください。**Secret key** は[サーバーサイド API](getting-started-with-server-side-api) 専用です。 - **SDK keys** はアプリごとに固有です。複数のアプリがある場合は、正しいキーを選択してください。 ::: ```dart showLineNumbers title="main.dart" void main() { runApp(MyApp()); } class MyApp extends StatefulWidget { @override _MyAppState createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { @override void initState() { _initializeAdapty(); super.initState(); } Future<void> _initializeAdapty() async { try { await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_PUBLIC_SDK_KEY'), ); } catch (e) { // handle the error } } Widget build(BuildContext context) { return Text("Hello"); } } ``` :::important 他の Adapty SDK メソッドを呼び出す前に、`activate` の完了を待ってください。完全な呼び出し順序については [Flutter SDK の呼び出し順序](flutter-sdk-call-order)を参照してください。 ::: 次に、アプリにペイウォールを設定します: - [Adapty ペイウォールビルダー](adapty-paywall-builder)を使用する場合は、まず下記の [AdaptyUI モジュールの有効化](#activate-adaptyui-module-of-adapty-sdk)を行い、その後[ペイウォールビルダーのクイックスタート](flutter-quickstart-paywalls)に進んでください。 - 独自のペイウォール UI を構築する場合は、[カスタムペイウォールのクイックスタート](flutter-quickstart-manual)を参照してください。 ## Adapty SDK の AdaptyUI モジュールを有効化する \{#activate-adaptyui-module-of-adapty-sdk\} [ペイウォールビルダー](adapty-paywall-builder)を使用する予定があり、[AdaptyUI モジュールをインストール](sdk-installation-flutter#install-adapty-sdk)済みの場合は、AdaptyUI も有効化する必要があります: :::note AdaptyUI に関連する依存関係は、AdaptyUI が有効化されているかどうかに関わらずアプリにリンクされます。 ::: :::important コード内では、AdaptyUI を有効化する前に必ずコアの Adapty モジュールを有効化してください。 ::: ```dart showLineNumbers title="main.dart" await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_PUBLIC_SDK_KEY') ..withActivateUI(true), // This automatically activates AdaptyUI ); ``` ## オプション設定 \{#optional-setup\} ### ログ \{#logging\} #### ログシステムを設定する \{#set-up-the-logging-system\} Adapty は、状況を把握するためにエラーやその他の重要な情報をログに記録します。利用可能なログレベルは以下のとおりです: | レベル | 説明 | | :----------------------- | :------------------------------------------------------------------------------------------------------------------------ | | `AdaptyLogLevel.none` | 何もログに記録されません。デフォルト値 | | `AdaptyLogLevel.error` | エラーのみログに記録されます | | `AdaptyLogLevel.warn` | 重大なエラーは発生しないものの注意が必要な SDK からのエラーとメッセージがログに記録されます。 | | `AdaptyLogLevel.info` | エラー、警告、およびさまざまな情報メッセージがログに記録されます。 | | `AdaptyLogLevel.verbose` | 関数呼び出しや API クエリなど、デバッグ時に役立つ追加情報がすべてログに記録されます。 | Adapty を設定する前に、アプリ内でログレベルを設定できます: ```dart showLineNumbers title="main.dart" // Set log level before activation. // 'verbose' is recommended for development and the first production release await Adapty().setLogLevel(AdaptyLogLevel.verbose); // Or set it during configuration await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_PUBLIC_SDK_KEY') ..withLogLevel(AdaptyLogLevel.verbose), ); ``` ### データポリシー \{#data-policies\} Adapty は明示的に送信しない限りユーザーの個人データを保存しませんが、ストアや各国のガイドラインに準拠するために追加のデータセキュリティポリシーを実装することができます。 #### IP アドレスの収集と共有を無効化する \{#disable-ip-address-collection-and-sharing\} Adapty モジュールを有効化する際に、`ipAddressCollectionDisabled` を `true` に設定することで、ユーザーの IP アドレスの収集と共有を無効化できます。デフォルト値は `false` です。 このパラメータは、ユーザープライバシーの強化、GDPR や CCPA などの地域のデータ保護規制への準拠、または IP ベースの機能がアプリに不要な場合の不必要なデータ収集の削減に活用できます。 ```dart showLineNumbers title="main.dart" await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_PUBLIC_SDK_KEY') ..withIpAddressCollectionDisabled(true), ); ``` #### 広告 ID の収集と共有を無効化する \{#disable-advertising-id-collection-and-sharing\} Adapty モジュールを有効化する際に、`appleIdfaCollectionDisabled`(iOS)または `googleAdvertisingIdCollectionDisabled`(Android)を `true` に設定することで、広告識別子の収集を無効化できます。デフォルト値は `false` です。 このパラメータは、App Store / Play Store のポリシーへの準拠、App Tracking Transparency プロンプトの表示回避、または広告 ID に基づく広告アトリビューションや分析をアプリが必要としない場合に活用できます。 ```dart showLineNumbers title="main.dart" await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_PUBLIC_SDK_KEY') ..withAppleIdfaCollectionDisabled(true) // iOS ..withGoogleAdvertisingIdCollectionDisabled(true), // Android ); ``` #### AdaptyUI のメディアキャッシュ設定を行う \{#set-up-media-cache-configuration-for-adaptyui\} モジュールは Adapty SDK と共に自動的に有効化されます。ペイウォールビルダーを使用しない場合に AdaptyUI モジュールを無効化したいときは、有効化時に `withActivateUI(false)` を渡してください。 デフォルトでは、AdaptyUI はパフォーマンス向上とネットワーク使用量削減のために、画像や動画などのメディアをキャッシュします。カスタム設定を指定することでキャッシュの設定をカスタマイズできます。 `withMediaCacheConfiguration` を使用して、デフォルトのキャッシュサイズと有効期間を上書きできます。これはオプションです。このメソッドを呼び出さない場合、デフォルト値(ディスクサイズ 100MB、メモリカウント無制限)が使用されます。ただし、設定を使用する場合はすべてのパラメータを含める必要があります。 ```dart showLineNumbers title="main.dart" final mediaCacheConfig = AdaptyUIMediaCacheConfiguration( memoryStorageTotalCostLimit: 200 * 1024 * 1024, // 200 MB memoryStorageCountLimit: 2147483647, // max int value diskStorageSizeLimit: 200 * 1024 * 1024, // 200 MB ); await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_PUBLIC_SDK_KEY') ..withMediaCacheConfiguration(mediaCacheConfig), ); ``` **パラメータ:** | パラメータ | 必須 | 説明 | |-------------------------|----------|-----------------------------------------------------------------------------| | memoryStorageTotalCostLimit | オプション | メモリ上のキャッシュの合計サイズ(バイト単位)。デフォルトは 100 MB。 | | memoryStorageCountLimit | オプション | メモリストレージのアイテム数の上限。デフォルトは int の最大値。 | | diskStorageSizeLimit | オプション | ディスク上のファイルサイズの上限(バイト単位)。デフォルトは 100 MB。 | ### ローカルアクセスレベルを有効化する(Android) \{#enable-local-access-levels-android\} デフォルトでは、[ローカルアクセスレベル](local-access-levels)は iOS で有効、Android で無効になっています。Android でも有効化するには、`withGoogleLocalAccessLevelAllowed` を `true` に設定します: ```dart showLineNumbers title="main.dart" await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_PUBLIC_SDK_KEY') ..withGoogleLocalAccessLevelAllowed(true), ); ``` ### バックアップ復元時のデータ消去 \{#clear-data-on-backup-restore\} `clearDataOnBackup` を `true` に設定すると、iCloud バックアップからアプリが復元されたことを SDK が検知し、キャッシュされたプロファイル情報、プロダクト詳細、ペイウォールなど、ローカルに保存されたすべての SDK データを削除します。その後、SDK はクリーンな状態で初期化されます。デフォルト値は `false` です。 :::note 削除されるのはローカルの SDK キャッシュのみです。Apple とのトランザクション履歴および Adapty サーバー上のユーザーデータは変更されません。 ::: ```dart showLineNumbers title="main.dart" await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_PUBLIC_SDK_KEY') ..withClearDataOnBackup(true) // default – false ); ``` ## トラブルシューティング \{#troubleshooting\} #### Android バックアップルール(Auto Backup 設定) \{#android-backup-rules-auto-backup-configuration\} 一部のSDK(Adaptyを含む)には、独自のAndroid Auto Backup設定が含まれています。バックアップルールを定義する複数のSDKを使用している場合、Androidのマニフェストマージャーが `android:fullBackupContent`、`android:dataExtractionRules`、または `android:allowBackup` に関するエラーで失敗することがあります。 よくあるエラーの症状: `Manifest merger failed: Attribute application@dataExtractionRules value=(@xml/your_data_extraction_rules) is also present at [com.other.sdk:library:1.0.0] value=(@xml/other_sdk_data_extraction_rules)` :::note これらの変更は、Androidプラットフォームのディレクトリ(通常はプロジェクトの `android/` フォルダー内)で行う必要があります。 ::: この問題を解決するには、以下が必要です: - バックアップ関連の属性に対して、アプリの値を使用するようマニフェストマージャーに指示する。 - AdaptyのルールとほかのSDKのルールをマージしたバックアップルールファイルを作成する。 #### 1. マニフェストに `tools` 名前空間を追加する \{#1-add-the-tools-namespace-to-your-manifest\} `AndroidManifest.xml` ファイルのルートの `<manifest>` タグに tools が含まれていることを確認してください: ```xml <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="com.example.app"> ... </manifest> ``` #### 2. `<application>` でバックアップ属性を上書きする \{#2-override-backup-attributes-in-application\} 同じ `AndroidManifest.xml` ファイルで、`<application>` タグを更新して、アプリが最終的な値を提供し、マニフェストマージャーにライブラリの値を置き換えるよう指示します: ```xml <application android:name=".App" android:allowBackup="true" android:fullBackupContent="@xml/sample_backup_rules" android:dataExtractionRules="@xml/sample_data_extraction_rules" tools:replace="android:fullBackupContent,android:dataExtractionRules"> ... </application> ``` いずれかのSDKが `android:allowBackup` も設定している場合は、`tools:replace` に含めてください: ```xml tools:replace="android:allowBackup,android:fullBackupContent,android:dataExtractionRules" ``` #### 3. マージしたバックアップルールファイルを作成する \{#3-create-merged-backup-rules-files\} AndroidプロジェクトのAdaptyのルールとほかのSDKのルールを組み合わせた `res/xml/` ディレクトリにXMLファイルを作成します。AndroidはOSのバージョンによって異なるバックアップルール形式を使用するため、両方のファイルを作成することで、アプリがサポートするすべてのAndroidバージョンとの互換性が確保されます。 :::note 以下の例では、サンプルのサードパーティSDKとしてAppsFlyerを使用しています。アプリで使用しているほかのSDKのルールに置き換えるか、追加してください。 ::: **Android 12以降**(新しいデータ抽出ルール形式を使用): ```xml title="sample_data_extraction_rules.xml" <?xml version="1.0" encoding="utf-8"?> <data-extraction-rules> <cloud-backup> <exclude domain="sharedpref" path="appsflyer-data"/> <exclude domain="sharedpref" path="appsflyer-purchase-data"/> <exclude domain="database" path="afpurchases.db"/> <exclude domain="sharedpref" path="AdaptySDKPrefs.xml"/> </cloud-backup> <device-transfer> <exclude domain="sharedpref" path="appsflyer-data"/> <exclude domain="sharedpref" path="appsflyer-purchase-data"/> <exclude domain="database" path="afpurchases.db"/> <exclude domain="sharedpref" path="AdaptySDKPrefs.xml"/> </device-transfer> </data-extraction-rules> ``` **Android 11以前**(従来のフルバックアップコンテンツ形式を使用): ```xml title="sample_backup_rules.xml" <?xml version="1.0" encoding="utf-8"?> <full-backup-content> <exclude domain="sharedpref" path="appsflyer-data"/> <exclude domain="sharedpref" path="AdaptySDKPrefs.xml"/> #### Android で別のアプリから戻った後に購入が失敗する \{#purchases-fail-after-returning-from-another-app-in-android\} 購入フローを開始する Activity が非デフォルトの `launchMode` を使用している場合、ユーザーが Google Play、銀行アプリ、またはブラウザから戻ったときに Android が Activity を誤って再作成または再利用することがあります。これにより、購入結果が失われたり、キャンセルとして処理されたりする場合があります。 購入が正しく機能するようにするには、購入フローを開始する Activity に `standard` または `singleTop` の起動モードのみを使用し、その他のモードは避けてください。 `AndroidManifest.xml` で、購入フローを開始する Activity の起動モードが `standard` または `singleTop` に設定されていることを確認してください: ```xml <activity android:name=".MainActivity" android:launchMode="standard" /> ``` #### Podfile の SWIFT_VERSION オーバーライドが原因で発生する Swift 6 ビルドエラー \{#swift-6-build-errors-caused-by-podfile-swift_version-override\} iOS 向けに Flutter アプリをビルドする際、Adapty pod ターゲットで Swift 6 のコンパイルエラーが発生することがあります。よくある症状としては、`AdaptyUIBuilderLogic` での `@Sendable` の不一致、Adapty 型への `Sendable` 適合の欠如、またはアクター隔離エラーなどがあります。 Adapty の pod は `s.swift_version = '6.0'` を宣言しており、ビルドに Swift 6 が必要です。アプリ独自のコードは Swift 5 のままで構いません。Swift 6 でビルドする必要があるのは Adapty の pod ターゲット(`Adapty`、`AdaptyUI`、`AdaptyUIBuilder`、`AdaptyLogger`、`AdaptyPlugin`)のみです。 最もよくある原因は、`ios/Podfile` の `post_install` フックがすべての pod ターゲットの `SWIFT_VERSION` を上書きしていることです: ```ruby showLineNumbers title="ios/Podfile" post_install do |installer| installer.pods_project.targets.each do |target| target.build_configurations.each do |config| config.build_settings['SWIFT_VERSION'] = '5.9' end end end ``` **修正方法**: Adapty の pod ターゲットをオーバーライドの対象から除外します: ```ruby showLineNumbers title="ios/Podfile" post_install do |installer| installer.pods_project.targets.each do |target| next if %w[Adapty AdaptyUI AdaptyUIBuilder AdaptyLogger AdaptyPlugin].include?(target.name) target.build_configurations.each do |config| config.build_settings['SWIFT_VERSION'] = '5.9' end end end ``` その後、`ios/` ディレクトリで `pod install` を実行してリビルドしてください。 確認するには、`ios/Pods/Pods.xcodeproj` を開き、`Adapty` の pod ターゲットを選択して **Build Settings** → **Swift Language Version** を確認します。**Swift 6** と表示されているはずです。 --- # File: flutter-quickstart-paywalls --- --- title: "Flutter SDKでペイウォールを使って課金を有効にする" description: "アプリ内サブスクリプション管理のためのAdaptyセットアップクイックスタートガイド。" --- アプリ内課金を有効にするには、3つの重要な概念を理解する必要があります: - [**プロダクト**](product) – ユーザーが購入できるもの(サブスクリプション、消耗型アイテム、永続アクセス) - [**ペイウォール**](paywalls) – どのプロダクトを提供するかを定義する設定です。Adaptyでは、ペイウォールがプロダクトを取得する唯一の方法ですが、この設計によりアプリのコードを変更せずにオファー内容や価格、プロダクトの組み合わせを変更できます。 - [**プレースメント**](placements) – アプリ内でペイウォールをどこでいつ表示するか(`main`、`onboarding`、`settings` など)。ダッシュボードでプレースメントにペイウォールを設定し、コードからはプレースメントIDで取得します。これにより、A/B テストの実施や異なるユーザーへの異なるペイウォール表示が簡単になります。 Adaptyには、アプリ内課金を有効にする3つの方法があります。アプリの要件に応じて選択してください: | 実装方法 | 複雑さ | 使用タイミング | |------------------------|------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Adapty ペイウォールビルダー | ✅ 簡単 | [ノーコードビルダーで完全な購入対応ペイウォールを作成](quickstart-paywalls)します。Adaptyが自動的にレンダリングし、複雑な購入フロー、レシート検証、サブスクリプション管理をすべて裏側で処理します。 | | 手動作成のペイウォール | 🟡 中程度 | ペイウォールのUIはアプリのコードで実装しますが、プロダクトオファーの柔軟性を保つためにAdaptyからペイウォールオブジェクトを取得します。[ガイド](flutter-quickstart-manual)をご覧ください。 | | オブザーバーモード | 🔴 難しい | 独自の購入処理インフラがすでにあり、それを引き続き使用したい場合。オブザーバーモードにはAdaptyでの制限があることに注意してください。[記事](observer-vs-full-mode)をご覧ください。 | :::important **以下の手順は、Adaptyのペイウォールビルダーで作成したペイウォールの実装方法を説明しています。** ペイウォールビルダーを使用しない場合は、[手動作成ペイウォールでの購入処理ガイド](flutter-making-purchases)をご覧ください。 ::: Adaptyのペイウォールビルダーで作成したペイウォールを表示するには、アプリのコードで以下のことだけが必要です: 1. **ペイウォールを取得する**: Adaptyからペイウォールを取得します。 2. **ペイウォールを表示するとAdaptyが購入を処理します**: 取得したペイウォールコンテナをアプリに表示します。 3. **ボタンアクションを処理する**: ペイウォールのユーザー操作とアプリのレスポンスを関連付けます。例えば、ユーザーがボタンをクリックした際にリンクを開いたりペイウォールを閉じたりします。 ## 始める前に \{#before-you-start\} 始める前に、以下の手順を完了してください: 1. Adapty ダッシュボードで [App Store](initial_ios) および/または [Google Play](initial-android) にアプリを接続します。 2. Adaptyで[プロダクトを作成](create-product)します。 3. [ペイウォールを作成してプロダクトを追加](create-paywall)します。 4. [プレースメントを作成してペイウォールを追加](create-placement)します。 5. アプリのコードに [Adapty SDKをインストールして有効化](sdk-installation-flutter)します。 :::tip これらの手順を最速で完了するには、[クイックスタートガイド](quickstart)に従うか、[Developer CLI](developer-cli-quickstart)を使用してペイウォールとプレースメントを作成してください。 ::: ## 1. ペイウォールを取得する \{#1-get-the-paywall\} ペイウォールはダッシュボードで設定されたプレースメントに紐づいています。プレースメントを使うことで、異なるオーディエンスに異なるペイウォールを表示したり、[A/B テスト](ab-tests)を実施したりできます。 Adaptyのペイウォールビルダーで作成したペイウォールを取得するには、以下の手順が必要です: 1. `getPaywall` メソッドを使って[プレースメント](placements)IDで `paywall` オブジェクトを取得し、`hasViewConfiguration` プロパティを使ってビルダーで作成したペイウォールかどうかを確認します。 2. `createPaywallView` メソッドを使ってペイウォールビューを作成します。ビューにはペイウォールを表示するために必要なUI要素とスタイリングが含まれています。 :::important ビュー設定を取得するには、ペイウォールビルダーで **Show on device** トグルをオンにする必要があります。オフのままだと空のビュー設定が返され、ペイウォールが表示されません。 ::: ```dart showLineNumbers try { final paywall = await Adapty().getPaywall(placementId: "YOUR_PLACEMENT_ID", locale: "en"); // the requested paywall } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } try { final view = await AdaptyUI().createPaywallView( paywall: paywall, ); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` ## 2. ペイウォールを表示する \{#2-display-the-paywall\} ペイウォールの設定が取得できたら、数行追加するだけでペイウォールを表示できます。 ペイウォールを表示するには、`createPaywallView` メソッドで作成した `view` に対して `view.present()` メソッドを使用します。各 `view` は一度しか使用できません。再度ペイウォールを表示する必要がある場合は、`createPaywallView` をもう一度呼び出して新しい `view` インスタンスを作成してください。 ```dart showLineNumbers title="Flutter" try { await view.present(); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` :::tip ペイウォールの表示方法の詳細については、[ガイド](flutter-present-paywalls)をご覧ください。 ::: ## 3. ボタンアクションを処理する \{#3-handle-button-actions\} ユーザーがペイウォール上のボタンをクリックすると、Flutter SDKは購入と復元を自動的に処理します。ただし、その他のボタンにはカスタムまたは事前定義されたIDがあり、コードでアクションを処理する必要があります。 ペイウォール画面上のプロセスを制御・監視するには、`AdaptyUIPaywallsEventsObserver` のメソッドを実装し、画面を表示する前にオブザーバーを設定します。ユーザーが何らかのアクションを実行すると `paywallViewDidPerformAction` が呼び出されるため、アプリはアクションIDに応じて応答する必要があります。 例えば、ペイウォールには通常、閉じるボタンや開くURLが含まれています(利用規約やプライバシーポリシーなど)。そのため、`Close` と `OpenUrl` のIDを持つアクションに応答する必要があります。 :::tip ボタンの[アクション](flutter-handle-paywall-actions)と[イベント](flutter-handling-events)の処理方法については、ガイドをご覧ください。 ::: ```dart showLineNumbers title="Flutter" class _PaywallScreenState extends State<PaywallScreen> implements AdaptyUIPaywallsEventsObserver { @override void initState() { super.initState(); // Register this class as the paywalls event observer AdaptyUI().setPaywallsEventsObserver(this); } // This method is called when user performs an action on the paywall UI @override void paywallViewDidPerformAction(AdaptyUIPaywallView view, AdaptyUIAction action) { switch (action) { case const CloseAction(): case const AndroidSystemBackAction(): view.dismiss(); break; case OpenUrlAction(url: final url): // Open the URL using url_launcher package _launchUrl(url); break; } } // Helper method to launch URLs Future<void> _launchUrl(String url) async { try { final Uri uri = Uri.parse(url); if (await canLaunchUrl(uri)) { await launchUrl(uri, mode: LaunchMode.externalApplication); } else { // Handle case where URL cannot be launched print('Could not launch $url'); } } catch (e) { // Handle any errors print('Error launching URL: $e'); } } } ``` ## 次のステップ \{#next-steps\} --- no_index: true --- import Callout from '../../../components/Callout.astro'; <Callout type="tip"> ご質問やお困りのことがあれば、[サポートフォーラム](https://adapty.featurebase.app/)をご覧ください。よくある質問への回答を見つけたり、ご自身の質問を投稿することができます。チームとコミュニティがサポートいたします! </Callout> ペイウォールはアプリに表示する準備が整いました。[App Store サンドボックス](test-purchases-in-sandbox)または[Google Play Store](testing-on-android)でテスト購入を試して、ペイウォールからテスト購入が完了できることを確認してください。 次に、[ユーザーのアクセスレベルを確認](flutter-check-subscription-status)して、適切なユーザーにペイウォールを表示したり有料機能へのアクセスを付与したりできるようにする必要があります。 ## 完全な実装例 \{#full-example\} これらのすべてのステップをアプリにまとめて統合する方法を示します。 ```dart void main() async { runApp(MaterialApp(home: PaywallScreen())); } class PaywallScreen extends StatefulWidget { @override State<PaywallScreen> createState() => _PaywallScreenState(); } class _PaywallScreenState extends State<PaywallScreen> implements AdaptyUIPaywallsEventsObserver { @override void initState() { super.initState(); // Register this class as the paywalls event observer AdaptyUI().setPaywallsEventsObserver(this); _showPaywallIfNeeded(); } Future<void> _showPaywallIfNeeded() async { try { final paywall = await Adapty().getPaywall( placementId: 'YOUR_PLACEMENT_ID', ); if (!paywall.hasViewConfiguration) return; final view = await AdaptyUI().createPaywallView(paywall: paywall); await view.present(); } catch (_) { // Handle any errors (network, SDK issues, etc.) } } // This method is called when user performs an action on the paywall UI @override void paywallViewDidPerformAction(AdaptyUIPaywallView view, AdaptyUIAction action) { switch (action) { case const CloseAction(): case const AndroidSystemBackAction(): view.dismiss(); break; case OpenUrlAction(url: final url): // Open the URL using url_launcher package _launchUrl(url); break; } } // Helper method to launch URLs Future<void> _launchUrl(String url) async { try { final Uri uri = Uri.parse(url); if (await canLaunchUrl(uri)) { await launchUrl(uri, mode: LaunchMode.externalApplication); } else { // Handle case where URL cannot be launched print('Could not launch $url'); } } catch (e) { // Handle any errors print('Error launching URL: $e'); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Adapty Paywall Example')), body: Center( // Add a button to re-trigger the paywall for testing purposes child: ElevatedButton( onPressed: _showPaywallIfNeeded, child: Text('Show Paywall'), ), ), ); } } ``` --- # File: flutter-check-subscription-status --- --- title: "Flutter SDKでサブスクリプションステータスを確認する" description: "AdaptyでFlutterアプリのサブスクリプションステータスを確認する方法を学びましょう。" --- 有料コンテンツへのアクセスやペイウォールの表示を判断するには、プロファイルの[アクセスレベル](access-level)を確認する必要があります。 この記事では、プロファイルの状態を取得して、ペイウォールを表示するか有料機能へのアクセスを許可するかを判断する方法を説明します。 ## サブスクリプションステータスを取得する \{#get-subscription-status\} ユーザーにペイウォールを表示するか有料コンテンツを見せるかを判断する際には、プロファイルの[アクセスレベル](access-level)を確認します。方法は2つあります。 - アプリ起動時など、最新のプロファイルデータをすぐに取得したい場合や強制更新したい場合は `getProfile` を呼び出す。 - **プロファイルの自動更新**を設定して、サブスクリプションステータスが変わるたびにローカルコピーを自動的に更新する。 ### プロファイルを取得する \{#get-profile\} サブスクリプションステータスを取得する最もシンプルな方法は、`getProfile` メソッドを使ってプロファイルにアクセスすることです。 ```javascript showLineNumbers try { final profile = await Adapty().getProfile(); // check the access } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` ### サブスクリプション更新をリッスンする \{#listen-to-subscription-updates\} アプリでプロファイルの更新を自動的に受け取るには: 1. `Adapty().didUpdateProfileStream.listen()` を使ってプロファイルの変更をリッスンします。ユーザーのサブスクリプションステータスが変わるたびに、Adaptyが自動的にこのメソッドを呼び出します。 2. このメソッドが呼ばれた際に更新されたプロファイルデータを保存しておくと、追加のネットワークリクエストなしにアプリ全体で利用できます。 ```dart class SubscriptionManager { AdaptyProfile? _currentProfile; SubscriptionManager() { // Listen for profile updates Adapty().didUpdateProfileStream.listen((profile) { _currentProfile = profile; // Update UI, unlock content, etc. }); } // Use stored profile instead of calling getProfile() bool hasAccess() { return _currentProfile?.accessLevels['premium']?.isActive ?? false; } } ``` :::note Adaptyはアプリ起動時にプロファイル更新ストリームのリスナーを自動的に呼び出し、デバイスがオフラインでもキャッシュされたサブスクリプションデータを提供します。 ::: ## プロファイルとペイウォールのロジックを連携する \{#connect-profile-with-paywall-logic\} ペイウォールを表示するか有料機能へのアクセスを許可するかを即座に判断する必要がある場合、ユーザーのプロファイルを直接確認できます。このアプローチは、アプリ起動時、プレミアムセクションへの入場時、特定コンテンツを表示する前など、様々なシナリオで役立ちます。 ```dart Future<bool> _checkAccessLevel() async { try { final profile = await Adapty().getProfile(); return profile.accessLevels['YOUR_ACCESS_LEVEL']?.isActive ?? false; } catch (e) { print('Error checking access level: $e'); return false; // Show paywall if access check fails } } Future<void> _initializePaywall() async { await _loadPaywall(); final hasAccess = await _checkAccessLevel(); if (!hasAccess) { // Show paywall if no access } } ``` ## 次のステップ \{#next-steps\} サブスクリプションステータスの追跡方法がわかったので、次は[ユーザープロファイルの操作](flutter-quickstart-identify)について学び、ユーザーが購入済みのコンテンツにアクセスできるようにしましょう。 --- # File: flutter-quickstart-identify --- --- title: "Flutter SDKでのユーザー識別" description: "FlutterでのアプリサブスクリプションのAdapty設定に関するクイックスタートガイド。" --- :::important このガイドは、独自の認証システムをお持ちの方向けです。ここでは、Adaptyのユーザープロファイルを既存の認証システムに合わせて管理する方法について説明します。 ::: ユーザーの購入管理方法は、アプリの認証モデルによって異なります: - バックエンド認証を使用しておらず、ユーザーデータも保存しないアプリの場合は、[匿名ユーザーに関するセクション](#anonymous-users)を参照してください。 - バックエンド認証がある(または予定している)アプリの場合は、[識別済みユーザーに関するセクション](#identified-users)を参照してください。 **主要な概念**: - **プロファイル**はSDKが動作するために必要なエンティティで、Adaptyが自動的に作成します。 - プロファイルは匿名(**カスタマーユーザーIDなし**)または識別済み(**カスタマーユーザーIDあり**)のいずれかです。 - **カスタマーユーザーID**を提供することで、Adaptyのプロファイルと内部認証システムをクロスリファレンスできます。 匿名ユーザーと識別済みユーザーの違いは以下の通りです: | | 匿名ユーザー | 識別済みユーザー | |-------------------------|---------------------------------------------------|-------------------------------------------------------------------------| | **購入管理** | ストアレベルの購入履歴復元 | カスタマーユーザーIDを通じてデバイス間で購入履歴を維持 | | **プロファイル管理** | 再インストールのたびに新しいプロファイルを作成 | セッションやデバイスをまたいで同じプロファイルを使用 | | **データ保持** | 匿名ユーザーのデータはアプリのインストールに紐づく | 識別済みユーザーのデータはアプリのインストールをまたいで保持される | ## 匿名ユーザー \{#anonymous-users\} バックエンド認証を使用していない場合、**アプリのコードで認証を処理する必要はありません**: 1. アプリの初回起動時にSDKが有効化されると、Adaptyは**ユーザー用の新しいプロファイルを作成**します。 2. ユーザーがアプリ内で何かを購入すると、その購入は**ユーザーのAdaptyプロファイルとストアアカウントに紐づけられます**。 3. ユーザーがアプリを**再インストール**したり、**新しいデバイス**にインストールしたりすると、Adaptyは**有効化時に新しい匿名プロファイルを作成**します。 4. ユーザーが以前にアプリ内で購入をしている場合、デフォルトでは、SDK有効化時にApp Storeから購入が自動的に同期されます。 匿名ユーザーの場合、インストールのたびに新しいプロファイルが作成されますが、Adaptyのアナリティクスで[新しいインストールとして扱われる条件を設定](general#4-installs-definition-for-analytics)できるため、問題ありません。 匿名ユーザーの場合、**デバイスID**でインストールをカウントする必要があります。この場合、再インストールを含め、デバイスへのアプリのインストールそれぞれが1回のインストールとしてカウントされます。 ## 識別済みユーザー \{#identified-users\} ユーザーを識別するには2つの方法があります: - [**ログイン・サインアップ時:**](#during-loginsignup) アプリ起動後にユーザーがサインインする場合は、認証時に`identify()`をカスタマーユーザーIDと共に呼び出します。 - [**SDK有効化時:**](#during-the-sdk-activation) アプリ起動時にすでにカスタマーユーザーIDが保存されている場合は、`activate()`の呼び出し時に送信します。 :::important デフォルトでは、Adaptyが現在別のカスタマーユーザーIDに紐づいているカスタマーユーザーIDからの購入を受け取った場合、アクセスレベルは共有されるため、両方のプロファイルが有料アクセスを持つことになります。この設定を変更して、有料アクセスを一方のプロファイルから別のプロファイルに移譲したり、共有を完全に無効にしたりできます。詳細は[こちらの記事](general#6-sharing-paid-access-between-user-accounts)を参照してください。 ::: <img src="/assets/shared/img/identify-diagram.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### ログイン・サインアップ時 \{#during-loginsignup\} アプリ起動後にユーザーを識別する場合(例:ログインやサインアップ後)は、`identify`メソッドを使用してカスタマーユーザーIDを設定します。 - **このカスタマーユーザーIDを使用したことがない場合**、Adaptyは自動的に現在のプロファイルに紐づけます。 - **以前にこのカスタマーユーザーIDでユーザーを識別したことがある場合**、AdaptyはそのカスタマーユーザーIDに関連するプロファイルに切り替えます。 :::important カスタマーユーザーIDは各ユーザーで一意でなければなりません。パラメーターの値をハードコードすると、すべてのユーザーが同一人物として扱われます。 ::: 他のSDKメソッドを呼び出す前に、必ず`identify`を`await`してください。並列呼び出しをすると`#3006 profileWasChanged`が発生するか、匿名プロファイルに対して処理が行われます。詳しくは[Flutter SDKの呼び出し順序](flutter-sdk-call-order)を参照してください。 ```dart showLineNumbers try { await Adapty().identify(customerUserId); // Unique for each user } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` ### SDK有効化時 \{#during-the-sdk-activation\} SDKを有効化する時点でカスタマーユーザーIDがわかっている場合は、`identify`を別途呼び出す代わりに、`activate`メソッドに渡すことができます。 カスタマーユーザーIDがわかっていても有効化後に設定する場合、有効化時にAdaptyが新しい匿名プロファイルを作成し、`identify`を呼び出した後にのみ既存のプロファイルへ切り替わります。 既存のカスタマーユーザーID(以前に使用したもの)でも新しいものでも渡すことができます。新しいIDを渡すと、有効化時に作成された新しいプロファイルがそのカスタマーユーザーIDに自動的に紐づけられます。 :::note デフォルトでは、匿名プロファイルの作成はアナリティクスのダッシュボードに影響しません。インストールはデバイスIDに基づいてカウントされるためです。 デバイスIDはストアからデバイスへのアプリの1回のインストールを表し、アプリを再インストールした場合にのみ再生成されます。 初回インストールか再インストールかに関係なく、また既存のカスタマーユーザーIDを使用するかどうかにも依存しません。 プロファイルの作成(SDK有効化時またはログアウト時)、ログイン、またはアプリの再インストールなしのアップグレードでは、追加のインストールイベントは生成されません。 デバイスではなく一意のユーザーを基準にインストールをカウントしたい場合は、**App settings**に移動して[**Installs definition for analytics**](general#4-installs-definition-for-analytics)を設定してください。 ::: ```dart showLineNumbers" try { await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_API_KEY') ..withCustomerUserId(YOUR_CUSTOMER_USER_ID) // Customer user IDs must be unique for each user. If you hardcode the parameter value, all users will be considered as one. ); } catch (e) { // handle the error } ``` ### ユーザーのログアウト \{#log-users-out\} ユーザーをログアウトさせるボタンがある場合は、`logout`メソッドを使用します。 :::important ユーザーをログアウトすると、そのユーザーに対して新しい匿名プロファイルが作成されます。 ::: ```dart showLineNumbers try { await Adapty().logout(); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle unknown error } ``` :::info ユーザーをアプリに再度ログインさせるには、`identify`メソッドを使用してください。 ::: ### ログインなしで購入を許可する \{#allow-purchases-without-login\} ユーザーがアプリにログインする前後の両方で購入できる場合、ログイン後もアクセスが維持されるよう対応する必要があります: 1. ログアウト中のユーザーが購入を行うと、AdaptyはそれをユーザーのAnonymous Profile IDに紐づけます。 2. ユーザーがアカウントにログインすると、Adaptyは識別済みプロファイルへの切り替えを行います。 - 新しいカスタマーユーザーIDの場合(例:登録前に購入が行われた場合)、Adaptyは現在のプロファイルにカスタマーユーザーIDを割り当てるため、購入履歴がすべて維持されます。 - 既存のカスタマーユーザーIDの場合(そのカスタマーユーザーIDがすでにプロファイルに紐づいている場合)、プロファイル切り替え後に実際のアクセスレベルを取得する必要があります。識別直後に[`getProfile`](flutter-check-subscription-status)を呼び出すか、[プロファイルの更新を購読](flutter-check-subscription-status)してデータが自動的に同期されるようにしてください。 ## 次のステップ \{#next-steps\} おめでとうございます!アプリにアプリ内決済のロジックを実装できました!アプリのマネタイズが成功することを願っています! Adaptyをさらに活用するために、以下のトピックを探索してみてください: - [**テスト**](troubleshooting-test-purchases):すべてが期待通りに動作することを確認する - [**オンボーディング**](flutter-onboardings):オンボーディングでユーザーを引き付けてリテンションを向上させる - [**インテグレーション**](configuration):マーケティングアトリビューションや分析サービスとワンラインで連携する - [**カスタムプロファイル属性の設定**](flutter-setting-user-attributes):ユーザープロファイルにカスタム属性を追加してセグメントを作成し、A/Bテストの実施や異なるユーザーへの異なるペイウォール表示を可能にする --- # File: adapty-sdk-integration-skill-flutter --- --- title: "SDK統合スキルを使ってFlutterアプリにAdaptyを導入する" description: "adapty-sdk-integrationスキルを使って、AIコーディングツールでFlutterアプリにAdapty SDKをエンドツーエンドで統合します。" --- :::important このスキルはベータ版です。処理が止まったり予期しない動作をした場合は、[ステップバイステップの統合ガイド](adapty-cursor-flutter)を参照してください。AIツールが各ステップを正しいドキュメントに沿って進められるよう案内しています。 ::: --- no_index: true --- [adapty-sdk-integration スキル](https://github.com/adaptyteam/adapty-sdk-integration-skill)は、Adapty のインテグレーションをエンドツーエンドで自動化します。ダッシュボードのセットアップ、SDK のインストール、ペイウォール、各ステージの検証まで対応しています。プラットフォームを自動検出し、各ステージで関連する Adapty ドキュメントを取得します。 **対応ツール**: Claude Code、GitHub Copilot CLI、OpenAI Codex、Gemini CLI。 インストールするには、お使いのツール向けのフォームを選択してください。完全なリストは[スキルの README](https://github.com/adaptyteam/adapty-sdk-integration-skill) をご覧ください。 **Claude Code** ``` claude plugin marketplace add adaptyteam/adapty-sdk-integration-skill claude plugin install adapty-sdk-integration@adapty ``` **GitHub Copilot CLI** ``` gh skill install adaptyteam/adapty-sdk-integration-skill ``` **Gemini CLI** ``` gemini skills install https://github.com/adaptyteam/adapty-sdk-integration-skill ``` **OpenAI Codex またはその他のツール**: リポジトリをクローンし、`plugins/adapty-sdk-integration/skills/adapty-sdk-integration/` をツールのスキルディレクトリにコピーしてください。 インストール後、プロジェクト内でスキルを実行します: ``` /adapty-sdk-integration ``` スキルがいくつかのセットアップ質問を行い、その後ダッシュボードのセットアップ、SDK のインストール、ペイウォール、検証の手順を案内します。 --- # File: adapty-cursor-flutter --- --- title: "AIアシスタントを使ってAdaptyをFlutterアプリに統合する" description: "Cursor、Context7、ChatGPT、Claude、その他のAIツールを使ってAdaptyをFlutterアプリに統合するステップバイステップガイド。" --- このガイドでは、AIコーディングツールを使ってAdaptyをFlutterアプリにステップバイステップで統合する方法を説明します。適切なAdaptyドキュメントを正しい順序でAIに渡していきます。 For a fully automated integration, use the [adapty-sdk-integration skill](https://github.com/adaptyteam/adapty-sdk-integration-skill): it runs the whole integration from your AI coding tool in one command. ## 始める前に:ダッシュボードの設定 \{#before-you-start-dashboard-setup\} AdaptyはSDKのコードを書く前に、ダッシュボードでいくつかの設定が必要です。インタラクティブなLLMスキルを使うか、ダッシュボードで手動設定するかを選べます。 ### スキルを使う方法(推奨) \{#skill-approach-recommended\} Adapty CLIスキルを使うと、LLMがダッシュボードを開かずに直接アプリ、プロダクト、アクセスレベル、ペイウォール、プレースメントを設定できます。必要なのは、ダッシュボードで[ストアを接続する](integrate-payments)ことだけです。 ``` npx skills add adaptyteam/adapty-cli --skill adapty-cli ``` スキルを追加したら、エージェントで `/adapty-cli` を実行します。ダッシュボードでストアを接続するタイミングも含め、各ステップをガイドしてくれます。 ### ダッシュボードを使う方法 \{#dashboard-approach\} 手動で設定したい場合は、コードを書く前に以下の手順を完了させてください。ダッシュボードの値はLLMが調べることはできないため、自分で用意する必要があります。 1. **ストアを接続する**: Adapty ダッシュボードで **App settings → General** に移動します。FlutterアプリがiOSとAndroidの両方を対象としている場合は、App StoreとGoogle Playの両方を接続してください。購入機能を動作させるために必要です。 [ストアを接続する](integrate-payments) 2. **Public SDKキーをコピーする**: Adapty ダッシュボードで **App settings → General** に移動し、**API keys** セクションを確認します。コードでは、このキーをAdapty設定に渡します。 3. **プロダクトを1つ以上作成する**: Adapty ダッシュボードで **Products** ページに移動します。コードでプロダクトを直接参照することはなく、Adaptyはペイウォールごしにプロダクトをデリバリーします。 [プロダクトを追加する](quickstart-products) 4. **ペイウォールとプレースメントを作成する**: Adapty ダッシュボードで **Paywalls** ページにペイウォールを作成し、**Placements** ページでプレースメントに割り当てます。コードでは、プレースメントIDを `Adapty().getPaywall()` に渡す文字列として使います。 [ペイウォールを作成する](quickstart-paywalls) 5. **アクセスレベルを設定する**: Adapty ダッシュボードの **Products** ページでプロダクトごとに設定します。コードでは `profile.accessLevels['premium']?.isActive` でチェックする文字列です。デフォルトの `premium` アクセスレベルはほとんどのアプリで使えます。プロダクトによって利用できる機能が異なる場合(たとえば `basic` プランと `pro` プラン)は、コーディングを始める前に[追加のアクセスレベルを作成](assigning-access-level-to-a-product)してください。 :::tip この5つが揃えばコードを書く準備は完了です。LLMに「Public SDKキーはX、プレースメントIDはY」と伝えることで、正確な初期化とペイウォール取得コードを生成してもらえます。 ::: ### 準備ができたら設定するもの \{#set-up-when-ready\} これらはコーディングを始めるために必須ではありませんが、統合が進むにつれて必要になります。 - **A/Bテスト**: **Placements** ページで設定します。コードの変更は不要です。 [A/Bテスト](ab-tests) - **追加のペイウォールとプレースメント**: 異なるプレースメントIDで `getPaywall` の呼び出しを追加します。 - **アナリティクス統合**: **Integrations** ページで設定します。統合によって手順が異なります。[アナリティクス統合](analytics-integration)および[アトリビューション統合](attribution-integration)を参照してください。 ## AdaptyドキュメントをLLMに渡す \{#feed-adapty-docs-to-your-llm\} ### Context7を使う(推奨) \{#use-context7-recommended\} [Context7](https://context7.com)は、LLMに最新のAdaptyドキュメントへの直接アクセスを提供するMCPサーバーです。質問内容に応じて適切なドキュメントをLLMが自動的に取得するため、URLを手動でペーストする必要はありません。 Context7は**Cursor**、**Claude Code**、**Windsurf**、その他のMCP対応ツールで動作します。セットアップするには次を実行します。 ``` npx ctx7 setup ``` これにより、エディタを自動検出してContext7サーバーを設定します。手動でのセットアップは[Context7 GitHubリポジトリ](https://github.com/upstash/context7)を参照してください。 設定が完了したら、プロンプトでAdaptyライブラリを参照します。 ``` Use the adaptyteam/adapty-docs library to look up how to install the Flutter SDK ``` :::warning Context7を使えばドキュメントリンクを手動でペーストする必要はなくなりますが、実装の順序は重要です。すべてが正しく動作するよう、以下の[実装ウォークスルー](#implementation-walkthrough)をステップごとに進めてください。 ::: ### プレーンテキストのドキュメントを使う \{#use-plain-text-docs\} AdaptyのドキュメントはプレーンテキストのMarkdownとして取得できます。URLの末尾に `.md` を追加するか、記事タイトルの下にある **Copy for LLM** をクリックしてください。例: [adapty-cursor-flutter.md](https://adapty.io/docs/ja/adapty-cursor-flutter.md) 以下の[実装ウォークスルー](#implementation-walkthrough)の各ステージには「LLMに送る」ブロックがあり、ペーストできる `.md` リンクが含まれています。 まとめて多くのドキュメントが必要な場合は、以下の[インデックスファイルとプラットフォーム別サブセット](#plain-text-doc-index-files)を参照してください。 ## 実装ウォークスルー \{#implementation-walkthrough\} このガイドの残りの部分では、実装の順序でAdaptyの統合を進めます。各ステージには、LLMに送るドキュメント、完了時に確認できること、よくある問題が含まれています。 ### 統合の計画を立てる \{#plan-your-integration\} コードを書き始める前に、LLMにプロジェクトを分析させて実装計画を作成してもらいましょう。AIツールに計画モード(CursorやClaude Codeのプランモードなど)がある場合は活用してください。コードを書く前にLLMがプロジェクト構造とAdaptyドキュメントの両方を読めます。 購入に使うアプローチをLLMに伝えてください。これにより、参照するガイドが変わります。 - [**Adapty ペイウォールビルダー**](adapty-paywall-builder): Adaptyのノーコードビルダーでペイウォールを作成し、SDKが自動的にレンダリングします。 - [**手動作成のペイウォール**](flutter-making-purchases): 独自のペイウォールUIをコードで構築しつつ、プロダクトの取得と購入処理にAdaptyを使います。 - [**オブザーバーモード**](observer-vs-full-mode): 既存の購入インフラをそのまま使い、アナリティクスと統合にのみAdaptyを使います。 どれを選べばよいかわからない場合は、[クイックスタートの比較表](flutter-quickstart-paywalls)を参照してください。 ### SDKのインストールと設定 \{#install-and-configure-the-sdk\} `flutter pub add` でAdapty SDKの依存関係を追加し、Public SDKキーで有効化します。これが基盤となり、ここなしには何も動きません。 **ガイド:** [Adapty SDKのインストールと設定](sdk-installation-flutter) LLMに送る内容: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/sdk-installation-flutter.md ``` :::tip[チェックポイント] - **期待される結果:** アプリがiOSとAndroidの両方でビルド・起動する。デバッグコンソールにAdaptyのアクティベーションログが表示される。 - **注意点:** 「Public API key is missing」→ プレースホルダーをApp settingsの実際のキーに置き換えたか確認する。 ::: ### ペイウォールの表示と購入の処理 \{#show-paywalls-and-handle-purchases\} プレースメントIDでペイウォールを取得し、表示して、購入イベントを処理します。必要なガイドは購入の処理方法によって異なります。 進める中でサンドボックスでの購入テストを都度行ってください。最後まで待たないようにしましょう。設定手順は[サンドボックスで購入テストする](test-purchases-in-sandbox)を参照してください。 <Tabs groupId="paywall-approach"> <TabItem value="builder" label="Paywall Builder" default> **ガイド:** - [ペイウォールを使って購入を有効にする(クイックスタート)](flutter-quickstart-paywalls) - [ペイウォールビルダーのペイウォールと設定を取得する](flutter-get-pb-paywalls) - [ペイウォールを表示する](flutter-present-paywalls) - [ペイウォールイベントを処理する](flutter-handling-events) - [ボタンアクションに応答する](flutter-handle-paywall-actions) LLMに送る内容: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/flutter-quickstart-paywalls.md - https://adapty.io/docs/ja/flutter-get-pb-paywalls.md - https://adapty.io/docs/ja/flutter-present-paywalls.md - https://adapty.io/docs/ja/flutter-handling-events.md - https://adapty.io/docs/ja/flutter-handle-paywall-actions.md ``` :::tip[チェックポイント] - **期待される結果:** 設定したプロダクトでペイウォールが表示される。プロダクトをタップするとサンドボックス購入ダイアログが表示される。 - **注意点:** ペイウォールが空または `getPaywall` エラー → プレースメントIDがダッシュボードと完全に一致しているか、プレースメントにオーディエンスが割り当てられているか確認する。 ::: </TabItem> <TabItem value="manual" label="Manual paywalls"> **ガイド:** - [カスタムペイウォールで購入を有効にする(クイックスタート)](flutter-quickstart-manual) - [ペイウォールとプロダクトを取得する](fetch-paywalls-and-products-flutter) - [リモートコンフィグで設計したペイウォールをレンダリングする](present-remote-config-paywalls-flutter) - [購入を行う](flutter-making-purchases) - [購入を復元する](flutter-restore-purchase) LLMに送る内容: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/flutter-quickstart-manual.md - https://adapty.io/docs/ja/fetch-paywalls-and-products-flutter.md - https://adapty.io/docs/ja/present-remote-config-paywalls-flutter.md - https://adapty.io/docs/ja/flutter-making-purchases.md - https://adapty.io/docs/ja/flutter-restore-purchase.md ``` :::tip[チェックポイント] - **期待される結果:** カスタムペイウォールにAdaptyから取得したプロダクトが表示される。プロダクトをタップするとサンドボックス購入ダイアログが表示される。 - **注意点:** プロダクト配列が空 → ダッシュボードでペイウォールにプロダクトが割り当てられているか、プレースメントにオーディエンスがあるか確認する。 ::: </TabItem> <TabItem value="observer" label="Observer mode"> **ガイド:** - [オブザーバーモードの概要](observer-vs-full-mode) - [オブザーバーモードを実装する](implement-observer-mode-flutter) - [オブザーバーモードでトランザクションを報告する](report-transactions-observer-mode-flutter) LLMに送る内容: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/observer-vs-full-mode.md - https://adapty.io/docs/ja/implement-observer-mode-flutter.md - https://adapty.io/docs/ja/report-transactions-observer-mode-flutter.md ``` :::tip[チェックポイント] - **期待される結果:** 既存の購入フローでサンドボックス購入を行うと、Adapty ダッシュボードの **Event Feed** にトランザクションが表示される。 - **注意点:** イベントが表示されない → Adaptyへのトランザクション報告が行われているか、両ストアでサーバー通知が設定されているか確認する。 ::: </TabItem> </Tabs> ### サブスクリプションステータスを確認する \{#check-subscription-status\} 購入後、ユーザープロファイルのアクティブなアクセスレベルを確認してプレミアムコンテンツを制限します。 **ガイド:** [サブスクリプションステータスを確認する](flutter-check-subscription-status) LLMに送る内容: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/flutter-check-subscription-status.md ``` :::tip[チェックポイント] - **期待される結果:** サンドボックス購入後、`profile.accessLevels['premium']?.isActive` が `true` を返す。 - **注意点:** 購入後に `accessLevels` が空 → ダッシュボードでプロダクトにアクセスレベルが割り当てられているか確認する。 ::: ### ユーザーを識別する \{#identify-users\} アプリのユーザーアカウントをAdaptyプロファイルに紐付けて、デバイスをまたいで購入が維持されるようにします。 :::important アプリに認証機能がない場合はこのステップをスキップしてください。 ::: **ガイド:** [ユーザーを識別する](flutter-quickstart-identify) LLMに送る内容: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/flutter-quickstart-identify.md ``` :::tip[チェックポイント] - **期待される結果:** `Adapty().identify()` を呼び出した後、ダッシュボードの **Profiles** セクションにカスタムユーザーIDが表示される。 - **注意点:** 匿名プロファイルへのアトリビューションを防ぐため、アクティベーション後かつペイウォール取得前に `identify` を呼び出すこと。 ::: ### リリースの準備をする \{#prepare-for-release\} サンドボックスでの統合が動作したら、リリースチェックリストを確認してすべてが本番環境で問題ないことを確かめます。 **ガイド:** [リリースチェックリスト](release-checklist) LLMに送る内容: ``` Read these Adapty docs before releasing: - https://adapty.io/docs/ja/release-checklist.md ``` :::tip[チェックポイント] - **期待される結果:** すべてのチェックリスト項目が確認済み:ストア接続、サーバー通知、購入フロー、アクセスレベルの確認、プライバシー要件。 - **注意点:** サーバー通知が未設定 → **App settings → iOS SDK** でApp Store Server Notificationsを設定し、**App settings → Android SDK** でGoogle Play Real-Time Developer Notificationsを設定する。 ::: ## プレーンテキストのドキュメントインデックスファイル \{#plain-text-doc-index-files\} 個別ページを超えてLLMに広いコンテキストを提供したい場合は、すべてのAdaptyドキュメントを一覧化または統合したインデックスファイルを用意しています。 - [`llms.txt`](https://adapty.io/docs/ja/llms.txt): `.md` リンクつきで全ページを一覧表示します。LLMがウェブサイトにアクセスしやすくするための[新興標準](https://llmstxt.org/)です。一部のAIエージェント(ChatGPTなど)では `llms.txt` をダウンロードしてチャットにファイルとしてアップロードする必要があります。 - [`llms-full.txt`](https://adapty.io/docs/ja/llms-full.txt): Adaptyドキュメントサイト全体を1つのファイルに統合したものです。非常に大きいため、全体像が必要な場合のみ使用してください。 - Flutter専用の [`flutter-llms.txt`](https://adapty.io/docs/ja/flutter-llms.txt) と [`flutter-llms-full.txt`](https://adapty.io/docs/ja/flutter-llms-full.txt): サイト全体よりもトークンを節約できるプラットフォーム別サブセットです。 --- # File: flutter-get-pb-paywalls --- --- title: "Flutter SDKでペイウォールビルダーのペイウォールとその設定を取得する" description: "Flutter向けAdaptyでPBペイウォールを取得し、サブスクリプション管理を改善する方法を学びましょう。" --- Adapty ダッシュボードの新しいペイウォールビルダーで[ペイウォールのビジュアル部分をデザインした](adapty-paywall-builder)後、モバイルアプリにそれを表示できます。このプロセスの最初のステップは、プレースメントに関連付けられたペイウォールとそのビュー設定を取得することです。 :::warning 新しいペイウォールビルダーはFlutter SDK バージョン3.3.0以上が必要です。 ::: このトピックはペイウォールビルダーでカスタマイズされたペイウォールに関するものです。ペイウォールを手動で実装する場合は、[モバイルアプリのリモートコンフィグペイウォール用にペイウォールとプロダクトを取得する](fetch-paywalls-and-products-flutter)トピックを参照してください。 :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: <details> <summary>モバイルアプリでペイウォールの表示を始める前に(クリックして展開)</summary> 1. Adapty ダッシュボードで[プロダクトを作成する](create-product)。 2. Adapty ダッシュボードで[ペイウォールを作成してプロダクトを追加する](create-paywall)。 3. Adapty ダッシュボードで[プレースメントを作成してペイウォールを追加する](create-placement)。 4. モバイルアプリに[Adapty SDK](sdk-installation-flutter)をインストールする。 </details> ## ペイウォールビルダーで作成されたペイウォールを取得する \{#fetch-paywall-designed-with-paywall-builder\} [ペイウォールビルダーを使用してペイウォールをデザインした](adapty-paywall-builder)場合、ユーザーに表示するためにモバイルアプリのコードでレンダリングする必要はありません。このようなペイウォールには、ペイウォール内に表示する内容と表示方法の両方が含まれています。ただし、プレースメントを通じてそのIDを取得し、ビュー設定を取得してからモバイルアプリに表示する必要があります。 最適なパフォーマンスを確保するために、ペイウォールとその[ビュー設定](flutter-get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder)をできるだけ早く取得し、ユーザーに提示する前に画像をダウンロードするのに十分な時間を確保することが重要です。 ペイウォールを取得するには、`getPaywall` メソッドを使用します。 ```dart showLineNumbers try { final paywall = await Adapty().getPaywall(placementId: "YOUR_PLACEMENT_ID", locale: "en"); // the requested paywall } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` パラメーター: | パラメーター | 必須/任意 | 説明 | |---------|--------|-----------| | **placementId** | 必須 | 取得したい[プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** | <p>任意</p><p>デフォルト:`en`</p> | <p>[ペイウォールのローカライズ](add-paywall-locale-in-adapty-paywall-builder)の識別子。マイナス(**-**)で区切られた1つまたは2つのサブタグで構成される言語コードを指定します。最初のサブタグは言語、2番目は地域を表します。</p><p></p><p>例:`en` は英語、`pt-br` はブラジルポルトガル語を表します。</p><p>ロケールコードと推奨される使用方法については、[ローカライズとロケールコード](flutter-localizations-and-locale-codes)を参照してください。</p> | | **fetchPolicy** | デフォルト:`.reloadRevalidatingCacheData` | <p>デフォルトでは、SDKはサーバーからデータを読み込もうとし、失敗した場合はキャッシュデータを返します。ユーザーが常に最新のデータを取得できるため、このオプションを推奨します。</p><p></p><p>ただし、ユーザーが不安定なインターネット環境にある場合は、`.returnCacheDataElseLoad` を使用してキャッシュデータが存在する場合に返すことを検討してください。この場合、ユーザーは最新のデータを取得できないこともありますが、インターネット接続が不安定でも読み込み時間が短縮されます。キャッシュは定期的に更新されるため、ネットワークリクエストを避けるためにセッション中に使用しても安全です。</p><p></p><p>キャッシュはアプリの再起動後も保持され、アプリの再インストールまたは手動クリーンアップ時にのみクリアされます。</p><p></p><p>Adapty SDKはペイウォールをローカルに2層で保存します:上記の定期更新されるキャッシュと[フォールバックペイウォール](fallback-paywalls)です。また、ペイウォールをより速く取得するためにCDNを使用し、CDNに到達できない場合のスタンドアロンフォールバックサーバーも備えています。このシステムは、インターネット接続が不安定な場合でも信頼性を確保しながら、常に最新バージョンのペイウォールを取得できるように設計されています。</p> | | **loadTimeout** | デフォルト:5秒 | <p>このメソッドのタイムアウト上限を設定します。タイムアウトに達した場合、キャッシュデータまたはローカルフォールバックが返されます。</p><p>操作が内部で複数のリクエストで構成される場合があるため、まれに `loadTimeout` で指定した時間よりもわずかに遅くタイムアウトすることがあります。</p><p>Android の場合:拡張関数(例:`5.seconds`、`.seconds` は `import com.adapty.utils.seconds` から)または `TimeInterval.seconds(5)` を使用して `TimeInterval` を作成できます。制限を設けない場合は `TimeInterval.INFINITE` を使用してください。</p> | レスポンスパラメーター: | パラメーター | 説明 | | :-------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------- | | Paywall | プロダクトIDのリスト、ペイウォール識別子、リモートコンフィグ、その他いくつかのプロパティを持つ [`AdaptyPaywall`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyPaywall-class.html) オブジェクト。 | ## ペイウォールビルダーで作成されたペイウォールのビュー設定を取得する \{#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder\} :::important ペイウォールビルダーで **Show on device** トグルを有効にしてください。このオプションがオンになっていない場合、ビュー設定を取得できません。 ::: ペイウォールを取得した後、`ViewConfiguration` が含まれているか確認してください。これはペイウォールビルダーで作成されたことを示します。この確認によってペイウォールの表示方法が決まります。`ViewConfiguration` が存在する場合はペイウォールビルダーのペイウォールとして扱い、存在しない場合は[リモートコンフィグのペイウォールとして処理します](present-remote-config-paywalls-flutter)。 ```dart showLineNumbers try { final view = await AdaptyUI().createPaywallView( paywall: paywall, ); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` ビューを取得したら、[ペイウォールを表示します](flutter-present-paywalls)。 ## デフォルトオーディエンス向けのペイウォールをより速く取得する \{#get-a-paywall-for-a-default-audience-to-fetch-it-faster\} 通常、ペイウォールはほぼ瞬時に取得されるため、このプロセスの高速化について心配する必要はありません。ただし、多数のオーディエンスとペイウォールがあり、ユーザーのインターネット接続が弱い場合、ペイウォールの取得に予想以上の時間がかかることがあります。そのような状況では、ペイウォールをまったく表示しないよりも、スムーズなユーザー体験を確保するためにデフォルトのペイウォールを表示したい場合があります。 これに対処するため、`getPaywallForDefaultAudience` メソッドを使用できます。このメソッドは、**All Users** オーディエンス向けの指定されたプレースメントのペイウォールを取得します。ただし、上記の[ペイウォール情報を取得する](flutter-get-pb-paywalls#fetch-paywall-designed-with-paywall-builder)セクションで詳述しているように、`getPaywall` メソッドでペイウォールを取得することが推奨されるアプローチであることを理解することが重要です。 :::warning `getPaywall` の使用を推奨する理由 `getPaywallForDefaultAudience` メソッドにはいくつかの重大な欠点があります: - **後方互換性の問題が発生する可能性**:異なるアプリバージョン(現在と将来)に対して異なるペイウォールを表示する必要がある場合、課題が生じる可能性があります。現在の(レガシー)バージョンをサポートするペイウォールを設計するか、現在の(レガシー)バージョンのユーザーがレンダリングされないペイウォールの問題に直面するリスクを受け入れるかのどちらかを選択する必要があります。 - **ターゲティングの喪失**:すべてのユーザーが **All Users** オーディエンス向けに設計された同じペイウォールを表示するため、パーソナライズされたターゲティング(国、マーケティングアトリビューション、または独自のカスタム属性に基づくものを含む)が失われます。 ペイウォール取得の高速化という恩恵を受けるためにこれらの欠点を受け入れる場合は、以下のように `getPaywallForDefaultAudience` メソッドを使用してください。そうでない場合は、[上記](#fetch-paywall-designed-with-paywall-builder)で説明した `getPaywall` を使用してください。 ::: ```dart showLineNumbers try { final paywall = await Adapty().getPaywallForDefaultAudience(placementId: 'YOUR_PLACEMENT_ID'); } on AdaptyError catch (adaptyError) { // handle error } catch (e) { // handle unknown error } ``` :::note `getPaywallForDefaultAudience` メソッドはFlutter SDK バージョン3.2.0以降で利用可能です。 ::: | パラメーター | 必須/任意 | 説明 | |---------|--------|-----------| | **placementId** | 必須 | [プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** | <p>任意</p><p>デフォルト:`en`</p> | <p>[ペイウォールのローカライズ](add-remote-config-locale)の識別子。マイナス(**-**)で区切られた1つ以上のサブタグで構成される言語コードを指定します。最初のサブタグは言語、2番目は地域を表します。</p><p></p><p>例:`en` は英語、`pt-br` はブラジルポルトガル語を表します。</p><p></p><p>ロケールコードと推奨される使用方法については、[ローカライズとロケールコード](localizations-and-locale-codes)を参照してください。</p> | | **fetchPolicy** | デフォルト:`.reloadRevalidatingCacheData` | <p>デフォルトでは、SDKはサーバーからデータを読み込もうとし、失敗した場合はキャッシュデータを返します。ユーザーが常に最新のデータを取得できるため、このオプションを推奨します。</p><p></p><p>ただし、ユーザーが不安定なインターネット環境にある場合は、`.returnCacheDataElseLoad` を使用してキャッシュデータが存在する場合に返すことを検討してください。この場合、ユーザーは最新のデータを取得できないこともありますが、インターネット接続が不安定でも読み込み時間が短縮されます。キャッシュは定期的に更新されるため、ネットワークリクエストを避けるためにセッション中に使用しても安全です。</p><p></p><p>キャッシュはアプリの再起動後も保持され、アプリの再インストールまたは手動クリーンアップ時にのみクリアされます。</p> | ## アセットをカスタマイズする \{#customize-assets\} ペイウォール内の画像や動画をカスタマイズするには、カスタムアセットを実装します。 ヒーロー画像と動画には事前定義されたID(`hero_image` および `hero_video`)があります。カスタムアセットバンドルでは、これらのIDを使用して要素をターゲットにし、その動作をカスタマイズします。 その他の画像や動画については、Adapty ダッシュボードで[カスタムIDを設定する](custom-media)必要があります。 例えば、次のことができます: - 一部のユーザーに異なる画像や動画を表示する。 - リモートのメイン画像が読み込まれている間にローカルのプレビュー画像を表示する。 - 動画を再生する前にプレビュー画像を表示する。 :::important この機能を使用するには、Adapty Flutter SDK をバージョン3.8.0以上にアップデートしてください。 ::: シンプルなディクショナリを使用してカスタムアセットを提供する例を示します: ```dart final customAssets = { // Show a local image using a custom ID 'custom_image': AdaptyCustomAsset.localImageAsset( assetId: 'assets/images/image_name.png', ), // Show a local video with a preview image 'hero_video': AdaptyCustomAsset.localVideoAsset( assetId: 'assets/videos/custom_video.mp4', ), }; try { final view = await AdaptyUI().createPaywallView( paywall: paywall, customAssets: <CUSTOM_ASSETS>, preloadProducts: preloadProducts, ); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` :::note アセットが見つからない場合、ペイウォールはデフォルトの外観にフォールバックします。 ::: ## 開発者定義タイマーを設定する \{#set-up-developer-defined-timers\} モバイルアプリでカスタムタイマーを使用するには、`AdaptyTimerResolver` プロトコルに準拠したオブジェクトを作成してください。このオブジェクトは各カスタムタイマーのレンダリング方法を定義します。必要であれば、このプロトコルにすでに準拠している `[String: Date]` ディクショナリを直接使用することもできます。以下に例を示します: ```dart showLineNumbers try { final view = await AdaptyUI().createPaywallView( paywall: paywall, customTimers: { 'CUSTOM_TIMER_6H': DateTime.now().add(const Duration(seconds: 3600 * 6)), 'CUSTOM_TIMER_NY': DateTime(2025, 1, 1), // New Year 2025 }, ); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` この例では、`CUSTOM_TIMER_NY` と `CUSTOM_TIMER_6H` はAdapity ダッシュボードで設定した開発者定義タイマーの **Timer ID** です。`timerResolver` は、アプリが各タイマーを正しい値で動的に更新することを保証します。例えば: - `CUSTOM_TIMER_NY`:元日など、タイマー終了までの残り時間。 - `CUSTOM_TIMER_6H`:ユーザーがペイウォールを開いた時点から始まる6時間の残り時間。 --- # File: flutter-present-paywalls --- --- title: "Flutter - 新しいペイウォールビルダーのペイウォールを表示する" description: "Adaptyのマネタイズ機能を使ってFlutterアプリでペイウォールを表示します。" --- ペイウォールビルダーを使ってペイウォールをカスタマイズした場合、モバイルアプリのコードでレンダリングしてユーザーに表示する必要はありません。このようなペイウォールには、表示する内容と表示方法の両方が含まれています。 :::warning このガイドは、SDK v3.2.0 以降が必要な**新しいペイウォールビルダーのペイウォール**専用です。ペイウォールの表示方法は、ペイウォールビルダーのバージョンやリモートコンフィグのペイウォールによって異なります。 - **リモートコンフィグのペイウォール**を表示する場合は、[リモートコンフィグで設計されたペイウォールのレンダリング](present-remote-config-paywalls)を参照してください。 ::: Adapty Flutter SDK では、ペイウォールを表示する方法が2つあります。 - **スタンドアロンスクリーン** - **埋め込みウィジェット** ## スタンドアロンスクリーンとして表示する \{#present-as-standalone-screen\} ペイウォールをスタンドアロンスクリーンとして表示するには、[`createPaywallView`](flutter-get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder) メソッドで作成した `view` に対して `view.present()` メソッドを使用します。各 `view` は一度しか使用できません。ペイウォールを再度表示する必要がある場合は、`createPaywallView` をもう一度呼び出して新しい `view` インスタンスを作成してください。 :::warning 同じ `view` を再作成せずに再利用すると、`AdaptyUIError.viewAlreadyPresented` エラーが発生する可能性があります。 ::: ```dart showLineNumbers title="Flutter" try { await view.present(); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: ### ペイウォールを閉じる \{#dismiss-the-paywall\} プログラムからペイウォールを閉じる必要がある場合は、`dismiss()` メソッドを使用します。 ```dart showLineNumbers title="Flutter" try { await view.dismiss(); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` ### ダイアログを表示する \{#show-dialog\} Android でペイウォールビューが表示されているときは、ネイティブのアラートダイアログの代わりにこのメソッドを使用してください。Android では、通常のアラートがペイウォールビューの背後に表示されるため、ユーザーには見えません。このメソッドを使用することで、すべてのプラットフォームでペイウォールの上に正しくダイアログが表示されます。 ```dart showLineNumbers title="Flutter" try { final action = await view.showDialog( title: 'Close paywall?', content: 'You will lose access to exclusive offers.', primaryActionTitle: 'Stay', secondaryActionTitle: 'Close', ); if (action == AdaptyUIDialogActionType.secondary) { // User confirmed - close the paywall await view.dismiss(); } // If primary - do nothing, user stays } catch (e) { // handle error } ``` ### iOS の表示スタイルを設定する \{#configure-ios-presentation-style\} `present()` メソッドに `iosPresentationStyle` パラメータを渡すことで、iOS でのペイウォールの表示方法を設定できます。パラメータには `AdaptyUIIOSPresentationStyle.fullScreen`(デフォルト)または `AdaptyUIIOSPresentationStyle.pageSheet` を指定できます。 ```dart showLineNumbers try { await view.present(iosPresentationStyle: AdaptyUIIOSPresentationStyle.pageSheet); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` ## ウィジェット階層に埋め込む \{#embed-in-widget-hierarchy\} 既存のウィジェットツリーにペイウォールを埋め込むには、Flutter のウィジェット階層に `AdaptyUIPaywallPlatformView` ウィジェットを直接使用します。 ```dart showLineNumbers title="Flutter" AdaptyUIPaywallPlatformView( paywall: paywall, // The paywall object you fetched onDidAppear: (view) { }, onDidDisappear: (view) { }, onDidPerformAction: (view, action) { }, onDidSelectProduct: (view, productId) { }, onDidStartPurchase: (view, product) { }, onDidFinishPurchase: (view, product, purchaseResult) { }, onDidFailPurchase: (view, product, error) { }, onDidStartRestore: (view) { }, onDidFinishRestore: (view, profile) { }, onDidFailRestore: (view, error) { }, onDidFailRendering: (view, error) { }, onDidFailLoadingProducts: (view, error) { }, onDidFinishWebPaymentNavigation: (view, product, error) { }, ) ``` :::note Android プラットフォームビューを機能させるには、`MainActivity` が `FlutterFragmentActivity` を継承していることを確認してください。 ```kotlin showLineNumbers title="Kotlin" class MainActivity : FlutterFragmentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) } } ``` ::: --- # File: flutter-handle-paywall-actions --- --- title: "Flutter SDKでボタンアクションに応答する" description: "AdaptyのFlutter SDKでペイウォールのボタンアクションを処理し、アプリのマネタイズを改善する方法を解説します。" --- ペイウォールビルダーでペイウォールを作成する場合、ボタンを適切に設定することが重要です。 1. [ペイウォールビルダーでボタンを追加](paywall-buttons)し、既存のアクションを割り当てるか、カスタムアクションIDを作成します。 2. 割り当てた各アクションを処理するコードをアプリに実装します。 このガイドでは、カスタムアクションと既存アクションをコードで処理する方法を説明します。 :::warning **購入と復元のみが自動的に処理されます。** ペイウォールを閉じたりリンクを開いたりする操作など、その他のボタンアクションはすべて、アプリのコードに適切な処理を実装する必要があります。 ::: ## ペイウォールを閉じる \{#close-paywalls\} ペイウォールを閉じるボタンを追加するには: 1. ペイウォールビルダーでボタンを追加し、**Close** アクションを割り当てます。 2. アプリのコードに、`CloseAction` と `AndroidSystemBackAction` アクションのハンドラーを実装します。 :::info Flutter SDK では、`CloseAction` と `AndroidSystemBackAction` アクションはデフォルトでペイウォールを閉じる動作をします。ただし、必要に応じてコードでこの動作をオーバーライドすることもできます。たとえば、あるペイウォールを閉じると別のペイウォールが開くようにすることも可能です。 ::: ```dart void paywallViewDidPerformAction(AdaptyUIPaywallView view, AdaptyUIAction action) { switch (action) { case const CloseAction(): case const AndroidSystemBackAction(): view.dismiss(); break; default: break; } } ``` ## ペイウォールからURLを開く \{#open-urls-from-paywalls\} :::tip リンクのグループ(利用規約や購入の復元など)を追加したい場合は、ペイウォールビルダーで **Link** 要素を追加し、**Open URL** アクションが割り当てられたボタンと同じ方法で処理します。 ::: ペイウォールからリンクを開くボタン(**Terms of use** や **Privacy policy** など)を追加するには: 1. ペイウォールビルダーでボタンを追加し、**Open URL** アクションを割り当てて、開きたいURLを入力します。 2. アプリのコードに、受け取ったURLをブラウザで開く `openUrl` アクションのハンドラーを実装します。 ```dart // You have to install url_launcher plugin in order to handle urls: // https://pub.dev/packages/url_launcher void paywallViewDidPerformAction(AdaptyUIView view, AdaptyUIAction action) { switch (action) { case OpenUrlAction(url: final url): final Uri uri = Uri.parse(url); launchUrl(uri, mode: LaunchMode.inAppBrowserView); break; default: break; } } ``` ## アプリへのログイン \{#log-into-the-app\} ユーザーをアプリにログインさせるボタンを追加するには: 1. ペイウォールビルダーでボタンを追加し、**Login** アクションを割り当てます。 2. アプリのコードに、ユーザーを識別する `login` アクションのハンドラーを実装します。 ```dart void paywallViewDidPerformAction(AdaptyUIPaywallView view, AdaptyUIAction action) { switch (action) { case CustomAction(action: 'login'): // Handle login action Navigator.of(context).push(MaterialPageRoute(builder: (context) => LoginScreen())); break; default: break; } } ``` ## カスタムアクションを処理する \{#handle-custom-actions\} その他のアクションを処理するボタンを追加するには: 1. ペイウォールビルダーでボタンを追加し、**Custom** アクションを割り当てて、IDを設定します。 2. アプリのコードに、作成したアクションIDのハンドラーを実装します。 たとえば、別のサブスクリプションプランや買い切り購入がある場合、別のペイウォールを表示するボタンを追加できます。 ```dart void paywallViewDidPerformAction(AdaptyUIPaywallView view, AdaptyUIAction action) { switch (action) { case CustomAction(action: 'openNewPaywall'): // Display another paywall break; default: break; } } ``` --- # File: flutter-handling-events --- --- title: "Flutter - ペイウォールイベントの処理" description: "Adapty を使用して Flutter でサブスクリプション関連イベントを処理し、ユーザーのインタラクションを効果的に追跡する方法を説明します。" --- :::important このガイドでは、購入・復元・プロダクト選択・ペイウォールレンダリングのイベント処理について説明します。ボタン操作(ペイウォールを閉じる、リンクを開くなど)の処理も実装する必要があります。詳細は[ボタン操作の処理に関するガイド](flutter-handle-paywall-actions)を参照してください。 ::: [ペイウォールビルダー](adapty-paywall-builder)で設定されたペイウォールは、購入や復元を行うための追加コードは不要です。ただし、アプリが応答できるイベントが生成されます。これらのイベントには、ボタン操作(閉じるボタン、URL、プロダクト選択など)やペイウォール上の購入関連アクションの通知が含まれます。これらのイベントへの対応方法を以下で説明します。 :::warning このガイドは、Adapty SDK v3.0 以降が必要な**新しいペイウォールビルダーのペイウォール**専用です。 ::: モバイルアプリのペイウォール画面で発生するプロセスを制御・監視するには、`AdaptyUIPaywallsEventsObserver` のメソッドを実装し、画面を表示する前にオブザーバーを設定してください。 ```javascript showLineNumbers title="Flutter" AdaptyUI().setPaywallsEventsObserver(this); ``` :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: ### ユーザー生成イベント \{#user-generated-events\} #### ペイウォールの表示 \{#paywall-appeared\} このメソッドは、ペイウォールビューが画面に表示されたときに呼び出されます。 :::note iOS では、ユーザーがペイウォール内の[ウェブペイウォールボタン](web-paywall#step-2a-add-a-web-purchase-button)をタップし、アプリ内ブラウザでウェブペイウォールが開いたときにも呼び出されます。 ::: ```javascript showLineNumbers title="Flutter" void paywallViewDidAppear(AdaptyUIPaywallView view) { } ``` #### ペイウォールの非表示 \{#paywall-disappeared\} このメソッドは、ペイウォールビューが画面から閉じられたときに呼び出されます。 :::note iOS では、ペイウォールからアプリ内ブラウザで開いた[ウェブペイウォール](web-paywall#step-2a-add-a-web-purchase-button)が画面から消えたときにも呼び出されます。 ::: ```javascript showLineNumbers title="Flutter" void paywallViewDidDisappear(AdaptyUIPaywallView view) { } ``` #### プロダクト選択 \{#product-selection\} プロダクトが購入のために選択された場合(ユーザーまたはシステムによる)、このメソッドが呼び出されます。 ```javascript showLineNumbers title="Flutter" void paywallViewDidSelectProduct(AdaptyUIPaywallView view, String productId) { } ``` <Details> <summary>イベントの例(クリックして展開)</summary> ```javascript { "productId": "premium_monthly" } ``` </Details> #### 購入の開始 \{#started-purchase\} ユーザーが購入プロセスを開始した場合、このメソッドが呼び出されます。 ```javascript showLineNumbers title="Flutter" void paywallViewDidStartPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product) { } ``` <Details> <summary>イベントの例(クリックして展開)</summary> ```javascript { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" } } ``` </Details> #### 購入の完了 \{#finished-purchase\} このメソッドは、購入が成功した場合、ユーザーが購入をキャンセルした場合、または購入が保留中になった場合に呼び出されます。 ```javascript showLineNumbers title="Flutter" void paywallViewDidFinishPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product, AdaptyPurchaseResult purchaseResult) { switch (purchaseResult) { case AdaptyPurchaseResultSuccess(profile: final profile): // successful purchase break; case AdaptyPurchaseResultPending(): // purchase is pending break; case AdaptyPurchaseResultUserCancelled(): // user cancelled the purchase break; default: break; } } ``` <Details> <summary>イベントの例(クリックして展開)</summary> ```javascript // Successful purchase { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "purchaseResult": { "type": "AdaptyPurchaseResultSuccess", "profile": { "accessLevels": { "premium": { "id": "premium", "isActive": true, "expiresAt": "2024-02-15T10:30:00Z" } } } } } // Pending purchase { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "purchaseResult": { "type": "AdaptyPurchaseResultPending" } } // User cancelled purchase { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "purchaseResult": { "type": "AdaptyPurchaseResultUserCancelled" } } ``` </Details> この場合は画面を閉じることを推奨します。ペイウォール画面を閉じる方法については、[ボタン操作への対応](flutter-handle-paywall-actions)を参照してください。 #### ウェブ決済ナビゲーションの完了 \{#finished-web-payment-navigation\} このメソッドは、特定のプロダクトに対して[ウェブペイウォール](web-paywall)を開こうとした後に呼び出されます。ナビゲーションの成功・失敗にかかわらず呼び出されます。 ```javascript showLineNumbers title="Flutter" void paywallViewDidFinishWebPaymentNavigation(AdaptyUIPaywallView view, AdaptyPaywallProduct? product, AdaptyError? error) { } ``` **パラメーター:** | パラメーター | 説明 | |:------------|:-------------------------------------------------------------------------------------------------------| | **product** | ウェブペイウォールが開かれた `AdaptyPaywallProduct`。`null` の場合があります。 | | **error** | ウェブペイウォールのナビゲーションが失敗した場合は `AdaptyError` オブジェクト。成功した場合は `null`。 | <Details> <summary>イベントの例(クリックして展開)</summary> ```javascript // Successful navigation { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "error": null } // Failed navigation { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "error": { "code": "web_navigation_failed", "message": "Failed to open web paywall", "details": { "underlyingError": "Browser unavailable" } } } ``` </Details> #### 購入の失敗 \{#failed-purchase\} このメソッドは、購入が失敗した場合(決済エラーやネットワークエラーなど)に呼び出されます。ユーザーによるキャンセルや保留中のトランザクションには**呼び出されません**。それらは `paywallViewDidFinishPurchase` で処理されます。 ```javascript showLineNumbers title="Flutter" void paywallViewDidFailPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product, AdaptyError error) { } ``` <Details> <summary>イベントの例(クリックして展開)</summary> ```javascript { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "error": { "code": "purchase_failed", "message": "Purchase failed due to insufficient funds", "details": { "underlyingError": "Insufficient funds in account" } } } ``` </Details> #### 復元の開始 \{#started-restore\} ユーザーが復元プロセスを開始した場合、このメソッドが呼び出されます。 ```javascript showLineNumbers title="Flutter" void paywallViewDidStartRestore(AdaptyUIPaywallView view) { } ``` #### 復元の成功 \{#successful-restore\} 購入の復元が成功した場合、このメソッドが呼び出されます。 ```javascript showLineNumbers title="Flutter" void paywallViewDidFinishRestore(AdaptyUIPaywallView view, AdaptyProfile profile) { } ``` <Details> <summary>イベントの例(クリックして展開)</summary> ```javascript { "profile": { "accessLevels": { "premium": { "id": "premium", "isActive": true, "expiresAt": "2024-02-15T10:30:00Z" } }, "subscriptions": [ { "vendorProductId": "premium_monthly", "isActive": true, "expiresAt": "2024-02-15T10:30:00Z" } ] } } ``` </Details> ユーザーが必要な `accessLevel` を持っている場合は、画面を閉じることを推奨します。確認方法については[サブスクリプションのステータス](flutter-listen-subscription-changes)を、ペイウォール画面の閉じ方については[ボタン操作への対応](flutter-handle-paywall-actions)を参照してください。 #### 復元の失敗 \{#failed-restore\} 購入の復元が失敗した場合、このメソッドが呼び出されます。 ```javascript showLineNumbers title="Flutter" void paywallViewDidFailRestore(AdaptyUIPaywallView view, AdaptyError error) { } ``` <Details> <summary>イベントの例(クリックして展開)</summary> ```javascript { "error": { "code": "restore_failed", "message": "Purchase restoration failed", "details": { "underlyingError": "No previous purchases found" } } } ``` </Details> ### データの取得とレンダリング \{#data-fetching-and-rendering\} #### プロダクト読み込みエラー \{#product-loading-errors\} 初期化時にプロダクト配列を渡さない場合、AdaptyUI は必要なオブジェクトをサーバーから自動的に取得します。この操作が失敗した場合、AdaptyUI はこのメソッドを呼び出してエラーを通知します。 ```javascript showLineNumbers title="Flutter" void paywallViewDidFailLoadingProducts(AdaptyUIPaywallView view, AdaptyError error) { } ``` <Details> <summary>イベントの例(クリックして展開)</summary> ```javascript { "error": { "code": "products_loading_failed", "message": "Failed to load products from the server", "details": { "underlyingError": "Network timeout" } } } ``` </Details> #### レンダリングエラー \{#rendering-errors\} インターフェースのレンダリング中にエラーが発生した場合、このメソッドが呼び出されます。デフォルト(v3.15.2 以降)では、レンダリングエラーが発生するとペイウォールは自動的に閉じられますが、必要に応じてこの動作をオーバーライドできます。 ```javascript showLineNumbers title="Flutter" void paywallViewDidFailRendering(AdaptyUIPaywallView view, AdaptyError error) { // Default behavior: view.dismiss() // Override with custom logic if needed, for example: // - Log the error // - Show an error message to the user } ``` <Details> <summary>イベントの例(クリックして展開)</summary> ```javascript { "error": { "code": "rendering_failed", "message": "Failed to render paywall interface", "details": { "underlyingError": "Invalid paywall configuration" } } } ``` </Details> 通常の状況ではこのようなエラーは発生しないため、もし遭遇した場合はお知らせください。 --- # File: flutter-use-fallback-paywalls --- --- title: "Flutter - フォールバックペイウォールを使用する" description: "ユーザーがオフラインのときや Adapty サーバーが利用できないときの対処方法" --- :::warning フォールバックペイウォールは Flutter SDK v2.11 以降でサポートされています。 ::: スムーズなユーザー体験を維持するために、フロー、[ペイウォール](paywalls)、[オンボーディング](onboardings)に[フォールバック](/fallback-paywalls)を設定することが重要です。この対策により、インターネット接続が部分的または完全に失われた場合でも、アプリケーションの機能を維持できます。 * **アプリケーションが Adapty サーバーにアクセスできない場合:** フォールバックのフローまたはペイウォールを表示し、ローカルのオンボーディング設定にアクセスできます。 * **アプリケーションがインターネットにアクセスできない場合:** フォールバックのフローまたはペイウォールを表示できます。オンボーディングはリモートコンテンツを含むため、動作にはインターネット接続が必要です。 :::important このガイドの手順を進める前に、Adapty からフォールバック設定ファイルを[ダウンロード](/local-fallback-paywalls)してください。 ::: ## 設定 \{#configuration\} 1. フォールバック設定ファイルをプロジェクトルートのアプリ `assets` ディレクトリに追加します。 2. 対象のペイウォールまたはオンボーディングを取得する**前に** `.setFallback` メソッドを呼び出します。 ```javascript showLineNumbers title="javascript" final assetId = Platform.isIOS ? 'assets/ios_fallback.json' : 'assets/android_fallback.json'; try { await Adapty.setFallback(assetId); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` パラメーター: | パラメーター | 説明 | | :------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **assetId** | フォールバック設定ファイルへのパス。 | :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: --- # File: flutter-localizations-and-locale-codes --- --- title: "Flutter SDKでローカライズとロケールコードを使用する" description: "グローバルなユーザーにリーチするために、アプリのローカライズとロケールコードを管理します。" --- ## なぜこれが重要なのか \{#why-this-is-important\} ロケールコードが関係するシナリオはいくつかあります。たとえば、アプリの現在のローカライズに合わせた正しいペイウォールを取得しようとする場合などです。 ロケールコードは複雑で、プラットフォームによって異なることがあるため、サポートしているすべてのプラットフォームに対して内部標準を採用しています。ただし、コードが複雑なため、サーバーに何を送信して正しいローカライズを取得するか、そしてその後何が起こるかを正確に理解することが非常に重要です。そうすることで、常に期待通りの結果を受け取れます。 ## Adaptyにおけるロケールコード標準 \{#locale-code-standard-at-adapty\} ロケールコードには、Adaptyは若干修正した [BCP 47標準](https://en.wikipedia.org/wiki/IETF_language_tag) を使用しています。各コードはハイフンで区切られた小文字のサブタグで構成されています。例: `en`(英語)、`pt-br`(ポルトガル語(ブラジル))、`zh`(簡体字中国語)、`zh-hant`(繁体字中国語)。 ## ロケールコードのマッチング \{#locale-code-matching\} Adaptyがクライアント側SDKからロケールコード付きのリクエストを受け取り、ペイウォールの対応するローカライズを探す際、以下の処理が行われます: 1. 受信したロケール文字列が小文字に変換され、アンダースコア(`_`)がすべてハイフン(`-`)に置き換えられます 2. 完全に一致するロケールコードのローカライズを検索します 3. 一致するものが見つからない場合、最初のハイフンより前の部分文字列(`pt-br` の場合は `pt`)を取り出し、一致するローカライズを検索します 4. それでも一致するものが見つからない場合、デフォルトの `en` ローカライズを返します こうすることで、`'pt_BR'` を送信したiOSデバイス、`pt-BR` を送信したAndroidデバイス、`pt-br` を送信した別のデバイスがすべて同じ結果を受け取ることができます。 ## ローカライズの実装:推奨される方法 \{#implementing-localizations-recommended-way\} ローカライズについて検討しているなら、プロジェクト内でローカライズされた文字列ファイルをすでに扱っていることでしょう。その場合、各ローカライズ用のファイルに対応するAdaptyロケールコードをキーと値のペアとして記述することをお勧めします。そして、SDKを呼び出す際にそのキーの値を取り出して使用します: ```dart showLineNumbers // 1. Modify your app_en.arb, app_es.arb, app_pt_br.arb files /* app_en.arb */ "adapty_paywalls_locale": "en", /* app_es.arb */ "adapty_paywalls_locale": "es", /* app_pt_br.arb */ "adapty_paywalls_locale": "pt-br", // 2. Extract and use the locale code final locale = AppLocalizations.of(context)!.adapty_paywalls_locale; // pass locale code to AdaptyUI.getViewConfiguration or Adapty.getPaywall method ``` こうすることで、アプリの各ユーザーに対してどのローカライズが取得されるかを完全にコントロールできます。 ## ローカライズの実装:別の方法 \{#implementing-localizations-the-other-way\} ロケールコードをすべてのローカライズに対して明示的に定義しなくても、同様の(ただし同一ではない)結果を得ることができます。その場合、プラットフォームが提供する他のオブジェクトからロケールコードを取り出す方法が考えられます: ```dart showLineNumbers final locale = Localizations.localeOf(context).languageCode; // pass locale code to AdaptyUI.getViewConfiguration or Adapty.getPaywall method ``` この方法はいくつかの理由から推奨していません: 1. iOSでは、優先言語と現在のロケールは同一ではありません。ローカライズを正しく選択させるには、Appleのロジックに依存するか(ローカライズされた文字列ファイルを使った推奨アプローチを使用していれば自動的に機能します)、自分でそのロジックを再現する必要があります。 2. Adaptyのサーバーが実際に何を受け取るかを予測するのが困難です。たとえばiOSでは、デバイスで `ar_OM@numbers='latn'` のようなロケールを取得してサーバーに送信することがあります。この場合、期待していた `ar-om` ローカライズではなく `ar` が返ってくる可能性があります。 それでもこのアプローチを使用する場合は、関連するすべてのユースケースをカバーしていることを確認してください。 --- # File: flutter-web-paywall --- --- title: "Flutter SDKにウェブペイウォールを実装する" description: "App Storeの手数料や審査なしで決済できるウェブペイウォールを設定します。" --- :::important 始める前に、[ダッシュボードでウェブペイウォールを設定](web-paywall)し、Adapty SDK バージョン 3.6.1 以降をインストールしていることを確認してください。 ::: 自分で作成したペイウォールを使用している場合は、SDKメソッドを使ってウェブペイウォールを処理する必要があります。`.openWebPaywall`メソッドは次の動作を行います。 1. Adaptyが特定のユーザーに表示されたペイウォールとリダイレクト先のウェブページを紐付けるための一意のURLを生成します。 2. ユーザーがアプリに戻ったタイミングを追跡し、短い間隔で`.getProfile`をリクエストして、プロファイルのアクセス権が更新されたかどうかを確認します。 これにより、決済が成功してアクセス権が更新された場合、サブスクリプションはほぼ即座にアプリ内で有効化されます。 ```dart showLineNumbers title="Flutter" try { await Adapty().openWebPaywall(product: <YOUR_PRODUCT>); // The web paywall will be opened } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle other errors } ``` :::note `openWebPaywall`メソッドには2つのバージョンがあります。 1. `openWebPaywall(product)` — ペイウォールによってURLを生成し、プロダクトデータもURLに追加します。 2. `openWebPaywall(paywall)` — プロダクトデータを追加せずにペイウォールによってURLを生成します。Adaptyのペイウォールのプロダクトとウェブペイウォールのプロダクトが異なる場合に使用します。 ::: #### エラーの処理 \{#handle-errors\} | エラー | 説明 | 推奨アクション | |-----------------------------------------|----------------------------------------------------------|-------------------------------------------------------------------------------| | AdaptyError.paywallWithoutPurchaseUrl | ペイウォールにウェブ購入URLが設定されていない | Adapty ダッシュボードでペイウォールが正しく設定されているか確認してください | | AdaptyError.productWithoutPurchaseUrl | プロダクトにウェブ購入URLがない | Adapty ダッシュボードでプロダクトの設定を確認してください | | AdaptyError.failedOpeningWebPaywallUrl | ブラウザでURLを開くことができなかった | デバイスの設定を確認するか、別の購入方法を提供してください | | AdaptyError.failedDecodingWebPaywallUrl | URLのパラメータのエンコードに失敗した | URLパラメータが有効で適切にフォーマットされているか確認してください | ## アプリ内ブラウザでウェブペイウォールを開く \{#open-web-paywalls-in-an-in-app-browser\} :::important アプリ内ブラウザでのウェブペイウォールの表示は、Adapty SDK v3.15 以降でサポートされています。 ::: デフォルトでは、ウェブペイウォールは外部ブラウザで開きます。 シームレスなユーザー体験を提供するために、アプリ内ブラウザでウェブペイウォールを開くことができます。これにより、ウェブ購入ページがアプリ内に表示され、ユーザーはアプリを切り替えることなく取引を完了できます。 これを有効にするには、`in`パラメータを`.inAppBrowser`に設定します。 ```dart showLineNumbers try { await Adapty().openWebPaywall( product: <YOUR_PRODUCT>, openIn: AdaptyWebPresentation.inAppBrowser, ); // The web paywall will be opened in the in-app browser } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle other errors } ``` --- # File: flutter-troubleshoot-paywall-builder --- --- title: "Flutter SDKのペイウォールビルダーのトラブルシューティング" description: "Flutter SDKのペイウォールビルダーのトラブルシューティング" --- このガイドでは、Flutter SDK でAdapty ペイウォールビルダーを使用してデザインしたペイウォールを利用する際によく発生する問題の解決方法を説明します。 ## ペイウォール設定の取得に失敗する \{#getting-a-paywall-configuration-fails\} **問題**: `createPaywallView` メソッドがペイウォール設定の取得に失敗する。 **原因**: ペイウォールビルダーでデバイス表示が有効になっていない。 **解決策**: ペイウォールビルダーで **Show on device** トグルを有効にしてください。 <img src="/assets/shared/img/show-on-device.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## ペイウォールのビュー数が多すぎる \{#the-paywall-view-number-is-too-big\} **問題**: ペイウォールのビュー数が想定の2倍になっている。 **原因**: コード内で `logShowPaywall` を呼び出している可能性があります。ペイウォールビルダーを使用している場合、これによりビュー数が重複してしまいます。ペイウォールビルダーでデザインされたペイウォールはアナリティクスが自動的に記録されるため、このメソッドを使用する必要はありません。 **解決策**: ペイウォールビルダーを使用している場合は、コード内で `logShowPaywall` を呼び出していないことを確認してください。 ## その他の問題 \{#other-issues\} **問題**: 上記に記載されていないペイウォールビルダー関連の問題が発生している。 **解決策**: 必要に応じて[移行ガイド](flutter-sdk-migration-guides)を参考にSDKを最新バージョンに移行してください。多くの問題は新しいSDKバージョンで解決されています。 --- # File: flutter-quickstart-manual --- --- title: "Flutter SDKでカスタムペイウォールの購入機能を有効にする" description: "Adapty SDKをFlutterのカスタムペイウォールに統合して、アプリ内課金を有効にします。" --- このガイドでは、Adaptyをカスタムペイウォールに統合する方法を説明します。ペイウォールの実装を完全にコントロールしながら、Adapty SDKがプロダクトの取得、新規購入の処理、過去の購入の復元を担います。 :::important **このガイドはカスタムペイウォールを実装する開発者向けです。** 最も簡単に購入機能を有効にしたい場合は、[Adapty ペイウォールビルダー](flutter-quickstart-paywalls)をご利用ください。ペイウォールビルダーを使えば、ノーコードのビジュアルエディターでペイウォールを作成でき、Adaptyがすべての購入ロジックを自動で処理します。また、アプリを再公開することなく異なるデザインをテストできます。 ::: ## 始める前に \{#before-you-start\} ### プロダクトのセットアップ \{#set-up-products\} アプリ内課金を有効にするには、3つの重要な概念を理解する必要があります。 - [**プロダクト**](product) – ユーザーが購入できるもの(サブスクリプション、消耗型アイテム、永続アクセスなど) - [**ペイウォール**](paywalls) – 提供するプロダクトを定義する設定。Adaptyではペイウォールを通じてのみプロダクトを取得できますが、この設計によりアプリのコードを変更せずにプロダクト、価格、オファーを変更できます。 - [**プレースメント**](placements) – アプリ内でペイウォールを表示する場所とタイミング(`main`、`onboarding`、`settings` など)。ダッシュボードでプレースメントにペイウォールを設定し、コード内でプレースメントIDを使ってリクエストします。これにより、A/Bテストの実施や異なるユーザーへの異なるペイウォールの表示が簡単になります。 カスタムペイウォールを使用する場合でも、これらの概念を理解しておくことが重要です。基本的には、アプリで販売するプロダクトを管理するための手段です。 カスタムペイウォールを実装するには、**ペイウォール**を作成して**プレースメント**に追加する必要があります。この設定でプロダクトを取得できるようになります。ダッシュボードで必要な作業を理解するには、[こちら](quickstart)のクイックスタートガイドをご覧ください。 ### ユーザーの管理 \{#manage-users\} バックエンド認証の有無にかかわらず利用できます。 ただし、Adapty SDKは匿名ユーザーと識別済みユーザーを異なる方法で扱います。詳細を確認してユーザーを適切に扱えるよう、[識別クイックスタートガイド](flutter-quickstart-identify)をご覧ください。 ## ステップ1. プロダクトを取得する \{#step-1-get-products\} カスタムペイウォール用のプロダクトを取得するには、次の手順を実行します。 1. `getPaywall` メソッドに[プレースメント](placements)IDを渡して `paywall` オブジェクトを取得する。 2. `getPaywallProducts` メソッドを使ってそのペイウォールのプロダクト配列を取得する。 ```dart showLineNumbers Future<void> loadPaywall() async { try { final paywall = await Adapty().getPaywall(placementId: 'YOUR_PLACEMENT_ID'); final products = await Adapty().getPaywallProducts(paywall: paywall); // Use products to build your custom paywall UI } on AdaptyError catch (adaptyError) { // Handle the error } catch (e) { // Handle the error } } ``` ## ステップ2. 購入を受け付ける \{#step-2-accept-purchases\} ユーザーがカスタムペイウォールでプロダクトをタップしたら、選択したプロダクトを引数に `makePurchase` メソッドを呼び出します。これにより購入フローが処理され、更新されたプロファイルが返されます。 ```dart showLineNumbers Future<void> purchaseProduct(AdaptyPaywallProduct product) async { try { final purchaseResult = await Adapty().makePurchase(product: product); switch (purchaseResult) { case AdaptyPurchaseResultSuccess(profile: final profile): // Purchase successful, profile updated break; case AdaptyPurchaseResultUserCancelled(): // User canceled the purchase break; case AdaptyPurchaseResultPending(): // Purchase is pending (e.g., user will pay offline with cash) break; } } on AdaptyError catch (adaptyError) { // Handle the error } catch (e) { // Handle the error } } ``` ## ステップ3. 購入を復元する \{#step-3-restore-purchases\} アプリストアは、サブスクリプションを提供するすべてのアプリに対して、ユーザーが購入を復元できる方法を提供することを求めています。 ユーザーが復元ボタンをタップしたら `restorePurchases` メソッドを呼び出します。これにより購入履歴がAdaptyと同期され、更新されたプロファイルが返されます。 ```dart showLineNumbers Future<void> restorePurchases() async { try { final profile = await Adapty().restorePurchases(); // Restore successful, profile updated } on AdaptyError catch (adaptyError) { // Handle the error } catch (e) { // Handle the error } } ``` ## 次のステップ \{#next-steps\} --- no_index: true --- import Callout from '../../../components/Callout.astro'; <Callout type="tip"> ご質問やお困りのことがあれば、[サポートフォーラム](https://adapty.featurebase.app/)をご覧ください。よくある質問への回答を見つけたり、ご自身の質問を投稿することができます。チームとコミュニティがサポートいたします! </Callout> ペイウォールをアプリで表示する準備が整いました。[App Storeサンドボックス](test-purchases-in-sandbox)または[Google Play Store](testing-on-android)でテスト購入が正しく完了できることを確認してください。本番環境に近い実装例については、サンプルアプリの[PurchasesObserver](https://github.com/adaptyteam/AdaptySDK-Flutter/blob/master/example/lib/purchase_observer.dart)を参照してください。エラーハンドリング、UIオブザーバー、包括的なSDK統合を含む購入処理の実装例が確認できます。 次は、[ユーザーが購入を完了しているか確認する](flutter-check-subscription-status)ことで、ペイウォールを表示すべきか有料機能へのアクセスを許可すべきかを判断できます。 --- # File: fetch-paywalls-and-products-flutter --- --- title: "Flutter SDKでリモートコンフィグペイウォールのペイウォールとプロダクトを取得する" description: "Adapty Flutter SDKでペイウォールとプロダクトを取得してユーザーの収益化を強化する。" --- リモートコンフィグやカスタムペイウォールを表示する前に、それらの情報を取得する必要があります。このトピックはリモートコンフィグおよびカスタムペイウォールに関するものです。ペイウォールビルダーでカスタマイズされたペイウォールの取得については、[ペイウォールビルダーのペイウォールと設定の取得](flutter-get-pb-paywalls)を参照してください。 :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: <details> <summary>モバイルアプリでペイウォールとプロダクトの取得を始める前に(クリックして展開)</summary> 1. Adapty ダッシュボードで[プロダクトを作成](create-product)します。 2. Adapty ダッシュボードで[ペイウォールを作成し、プロダクトをペイウォールに追加](create-paywall)します。 3. Adapty ダッシュボードで[プレースメントを作成し、ペイウォールをプレースメントに追加](create-placement)します。 4. モバイルアプリに[Adapty SDKをインストール](sdk-installation-flutter)します。 </details> ## ペイウォール情報の取得 \{#fetch-paywall-information\} Adaptyでは、[プロダクト](product)はApp StoreとGoogle Play両方のプロダクトを組み合わせたものです。これらのクロスプラットフォームプロダクトはペイウォールに統合され、モバイルアプリの特定のプレースメントで表示できます。 プロダクトを表示するには、`getPaywall`メソッドを使って[プレースメント](placements)のいずれかから[ペイウォール](paywalls)を取得する必要があります。 :::important **プロダクトIDをハードコードしないでください。** ハードコードすべきIDはプレースメントIDのみです。ペイウォールはリモートで設定されるため、プロダクト数や利用可能なオファーはいつでも変更される可能性があります。アプリはこれらの変更を動的に処理する必要があります。今日ペイウォールが2つのプロダクトを返し、明日3つを返した場合も、コードを変更せずにすべてを表示してください。 ::: ```dart showLineNumbers try { final paywall = await Adapty().getPaywall(id: "YOUR_PLACEMENT_ID", locale: "en"); // the requested paywall } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` | パラメーター | 必須 | 説明 | |---------|--------|-----------| | **placementId** | 必須 | [プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** | <p>任意</p><p>デフォルト: `en`</p> | <p>[ペイウォールのローカライズ](add-remote-config-locale)の識別子。マイナス(**-**)文字で区切られた1つ以上のサブタグで構成される言語コードを指定します。最初のサブタグは言語、2番目は地域を表します。</p><p></p><p>例:`en`は英語、`pt-br`はブラジルポルトガル語を表します。</p><p></p><p>ロケールコードの詳細と推奨される使用方法については、[ローカライズとロケールコード](flutter-localizations-and-locale-codes)を参照してください。</p> | | **fetchPolicy** | デフォルト: `.reloadRevalidatingCacheData` | <p>デフォルトでは、SDKはサーバーからデータを読み込もうとし、失敗した場合はキャッシュされたデータを返します。ユーザーが常に最新のデータを取得できるため、この設定を推奨します。</p><p></p><p>ただし、ユーザーがインターネット接続の不安定な環境にいると思われる場合は、`.returnCacheDataElseLoad`を使用してキャッシュデータが存在する場合に返すことを検討してください。このシナリオでは、ユーザーは最新データを取得できないことがありますが、インターネット接続が不安定でも読み込みが速くなります。キャッシュは定期的に更新されるため、ネットワークリクエストを避けるためにセッション中に使用しても安全です。</p><p></p><p>キャッシュはアプリの再起動後も保持され、アプリの再インストールまたは手動でのクリーンアップ時にのみクリアされます。</p><p></p><p>Adapty SDKはペイウォールを2層で保存しています:上記の定期更新キャッシュと[フォールバックペイウォール](flutter-use-fallback-paywalls)です。また、ペイウォールをより速く取得するためにCDNを使用し、CDNが利用できない場合のスタンドアロンフォールバックサーバーも用意しています。このシステムは、インターネット接続が乏しい場合でも信頼性を確保しながら、常に最新バージョンのペイウォールを取得できるように設計されています。</p> | | **loadTimeout** | デフォルト: 5秒 | <p>このメソッドのタイムアウト上限を設定します。タイムアウトに達した場合、キャッシュデータまたはローカルフォールバックが返されます。</p><p></p><p>内部で複数のリクエストで構成される場合があるため、まれに`loadTimeout`で指定した時間よりわずかに遅れてタイムアウトすることがあります。</p> | プロダクトIDをハードコードしないでください!ペイウォールはリモートで設定されるため、利用可能なプロダクト、プロダクト数、特別オファー(無料トライアルなど)は随時変更される可能性があります。これらのシナリオに対応できるコードを書いてください。 例えば、最初に2つのプロダクトを取得する場合、アプリはその2つを表示してください。後で3つのプロダクトを取得した場合は、コードを変更せずに3つすべてを表示してください。ハードコードすべき唯一のものはプレースメントIDです。 レスポンスパラメーター: | パラメーター | 説明 | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- | | Paywall | プロダクトIDのリスト、ペイウォール識別子、リモートコンフィグ、その他いくつかのプロパティを含む[`AdaptyPaywall`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyPaywall-class.html)オブジェクト。 | ## プロダクトの取得 \{#fetch-products\} ペイウォールを取得したら、それに対応するプロダクトの配列を取得できます: ```dart showLineNumbers try { final products = await Adapty().getPaywallProducts(paywall: paywall); // the requested products array } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` レスポンスパラメーター: | パラメーター | 説明 | | :-------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Products | プロダクト識別子、プロダクト名、価格、通貨、サブスクリプション期間、その他いくつかのプロパティを含む[`AdaptyPaywallProduct`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyPaywallProduct-class.html)オブジェクトのリスト。 | 独自のペイウォールデザインを実装する場合、[`AdaptyPaywallProduct`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyPaywallProduct-class.html)オブジェクトのプロパティにアクセスする必要があるでしょう。以下によく使われるプロパティを示しますが、すべての利用可能なプロパティの詳細はリンク先のドキュメントを参照してください。 | プロパティ | 説明 | |-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Title** | プロダクトのタイトルを表示するには、`product.localizedTitle`を使用します。ローカライズはデバイスのロケールではなく、ユーザーが選択したストアの国に基づいています。 | | **Price** | ローカライズされた価格を表示するには、`product.price.localizedString`を使用します。このローカライズはデバイスのロケール情報に基づいています。`product.price.amount`で数値として価格にアクセスすることもできます。値はローカル通貨で提供されます。関連する通貨記号を取得するには、`product.price.currencySymbol`を使用します。 | | **Subscription Period** | 期間(週、月、年など)を表示するには、`product.subscription?.localizedPeriod`を使用します。このローカライズはデバイスのロケールに基づいています。プログラムでサブスクリプション期間を取得するには、`product.subscription?.period`を使用します。そこから`unit`列挙型にアクセスして長さ(日、週、月、年、または不明)を取得できます。`numberOfUnits`の値で期間の単位数を取得できます。例えば、四半期サブスクリプションの場合、unitプロパティには`AdaptyPeriodUnit.month`、numberOfUnitsプロパティには`3`が表示されます。 | | **Introductory Offer** | サブスクリプションに初回オファーが含まれていることを示すバッジなどを表示するには、`product.subscription?.offer?.phases`プロパティを確認してください。これは最大2つの割引フェーズ(無料トライアルフェーズと初回価格フェーズ)を含むことができるリストです。各フェーズオブジェクトには以下の便利なプロパティがあります:<br/>• `paymentMode`:`AdaptyPaymentMode.freeTrial`、`AdaptyPaymentMode.payAsYouGo`、`AdaptyPaymentMode.payUpFront`、`AdaptyPaymentMode.unknown`の値を持つ列挙型。無料トライアルは`AdaptyPaymentMode.freeTrial`タイプです。<br/>• `price`:数値としての割引価格。無料トライアルの場合は`0`になります。<br/>• `localizedNumberOfPeriods`:オファーの長さをデバイスのロケールでローカライズした文字列。例えば、3日間のトライアルオファーはこのフィールドに`3 days`と表示されます。<br/>• `subscriptionPeriod`:オファー期間の個別の詳細をこのプロパティで取得することもできます。オファーに対しても前のセクションと同様に機能します。<br/>• `localizedSubscriptionPeriod`:ユーザーのロケールに合わせてフォーマットされた割引のサブスクリプション期間。 | ## デフォルトオーディエンスのペイウォールでペイウォール取得を高速化する \{#speed-up-paywall-fetching-with-default-audience-paywall\} 通常、ペイウォールはほぼ即座に取得されるため、このプロセスの高速化を心配する必要はありません。ただし、多数のオーディエンスとペイウォールがあり、ユーザーのインターネット接続が弱い場合、ペイウォールの取得に予想より時間がかかることがあります。このような状況では、ペイウォールを全く表示しないよりもスムーズなユーザー体験を確保するために、デフォルトのペイウォールを表示したい場合があります。 これに対処するために、`getPaywallForDefaultAudience`メソッドを使用できます。このメソッドは**All Users**オーディエンス向けに指定されたプレースメントのペイウォールを取得します。ただし、推奨されるアプローチは上記の[ペイウォール情報の取得](fetch-paywalls-and-products-flutter#fetch-paywall-information)セクションで説明している`getPaywall`メソッドでペイウォールを取得することであることを理解することが重要です。 :::warning `getPaywall`を推奨する理由 `getPaywallForDefaultAudience`メソッドにはいくつかの重大な欠点があります: - **後方互換性の問題の可能性**:現在と将来の異なるアプリバージョンに異なるペイウォールを表示する必要がある場合、課題に直面する可能性があります。現在(レガシー)バージョンをサポートするペイウォールを設計するか、現在(レガシー)バージョンのユーザーがレンダリングされないペイウォールの問題に遭遇することを受け入れるかのどちらかになります。 - **ターゲティングの喪失**:すべてのユーザーが**All Users**オーディエンス向けに設計された同じペイウォールを見ることになり、パーソナライズされたターゲティング(国、マーケティングアトリビューション、独自のカスタム属性に基づくものを含む)が失われます。 これらの欠点を受け入れてペイウォール取得の高速化メリットを享受する場合は、以下のように`getPaywallForDefaultAudience`メソッドを使用してください。そうでない場合は、[上記](fetch-paywalls-and-products-flutter#fetch-paywall-information)で説明した`getPaywall`を使用してください。 ::: :::note `getPaywallForDefaultAudience`メソッドはFlutter SDKではまだサポートされていませんが、近日中にサポートが追加される予定です。 ::: | パラメーター | 必須 | 説明 | |---------|--------|-----------| | **placementId** | 必須 | [プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** | <p>任意</p><p>デフォルト: `en`</p> | <p>[ペイウォールのローカライズ](add-remote-config-locale)の識別子。マイナス(**-**)文字で区切られた1つ以上のサブタグで構成される言語コードを指定します。最初のサブタグは言語、2番目は地域を表します。</p><p></p><p>例:`en`は英語、`pt-br`はブラジルポルトガル語を表します。</p><p></p><p>ロケールコードの詳細と推奨される使用方法については、[ローカライズとロケールコード](flutter-localizations-and-locale-codes)を参照してください。</p> | | **fetchPolicy** | デフォルト: `.reloadRevalidatingCacheData` | <p>デフォルトでは、SDKはサーバーからデータを読み込もうとし、失敗した場合はキャッシュされたデータを返します。ユーザーが常に最新のデータを取得できるため、この設定を推奨します。</p><p></p><p>ただし、ユーザーがインターネット接続の不安定な環境にいると思われる場合は、`.returnCacheDataElseLoad`を使用してキャッシュデータが存在する場合に返すことを検討してください。このシナリオでは、ユーザーは最新データを取得できないことがありますが、インターネット接続が不安定でも読み込みが速くなります。キャッシュは定期的に更新されるため、ネットワークリクエストを避けるためにセッション中に使用しても安全です。</p><p></p><p>キャッシュはアプリの再起動後も保持され、アプリの再インストールまたは手動でのクリーンアップ時にのみクリアされます。</p> | --- # File: present-remote-config-paywalls-flutter --- --- title: "Flutter SDKでリモートコンフィグで設計したペイウォールを表示する" description: "Adapty Flutter SDKでリモートコンフィグペイウォールを表示し、ユーザーエクスペリエンスをパーソナライズする方法をご紹介します。" --- リモートコンフィグを使ってペイウォールをカスタマイズした場合、ユーザーに表示するためにモバイルアプリのコードでレンダリングを実装する必要があります。リモートコンフィグはニーズに合わせた柔軟性を提供するため、何を含めるか、ペイウォールビューをどのように表示するかはすべてあなたが決められます。リモートコンフィグを取得するメソッドを用意しているので、リモートコンフィグで設定したカスタムペイウォールを自由に表示できます。 ## ペイウォールのリモートコンフィグを取得して表示する \{#get-paywall-remote-config-and-present-it\} ペイウォールのリモートコンフィグを取得するには、`remoteConfig` プロパティにアクセスして必要な値を取り出します。 ```dart showLineNumbers try { final paywall = await Adapty().getPaywall(id: "YOUR_PLACEMENT_ID"); final String? headerText = paywall.remoteConfig?.dictionary?['header_text'] as String?; } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` 必要な値をすべて取得したら、それらをレンダリングして視覚的に魅力的なページに組み立てましょう。さまざまなスマートフォンの画面サイズや向きに対応したデザインにすることで、あらゆるデバイスでシームレスで使いやすい体験を提供できます。 :::warning 以下で説明するように、必ず[ペイウォールビューイベントを記録](present-remote-config-paywalls-flutter#track-paywall-view-events)してください。これにより、Adapty アナリティクスがファネルやA/B テスト用の情報を収集できるようになります。 ::: ペイウォールの表示が完了したら、購入フローの設定に進みます。ユーザーが購入する際は、ペイウォールのプロダクトを使って `.makePurchase()` を呼び出すだけです。`.makePurchase()` メソッドの詳細については、[購入を行う](flutter-making-purchases)をご覧ください。 [フォールバックペイウォールと呼ばれるバックアップペイウォールの作成](flutter-use-fallback-paywalls)をお勧めします。このバックアップは、インターネット接続がない場合やキャッシュが利用できない場合にユーザーに表示され、そのような状況でもスムーズな体験を確保します。 ## ペイウォールビューイベントを記録する \{#track-paywall-view-events\} Adapty はペイウォールのパフォーマンス測定をサポートしています。購入データは自動的に収集されますが、ペイウォールビューのログ記録はあなたの入力が必要です。顧客がペイウォールを見たタイミングを把握しているのはあなただけだからです。 ペイウォールビューイベントをログに記録するには、`.logShowPaywall(paywall)` を呼び出すだけです。ファネルやA/B テストのペイウォール指標に反映されます。 :::important [ペイウォールビルダー](adapty-paywall-builder)で作成したペイウォールを表示している場合は、`.logShowPaywall(paywall)` を呼び出す必要はありません。 ::: ```dart showLineNumbers try { final result = await Adapty().logShowPaywall(paywall: paywall); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` リクエストパラメータ: | パラメータ | 必須かどうか | 説明 | | :---------- | :------- |:----------------------------------------------------------------------| | **paywall** | 必須 | [`AdaptyPaywall`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyPaywall-class.html) オブジェクト。 | --- # File: flutter-making-purchases --- --- title: "Flutter SDKでモバイルアプリの購入を行う" description: "Adaptyを使ったアプリ内課金とサブスクリプションの処理に関するガイド。" --- モバイルアプリ内にペイウォールを表示することは、プレミアムコンテンツやサービスへのアクセスをユーザーに提供するための重要なステップです。ただし、ペイウォールの表示だけで購入をサポートできるのは、[ペイウォールビルダー](adapty-paywall-builder)を使ってペイウォールをカスタマイズしている場合に限られます。 ペイウォールビルダーを使用しない場合は、`.makePurchase()` という別のメソッドを使って購入を完了し、コンテンツのロックを解除する必要があります。このメソッドは、ユーザーがペイウォールを操作し、目的の取引を進めるための入口となります。 ペイウォールに、ユーザーが購入しようとしているプロダクトに対するアクティブなプロモーションオファーがある場合、Adapty は購入時に自動的にそれを適用します。 :::warning 初回オファーが自動的に適用されるのは、ペイウォールビルダーで設定したペイウォールを使用している場合のみです。 それ以外の場合は、[iOS での初回オファーの利用資格をユーザーが持つかどうかを確認](fetch-paywalls-and-products#check-intro-offer-eligibility-on-ios)する必要があります。このステップをスキップすると、リリース時にアプリが審査で却下される可能性があります。また、初回オファーの対象ユーザーに通常価格が請求されてしまう恐れもあります。 ::: まず、一切のステップを省略せずに[初期設定](quickstart)を完了していることを確認してください。これが完了していなければ、購入の検証ができません。 ## 購入する \{#make-purchase\} :::note **[ペイウォールビルダー](adapty-paywall-builder)を使用していますか?** 購入は自動的に処理されるため、このステップはスキップできます。 **ステップごとのガイダンスをお探しですか?** 完全なコンテキストを含むエンドツーエンドの実装手順については、[クイックスタートガイド](flutter-implement-paywalls-manually)をご確認ください。 ::: ```dart showLineNumbers try { final purchaseResult = await Adapty().makePurchase(product: product); switch (purchaseResult) { case AdaptyPurchaseResultSuccess(profile: final profile): if (profile.accessLevels['premium']?.isActive ?? false) { // Grant access to the paid features } break; case AdaptyPurchaseResultPending(): break; case AdaptyPurchaseResultUserCancelled(): break; default: break; } } on AdaptyError catch (adaptyError) { // Handle the error } catch (e) { // Handle the error } ``` リクエストパラメータ: | パラメータ | 必須/任意 | 説明 | | :---------- | :------- | :-------------------------------------------------------------------------------------------------- | | **Product** | 必須 | ペイウォールから取得した [`AdaptyPaywallProduct`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyPaywallProduct-class.html) オブジェクト。 | レスポンスパラメータ: | パラメータ | 説明 | |---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Profile** | <p>リクエストが成功した場合、レスポンスにはこのオブジェクトが含まれます。[AdaptyProfile](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyProfile-class.html) オブジェクトは、アプリ内でのユーザーのアクセスレベル、サブスクリプション、非サブスクリプション購入に関する包括的な情報を提供します。</p><p>ユーザーが必要なアクセス権を持っているかどうかを確認するために、アクセスレベルのステータスをチェックしてください。</p> | :::warning **注意:** Apple の StoreKit バージョン 2.0 未満、かつ Adapty SDK バージョン v2.9.0 未満をお使いの場合は、代わりに [Apple App Store 共有シークレット](app-store-connection-configuration#step-5-enter-app-store-shared-secret)を指定する必要があります。この方法は現在 Apple によって非推奨となっています。 ::: ## 購入時のサブスクリプション変更 \{#change-subscription-when-making-a-purchase\} ユーザーが現在のサブスクリプションを更新せず、新しいサブスクリプションを選択した場合の動作は、アプリストアによって異なります。 - App Store では、サブスクリプショングループ内でサブスクリプションが自動的に更新されます。ユーザーがあるグループのサブスクリプションを購入しつつ、別のグループのサブスクリプションをすでに持っている場合、両方のサブスクリプションが同時にアクティブになります。 - Google Play では、サブスクリプションは自動的に更新されません。以下に説明するように、モバイルアプリのコードで切り替えを管理する必要があります。 Android でサブスクリプションを別のものに切り替えるには、追加パラメータを指定して `.makePurchase()` メソッドを呼び出してください。 ```dart showLineNumbers try { final result = await adapty.makePurchase( product: product, subscriptionUpdateParams: subscriptionUpdateParams, ); // successful cross-grade } on AdaptyError catch (adaptyError) { // Handle the error } catch (e) { // Handle the error } ``` 追加リクエストパラメータ: | パラメータ | 必須/任意 | 説明 | | :--------------------------- | :------- |:--------------------------------------------------------------------------------------------------------| | **subscriptionUpdateParams** | 必須 | [`AdaptyAndroidSubscriptionUpdateParameters`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyAndroidSubscriptionUpdateParameters-class.html) オブジェクト。 | サブスクリプションと置き換えモードについては、Google デベロッパードキュメントを参照してください。 - [置き換えモードについて](https://developer.android.com/google/play/billing/subscriptions#replacement-modes) - [置き換えモードに関する Google の推奨事項](https://developer.android.com/google/play/billing/subscriptions#replacement-recommendations) - 置き換えモード [`CHARGE_PRORATED_PRICE`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode#CHARGE_PRORATED_PRICE())。注意:このメソッドはサブスクリプションのアップグレード時のみ使用できます。ダウングレードはサポートされていません。 - 置き換えモード [`DEFERRED`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode#DEFERRED())。注意:実際のサブスクリプション変更は、現在のサブスクリプションの請求期間が終了したときにのみ発生します。 ## iOS でオファーコードを利用する \{#redeem-offer-codes-in-ios\} --- no_index: true --- import Callout from '../../../components/Callout.astro'; <Details> <summary>オファーコードについて</summary> オファーコードを使うと、特定のユーザーに割引や無料トライアルを提供できます。自動的に適用される通常のオファーとは異なり、オファーコードはメールキャンペーン、SNS、印刷物など、アプリの外で配布します。ユーザーはApp Storeでコードを入力するか、引き換えURLを使うか、アプリ内ダイアログから利用できます。 オファーコードを設定するには、App Store Connectでサブスクリプションを開き、**Offer Codes** セクションに移動してください。オファーコードは[3種類](https://developer.apple.com/help/app-store-connect/manage-subscriptions/set-up-subscription-offer-codes)作成できます。 - **Free** — 指定した期間はサブスクリプションが無料になり、次の更新から通常価格になります。 - **Pay as you go** — 指定した期間、各請求サイクルに割引価格が適用され、その後は通常価格で更新されます。 - **Pay up front** — オファー期間全体に対して一括で割引価格を支払い、その後は通常価格で更新されます。 オファーコードをAdaptyに追加する必要はありません。Appleはオファー期間中のすべてのトランザクションにオファーコードカテゴリのタグを付与します。これには最初の引き換えとその後の割引更新がすべて含まれます。Adaptyはこのタグを検出し、各トランザクションをオファーカテゴリ `offer_code` として記録します。オファー期間が終了してサブスクリプションが通常価格で更新されると、タグは付与されなくなります。[Adapty ダッシュボード](controls-filters-grouping-compare-proceeds)のアナリティクスで **Offer Code** オファータイプによるフィルタリングが可能です。 #### 収益の差異が生じた場合のトラブルシューティング \{#revenue-discrepancy-troubleshooting\} オファーコードのトランザクションが、割引価格ではなく通常価格でAdaptyに記録されている場合は、App Store Connectで以下を確認してください。 - オファーコードに、ユーザーが引き換え可能なすべての地域に対して正しい価格が設定されているか。 - ユーザーの特定の国や地域に対してオファー価格が設定されているか。Appleはトランザクションに地域価格を含めて送信します。その地域のオファー価格が設定されていない場合、Appleは通常価格を送信することがあります。 [Adapty ダッシュボード](controls-filters-grouping-compare-proceeds)で、**Offer Code** オファータイプと **Offer Discount Type** フィルターを使ってオファーコードのトランザクションをフィルタリング・確認できます。 #### レガシープロモコード(非推奨) \{#legacy-promo-codes-deprecated\} <Callout type="warning"> Appleは2026年3月にアプリ内課金向けのプロモコードを廃止しました。オファーコードはより多くの機能(適格性の設定、有効期限、四半期あたり最大100万コード)を備えた後継機能です。アプリ内課金にプロモコードを使用していた場合は、App Store Connectでオファーコードに移行してください。 </Callout> レガシープロモコード(アプリのバージョンごとに最大100件)は、サブスクリプションへの無料アクセスを付与していました。オファーコードとは異なり、Appleはプロモコードのトランザクションに割引情報を含めず、レシートには通常価格が記載されていました。そのため、Adaptyはこれらのトランザクションを通常価格で記録し、Adaptyアナリティクスとレポートの間に収益の差異が生じていました。 本来は無料であるべきトランザクションが通常価格で記録されている履歴がある場合、それはレガシープロモコードによるものと考えられます。これらのコードは現在廃止されているため、正確な収益追跡のためにオファーコードに移行してください。 </Details> アプリにコード引き換えシートを表示するには: ```dart showLineNumbers try { await Adapty().presentCodeRedemptionSheet(); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` :::danger 私たちの観察では、一部のアプリではオファーコード引き換えシートが正常に機能しないことがあります。ユーザーを直接 App Store にリダイレクトすることをお勧めします。 そのためには、以下の形式の URL を開く必要があります: `https://apps.apple.com/redeem?ctx=offercodes&id={apple_app_id}&code={code}` ::: ### プリペイドプランの管理(Android) \{#manage-prepaid-plans-android\} アプリのユーザーが[プリペイドプラン](https://developer.android.com/google/play/billing/subscriptions#prepaid-plans)(例:数ヶ月分の非更新型サブスクリプションを一括購入)を利用できる場合、プリペイドプランの[保留中のトランザクション](https://developer.android.com/google/play/billing/subscriptions#pending)を有効にすることができます。 ```dart showLineNumbers title="main.dart" await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_PUBLIC_SDK_KEY') ..withGoogleEnablePendingPrepaidPlans(true), ); ``` --- # File: flutter-restore-purchase --- --- title: "Flutter SDKでアプリ内購入を復元する" description: "Adaptyで購入を復元し、シームレスなユーザー体験を確保する方法を学びましょう。" --- iOSとAndroidの両方における購入の復元は、ユーザーがサブスクリプションやアプリ内課金などの以前に購入したコンテンツに、再度課金されることなく再アクセスできるようにする機能です。この機能は、アプリをアンインストールして再インストールしたユーザーや、新しいデバイスに切り替えたユーザーが、再度支払いをせずに以前に購入したコンテンツにアクセスしたい場合に特に便利です。 :::note [ペイウォールビルダー](adapty-paywall-builder)で作成したペイウォールでは、追加のコードなしに購入が自動的に復元されます。その場合は、このステップをスキップできます。 ::: [ペイウォールビルダー](adapty-paywall-builder)を使用してペイウォールをカスタマイズしていない場合に購入を復元するには、`.restorePurchases()` メソッドを呼び出してください: ```javascript showLineNumbers try { final profile = await Adapty().restorePurchases(); if (profile?.accessLevels['YOUR_ACCESS_LEVEL']?.isActive ?? false) { // successful access restore } } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` レスポンスパラメーター: | パラメーター | 説明 | |---------|-----------| | **Profile** | <p>[`AdaptyProfile`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyProfile-class.html) オブジェクト。このモデルにはアクセスレベル、サブスクリプション、および買い切り購入に関する情報が含まれています。</p><p>ユーザーがアプリへのアクセス権を持っているかどうかを確認するには、**アクセスレベルのステータス**を確認してください。</p> | :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: --- # File: implement-observer-mode-flutter --- --- title: "Flutter SDKでObserverモードを実装する" description: "AdaptyのObserverモードを実装してFlutter SDKでユーザーのサブスクリプションイベントを追跡します。" --- すでに独自の購入インフラをお持ちで、すぐにAdaptyへ完全移行する準備ができていない場合は、[Observerモード](observer-vs-full-mode)を検討してみてください。基本的な使い方では、Observerモードは高度なアナリティクスとアトリビューション・アナリティクスシステムとのシームレスな連携を提供します。 これで十分であれば、必要な作業は次の2つだけです。 1. Adapty SDKの設定時に`observerMode`パラメータを`true`に設定してObserverモードをオンにします。[Flutter](sdk-installation-flutter#activate-adapty-module-of-adapty-sdk)のセットアップ手順に従ってください。 2. 既存の購入インフラから[トランザクションをAdaptyに報告する](report-transactions-observer-mode-flutter)。 ## Observerモードのセットアップ \{#observer-mode-setup\} 購入状態とサブスクリプションステータスを自分で管理し、Adaptyをサブスクリプションイベントやアナリティクスの送信に使用する場合は、Observerモードをオンにします。 :::important Observerモードで動作している場合、Adapty SDKはトランザクションを閉じません。そのため、必ずご自身でトランザクションの処理を行ってください。 ::: ```dart showLineNumbers title="main.dart" await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_PUBLIC_SDK_KEY') ..withObserverMode(true) // Enable observer mode ..withLogLevel(AdaptyLogLevel.verbose), ); ``` パラメータ: | パラメータ | 説明 | | --------------------------- | ------------------------------------------------------------ | | observerMode | [Observerモード](observer-vs-full-mode)を制御するboolean値。デフォルト値は`false`です。 | ## ObserverモードでAdaptyのペイウォールを使用する \{#using-adapty-paywalls-in-observer-mode\} Adatyのペイウォールやa/bテスト機能も使用したい場合は可能ですが、Observerモードでは追加のセットアップが必要です。上記の手順に加えて、以下を行う必要があります。 1. [リモートコンフィグペイウォール](present-remote-config-paywalls-flutter)と同様にペイウォールを表示します。 3. 購入トランザクションに[ペイウォールを関連付けます](report-transactions-observer-mode-flutter)。 --- # File: report-transactions-observer-mode-flutter --- --- title: "Flutter SDKのオブザーバーモードでトランザクションを報告する" description: "Flutter SDKのAdaptyオブザーバーモードで購入トランザクションを報告し、ユーザーインサイトと収益追跡を行います。" --- <Tabs groupId="sdk-version" queryString> <TabItem value="current" label="Adapty SDK v3.4+(現行版)" default> オブザーバーモードでは、Adapty SDKは既存の購入システムで行われた購入を自動で追跡することができません。アプリストアからのトランザクションを手動で報告する必要があります。分析エラーを避けるため、アプリをリリースする**前**にこの設定を行うことが重要です。 `reportTransaction`を使用して、Adaptyがトランザクションを認識できるよう各トランザクションを明示的に報告してください。 :::warning **トランザクション報告をスキップしないでください!** `reportTransaction`を呼び出さない場合、Adaptyはトランザクションを認識できず、分析に表示されず、インテグレーションにも送信されません。 ::: Adaptyのペイウォールを使用している場合は、トランザクション報告時に`variationId`を含めてください。これにより購入が対象のペイウォールに紐づき、正確なペイウォール分析が可能になります。 ```javascript showLineNumbers try { // every time when calling transaction.finish() await Adapty().reportTransaction( "YOUR_TRANSACTION_ID", variationId: "PAYWALL_VARIATION_ID", // optional ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` パラメーター: | パラメーター | 必須/任意 | 説明 | | ------------- | --------- | ------------------------------------------------------------ | | transactionId | 必須 | <ul><li> iOS の場合:トランザクションの識別子。</li><li> Android の場合:購入の文字列識別子 `purchase.getOrderId`。ここで purchase は billing library の [Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase) クラスのインスタンスです。</li></ul> | | variationId | 任意 | バリアントの文字列識別子。[AdaptyPaywall](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyPaywall-class.html) オブジェクトの `variationId` プロパティから取得できます。 | </TabItem> <TabItem value="old" label="Adapty SDK 3.3.x(レガシー)" default> オブザーバーモードでは、Adapty SDKは既存の購入システムで行われた購入を自動で追跡することができません。アプリストアからのトランザクションを報告するか、復元する必要があります。分析エラーを避けるため、アプリをリリースする**前**にこの設定を行うことが重要です。 両プラットフォームで`reportTransaction`を使用して各トランザクションを明示的に報告し、Android では追加手順として`restorePurchases`を使用してAdaptyがトランザクションを認識できるようにしてください。 :::warning **トランザクション報告と購入の復元をスキップしないでください!** これらのメソッドを呼び出さない場合、Adaptyはトランザクションを認識できず、分析に表示されず、インテグレーションにも送信されません。 ::: Adaptyのペイウォールを使用している場合は、トランザクション報告時に`variationId`を含めてください。これにより購入が対象のペイウォールに紐づき、正確なペイウォール分析が可能になります。 ```javascript showLineNumbers // every time when calling transaction.finish() if (Platform.isAndroid) { try { await Adapty().restorePurchases(); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } } try { // every time when calling transaction.finish() await Adapty().reportTransaction( "YOUR_TRANSACTION_ID", variationId: "PAYWALL_VARIATION_ID", // optional ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` パラメーター: | パラメーター | 必須/任意 | 説明 | | ------------- | --------- | ------------------------------------------------------------ | | transactionId | 必須 | <ul><li> iOS、StoreKit 1 の場合:[SKPaymentTransaction](https://developer.apple.com/documentation/storekit/skpaymenttransaction) オブジェクト。</li><li> iOS、StoreKit 2 の場合:[Transaction](https://developer.apple.com/documentation/storekit/transaction) オブジェクト。</li><li> Android の場合:文字列識別子(purchase.getOrderId)。ここで purchase は billing library の [Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase) クラスのインスタンスです。</li></ul> | | variationId | 任意 | バリアントの文字列識別子。[AdaptyPaywall](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyPaywall-class.html) オブジェクトの `variationId` プロパティから取得できます。 | </TabItem> <TabItem value="old2" label="Adapty SDK 3.2.x 以前(レガシー)" default> <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS" default> **トランザクションの報告** - 3.1.x 以前のバージョンはApp Storeのトランザクションを自動でリッスンするため、手動での報告は不要です。 - バージョン 3.2 はオブザーバーモードをサポートしていません。 </TabItem> <TabItem value="kotlin" label="Android および Android ベースのクロスプラットフォーム" default> **トランザクションの報告** オブザーバーモードでAdaptyにトランザクションを報告するには、[モバイルコードでの購入の復元](flutter-restore-purchase)ページで説明しているとおり、`restorePurchases`を使用してください。 :::warning **トランザクション報告をスキップしないでください!** `restorePurchases`を呼び出さない場合、Adaptyはトランザクションを認識できず、分析に表示されず、インテグレーションにも送信されません。 ::: </TabItem> </Tabs> **ペイウォールとトランザクションの紐付け** Adapty SDKは購入のソースを特定することができません。購入処理はお客様自身が行うためです。そのため、オブザーバーモードでペイウォールやA/B テストを使用する場合は、アプリストアから受け取ったトランザクションをモバイルアプリのコード内で対応するペイウォールに紐付ける必要があります。アプリリリース前にこの設定を正しく行わないと、分析エラーが発生します。 ```javascript final transactionId = transaction.transactionIdentifier final variationId = paywall.variationId try { await Adapty().setVariationId('transactionId', variationId); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` </TabItem> </Tabs> --- # File: flutter-troubleshoot-purchases --- --- title: "Flutter SDKでの購入のトラブルシューティング" description: "Flutter SDKでの購入のトラブルシューティング" --- このガイドでは、Flutter SDKで手動購入を実装する際によく発生する問題の解決方法を説明します。 ## makePurchaseは正常に呼び出されたが、プロファイルが更新されない \{#makepurchase-is-called-successfully-but-the-profile-is-not-being-updated\} **問題**: `makePurchase` メソッドが正常に完了したにもかかわらず、ユーザーのプロファイルとサブスクリプションのステータスがAdaptyで更新されません。 **原因**: これは通常、Google Play ストアのセットアップが不完全またはコンフィグレーションに問題があることを示しています。 **解決策**: [Google Playのセットアップ手順](initial-android)をすべて完了していることを確認してください。 ## makePurchaseが2回呼び出される \{#makepurchase-is-invoked-twice\} **問題**: 同じ購入に対して `makePurchase` メソッドが複数回呼び出されています。 **原因**: これは通常、UIの状態管理の問題やユーザーの素早い操作によって購入フローが複数回トリガーされたときに発生します。 **解決策**: [Google Playのセットアップ手順](initial-android)をすべて完了していることを確認してください。 ## オブザーバーモードでのAdaptyError.cantMakePayments \{#adaptyerrorcantmakepayments-in-observer-mode\} **問題**: オブザーバーモードで `makePurchase` を使用すると `AdaptyError.cantMakePayments` が発生します。 **原因**: オブザーバーモードでは、Adaptyの `makePurchase` メソッドを使用するのではなく、購入処理をご自身で行う必要があります。 **解決策**: 購入に `makePurchase` を使用している場合は、オブザーバーモードをオフにしてください。`makePurchase` を使用するか、オブザーバーモードで購入を自分で処理するか、どちらか一方を選ぶ必要があります。詳細については、[オブザーバーモードの実装](implement-observer-mode-flutter)を参照してください。 ## Adaptyエラー: (code: 103, message: Play Market request failed on purchases updated: responseCode=3, debugMessage=Billing Unavailable, detail: null) \{#adapty-error-code-103-message-play-market-request-failed-on-purchases-updated-responsecode3-debugmessagebilling-unavailable-detail-null\} **問題**: Google Play ストアからbilling unavailableエラーが返されています。 **原因**: このエラーはAdaptyとは無関係です。デバイスで課金が利用できないことを示すGoogle Play課金ライブラリのエラーです。 **解決策**: このエラーはAdaptyとは無関係です。Play Storeのドキュメントで詳細を確認できます: [Handle BillingResult response codes](https://developer.android.com/google/play/billing/errors#billing_unavailable_error_code_3) | Play Billing | Android Developers。 ## makePurchasesCompletionHandlersが見つからない \{#not-found-makepurchasescompletionhandlers\} **問題**: `makePurchasesCompletionHandlers` が見つからないという問題が発生しています。 **原因**: これは通常、サンドボックステストの問題に関連しています。 **解決策**: 新しいサンドボックスユーザーを作成して再試行してください。サンドボックス関連の購入完了ハンドラーの問題はこれで解決することが多いです。 ## その他の問題 \{#other-issues\} **問題**: 上記で説明していないその他の購入関連の問題が発生しています。 **解決策**: 必要に応じて、[移行ガイド](flutter-sdk-migration-guides)を使用してSDKを最新バージョンに移行してください。新しいSDKバージョンでは多くの問題が解決されています。 --- # File: flutter-identifying-users --- --- title: "Flutter SDK でユーザーを識別する" description: "Adapty でユーザーを識別して、パーソナライズされたサブスクリプション体験を向上させましょう。" --- Adapty はすべてのユーザーに対して内部プロファイル ID を作成します。ただし、独自の認証システムがある場合は、独自の Customer User ID を設定する必要があります。[Profiles](profiles-crm) セクションで Customer User ID によってユーザーを検索でき、また[サーバーサイド API](getting-started-with-server-side-api) でも使用でき、すべてのインテグレーションに送信されます。 ### 設定時に Customer User ID を設定する \{#setting-customer-user-id-on-configuration\} 設定時にユーザー ID がある場合は、`.activate()` メソッドの `customerUserId` パラメータとして渡すだけです: ```dart showLineNumbers title="Dart" try { await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_API_KEY') ..withCustomerUserId(YOUR_CUSTOMER_USER_ID) ); } catch (e) { // handle the error } ``` :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: ### 設定後に Customer User ID を設定する \{#setting-customer-user-id-after-configuration\} SDK の設定時にユーザー ID がない場合は、`.identify()` メソッドを使っていつでも後から設定できます。このメソッドが最もよく使われるケースは、登録または認証後に匿名ユーザーから認証済みユーザーに切り替わるときです。 ```dart showLineNumbers try { await Adapty().identify(customerUserId); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` リクエストパラメータ: - **Customer User ID**(必須):文字列のユーザー識別子。 :::warning 重要なユーザーデータの再送信 ユーザーが再度ログインするなど、一部のケースでは Adapty のサーバーにはすでにそのユーザーの情報があります。このような場合、Adapty SDK は自動的に新しいユーザーとして動作するよう切り替わります。カスタム属性やサードパーティネットワークからのアトリビューションなど、匿名ユーザーに渡したデータがある場合は、識別されたユーザーに対してそのデータを再送信する必要があります。 また、新しいユーザーのデータが異なる可能性があるため、ユーザーを識別した後はすべてのペイウォールとプロダクトを再取得する必要があることにも注意してください。 ::: ### ログアウトとログイン \{#logging-out-and-logging-in\} `.logout()` メソッドを呼び出すことで、いつでもユーザーをログアウトできます: ```dart showLineNumbers try { await Adapty().logout(); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle unknown error } ``` その後、`.identify()` メソッドを使ってユーザーをログインできます。 ## `appAccountToken` を設定する(iOS) \{#assign-appaccounttoken-ios\} [`appAccountToken`](https://developer.apple.com/documentation/storekit/product/purchaseoption/appaccounttoken(_:)) は、App Store のトランザクションを内部ユーザー ID に紐付けるための **UUID** です。 StoreKit はすべてのトランザクションにこのトークンを関連付けるため、バックエンドで App Store のデータとユーザーを照合できます。 ユーザーごとに生成した安定した UUID を使用し、同じアカウントに対してデバイスをまたいで再利用してください。 これにより、購入と App Store の通知が正しく紐付けられます。 トークンは 2 つの方法で設定できます — SDK の起動時またはユーザーの識別時です。 :::important `appAccountToken` は必ず `customerUserId` と一緒に渡す必要があります。 トークンのみを渡した場合、トランザクションに含まれません。 ::: ```dart showLineNumbers // During configuration: try { await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_API_KEY') ..withCustomerUserId(YOUR_CUSTOMER_USER_ID, iosAppAccountToken: "YOUR_APP_ACCOUNT_TOKEN") ); } catch (e) { // handle the error } // Or when identifying users try { await Adapty().identify(customerUserId, iosAppAccountToken: "YOUR_APP_ACCOUNT_TOKEN"); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` ### 難読化されたアカウント ID を設定する(Android) \{#set-obfuscated-account-ids-android\} Google Play では、ユーザーのプライバシーとセキュリティを強化するために、特定のユースケースで難読化されたアカウント ID が必要です。これらの ID により、Google Play はユーザー情報を匿名に保ちながら購入を識別できます。これは不正防止や分析において特に重要です。 アプリが機密性の高いユーザーデータを扱う場合、または特定のプライバシー規制に準拠する必要がある場合は、これらの ID を設定する必要があるかもしれません。難読化された ID により、Google Play は実際のユーザー識別子を公開せずに購入を追跡できます。 ```dart showLineNumbers // During configuration: try { await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_API_KEY') ..withCustomerUserId(YOUR_CUSTOMER_USER_ID, androidObfuscatedAccountId: "OBFUSCATED_ACCOUNT_ID") ); } catch (e) { // handle the error } // Or when identifying users try { await Adapty().identify(customerUserId, androidObfuscatedAccountId: "OBFUSCATED_ACCOUNT_ID"); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` ## デバイスをまたいでユーザーを識別する \{#detect-users-across-devices\} --- no_index: true --- SDKが有効化されると、StoreKit(iOS)またはGoogle Play Billing(Android)からユーザーの既存のエンタイトルメントを自動的に読み取り、Adaptyバックエンドと同期します。有効なサブスクリプションは、アプリが`restorePurchases`を呼び出すことなく、Adaptyプロファイルに表示されます。 **自動では行われない**のは、新しいデバイスのプロファイルが元のデバイスと同じユーザーのものであることの認識です。AdaptyはCustomer User IDでプロファイルを照合するため、同一性の継続性はCUIDとして何を使用するかによって異なります。 **デバイス間でAdaptyが検出できること** | あなたの設定 | Adaptyが検出すること | 必要な対応 | | --- | --- | --- | | Customer User ID = `device_id`(アプリのログインなし) | 新しいデバイスは異なるCUIDを取得するため、異なるプロファイルが作成されます。サブスクリプションは**Access level updated**イベントを通じて新しいプロファイルに同期されますが、`subscription_started`は発火しません。新しいプロファイルは元の購入の継承者として扱われます。`subscription_started`に基づくアナリティクスは、リターニングユーザーをカウント不足します。 | リターニングユーザーが既存のプロファイルをデバイス間で照合できるよう、安定したアカウントIDをCustomer User IDとして使用してください。 | | Customer User ID = 安定したアカウントID(すべてのデバイスでログイン) | SDKは`activate()`でサブスクリプションを自動同期し、`identify()`がCUIDで既存のプロファイルを照合します。 | 追加の設定は不要です。IDとサブスクリプションの両方が自動的に解決されます。 | | Apple Family Sharing の継承者 | ファミリーメンバーは**Access level updated**イベントのみを通じてサブスクリプションを受け取ります。`subscription_started`は発火しません。 | **Access level updated**をリッスンしてください。完全なイベントマトリクスは[Apple Family Sharing](apple-family-sharing)を参照してください。 | | 同じApple/Googleアカウント、異なるアプリ内ユーザー | 最初に購入を記録したプロファイルが親になります。その後のプロファイルは継承者チェーンを通じてサブスクリプションを確認し、**Access level updated**イベントが1回発生します。 | ログインを必須にし、あなたのモデルに合った[共有モード](sharing-paid-access-between-user-accounts)を選択してください。 | **新しいデバイスでの購入の復元** ペイウォールにユーザーが操作できる「購入を復元」ボタンを設置してください。Apple App Review(ガイドライン3.1.1)で必須とされており、自動同期がエッジケースを見逃した場合のフォールバックとして機能します。このボタンはSDKの`restorePurchases`を呼び出す必要があります。 初回起動時にプログラムで`restorePurchases`を呼び出すことは、通常の使用では必要ありません。SDKはすでに`activate()`で同等の処理を実行しています。プログラムによる呼び出しは、`activate()`完了後にアクセスが欠落している場合のデバッグなど、強制的に新しいレシートチェックを行う場合にのみ使用してください。 --- # File: flutter-setting-user-attributes --- --- title: "Flutter SDKでユーザー属性を設定する" description: "Adaptyでユーザー属性を設定し、より正確なオーディエンスセグメンテーションを実現する方法を学びましょう。" --- メールアドレスや電話番号などのオプション属性をアプリのユーザーに設定できます。設定した属性は、ユーザー[セグメント](segments)の作成やCRMでの閲覧に活用できます。 ### ユーザー属性の設定 \{#setting-user-attributes\} ユーザー属性を設定するには、`.updateProfile()` メソッドを呼び出します。 ```dart showLineNumbers final builder = AdaptyProfileParametersBuilder() ..setEmail("email@email.com") ..setPhoneNumber("+18888888888") ..setFirstName('John') ..setLastName('Appleseed') ..setGender(AdaptyProfileGender.other) ..setBirthday(DateTime(1970, 1, 3)); try { await Adapty().updateProfile(builder.build()); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` `updateProfile` メソッドで以前に設定した属性はリセットされません。 :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: ### 使用可能なキーの一覧 \{#the-allowed-keys-list\} `AdaptyProfileParameters.Builder` で使用できるキー `<Key>` と値 `<Value>` の一覧は以下のとおりです。 | キー | 値 | |---|-----| | <p>email</p><p>phoneNumber</p><p>firstName</p><p>lastName</p> | String | | gender | 列挙型。使用できる値: `female`、`male`、`other` | | birthday | Date | ### カスタムユーザー属性 \{#custom-user-attributes\} 独自のカスタム属性を設定できます。カスタム属性は通常、アプリの利用状況に関連するものです。たとえば、フィットネスアプリであれば週ごとのエクササイズ回数、語学学習アプリであればユーザーの習熟度レベルなどが考えられます。カスタム属性をセグメントに活用して、ターゲットを絞ったペイウォールやオファーを作成したり、アナリティクスでどのプロダクト指標が収益に最も影響するかを分析したりできます。 ```javascript showLineNumbers try { final builder = AdaptyProfileParametersBuilder() ..setCustomStringAttribute('value1', 'key1') ..setCustomDoubleAttribute(1.0, 'key2'); await Adapty().updateProfile(builder.build()); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` 既存のキーを削除するには、`.withRemoved(customAttributeForKey:)` メソッドを使用します。 ```javascript showLineNumbers try { final builder = AdaptyProfileParametersBuilder() ..removeCustomAttribute('key1') ..removeCustomAttribute('key2'); await Adapty().updateProfile(builder.build()); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` すでに設定されているカスタム属性を確認したい場合は、`AdaptyProfile` オブジェクトの `customAttributes` フィールドを使用してください。 :::warning `customAttributes` の値は最新でない場合があります。ユーザー属性は異なるデバイスからいつでも送信できるため、最後の同期以降にサーバー上の属性が変更されている可能性があります。 ::: ### 制限事項 \{#limits\} - ユーザーあたり最大30件のカスタム属性 - キー名は最大30文字。キー名には英数字と次の文字を使用できます: `_` `-` `.` - 値は50文字以内の文字列または浮動小数点数。 --- # File: flutter-listen-subscription-changes --- --- title: "Flutter SDKでサブスクリプションステータスを確認する" description: "AdaptyでFlutterアプリのユーザーのサブスクリプションステータスを追跡・管理し、顧客維持率を向上させましょう。" --- Adaptyを使えば、サブスクリプションステータスの追跡が簡単になります。プロダクトIDをコードに手動で埋め込む必要はありません。代わりに、アクティブな[アクセスレベル](access-level)を確認するだけで、ユーザーのサブスクリプションステータスをすぐに把握できます。 <details> <summary>サブスクリプションステータスの確認を始める前に(クリックして展開)</summary> - iOS の場合、[App Store Server Notifications](enable-app-store-server-notifications) を設定してください - Android の場合、[リアルタイム デベロッパー通知(RTDN)](enable-real-time-developer-notifications-rtdn) を設定してください </details> ## アクセスレベルと AdaptyProfile オブジェクト \{#access-level-and-the-adaptyprofile-object\} アクセスレベルは [AdaptyProfile](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyProfile-class.html) オブジェクトのプロパティです。アプリ起動時([ユーザーを識別する](flutter-identifying-users#setting-customer-user-id-on-configuration)タイミングなど)にプロファイルを取得し、変更があるたびに更新することをおすすめします。こうすることで、都度リクエストを送ることなくプロファイルオブジェクトを利用できます。 プロファイルの更新通知を受け取るには、以下の[サブスクリプションステータス更新のリッスン](flutter-listen-subscription-changes)セクションで説明しているプロファイル変更のリスニングを設定してください。 :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: ## サーバーからアクセスレベルを取得する \{#retrieving-the-access-level-from-the-server\} サーバーからアクセスレベルを取得するには、`.getProfile()` メソッドを使用します。 ```javascript showLineNumbers try { final profile = await Adapty().getProfile(); // check the access } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` レスポンスパラメーター: | パラメーター | 説明 | | --------- | ------------------------------------------------------------ | | Profile | <p>[AdaptyProfile](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyProfile-class.html) オブジェクト。通常は、ユーザーがアプリのプレミアムアクセス権を持っているかどうかを判断するために、プロファイルのアクセスレベルのステータスだけを確認すれば十分です。</p><p></p><p>`.getProfile` メソッドは常にAPIへのクエリを試みるため、最新の結果を返します。何らかの理由(インターネット接続がないなど)でAdapty SDKがサーバーから情報を取得できない場合は、キャッシュのデータが返されます。また、Adapty SDKは `AdaptyProfile` のキャッシュを定期的に更新し、情報をできる限り最新の状態に保ちます。</p> | `.getProfile()` メソッドはユーザープロファイルを返し、そこからアクセスレベルのステータスを取得できます。アプリごとに複数のアクセスレベルを設定できます。たとえば、ニュースアプリでトピックごとに独立したサブスクリプションを販売する場合、「sports」と「science」というアクセスレベルを作成できます。ただし、多くの場合はアクセスレベルは1つで十分であり、その場合はデフォルトの「premium」アクセスレベルを使用するだけで問題ありません。 デフォルトの「premium」アクセスレベルを確認する例を示します。 ```javascript showLineNumbers try { final profile = await Adapty().getProfile(); if (profile?.accessLevels['premium']?.isActive ?? false) { // grant access to premium features } } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` ### サブスクリプションステータス更新のリッスン \{#listening-for-subscription-status-updates\} ユーザーのサブスクリプションが変更されるたびに、Adaptyはイベントを発火します。 Adaptyからメッセージを受け取るには、追加の設定が必要です。 ```javascript showLineNumbers Adapty().didUpdateProfileStream.listen((profile) { // handle any changes to subscription state }); ``` Adaptyはアプリ起動時にもイベントを発火します。この場合、キャッシュされたサブスクリプションステータスが渡されます。 ### サブスクリプションステータスのキャッシュ \{#subscription-status-cache\} Adapty SDKに実装されているキャッシュは、プロファイルのサブスクリプションステータスを保存します。そのため、サーバーが利用できない場合でも、キャッシュされたデータからプロファイルのサブスクリプションステータスを取得できます。 ただし、キャッシュから直接データをリクエストすることはできません。SDKは1分ごとにサーバーへ定期的にクエリを送信し、プロファイルに関する更新や変更を確認します。新しいトランザクションやその他の更新など変更があった場合は、サーバーとの同期を保つためにキャッシュデータへ反映されます。 --- # File: flutter-deal-with-att --- --- title: "Flutter SDK での ATT の処理" description: "Flutter で Adapty を使い始めて、サブスクリプションの設定と管理を効率化しましょう。" --- アプリが AppTrackingTransparency フレームワークを使用しており、ユーザーにアプリのトラッキング認可リクエストを表示する場合は、[認可ステータス](https://developer.apple.com/documentation/apptrackingtransparency/attrackingmanager/authorizationstatus/)を Adapty に送信する必要があります。 ```dart showLineNumbers final builder = AdaptyProfileParametersBuilder() ..setAppTrackingTransparencyStatus(AdaptyIOSAppTrackingTransparencyStatus.authorized); try { await Adapty().updateProfile(builder.build()); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle unknown error } ``` :::warning この値は変更されたときにできるだけ早く送信することを強くおすすめします。そうすることで、設定済みのインテグレーションにデータがタイムリーに送信されます。 ::: --- # File: kids-mode-flutter --- --- title: "Flutter SDKのキッズモード" description: "AppleとGoogleのポリシーに準拠するためにキッズモードを簡単に有効化。Flutter SDKではIDFA、GAID、広告データを収集しません。" --- Flutterアプリが子ども向けの場合、[Apple](https://developer.apple.com/kids/)および[Google](https://support.google.com/googleplay/android-developer/answer/9893335)のポリシーに従う必要があります。Adapty SDKを使用している場合、いくつかの簡単な手順でこれらのポリシーに準拠するよう設定し、アプリストアの審査を通過できます。 ## 必要な対応 \{#whats-required\} 以下の収集を無効化するよう、Adapty SDKを設定する必要があります。 - [IDFA(広告主識別子)](https://en.wikipedia.org/wiki/Identifier_for_Advertisers)(iOS) - [Android広告ID(AAID/GAID)](https://support.google.com/googleplay/android-developer/answer/6048248)(Android) - [IPアドレス](https://www.ftc.gov/system/files/ftc_gov/pdf/p235402_coppa_application.pdf) また、カスタマーユーザーIDの扱いには注意が必要です。`<FirstName.LastName>`形式のユーザーIDは個人情報の収集と見なされる可能性があります(メールアドレスも同様です)。キッズモードでは、コンプライアンスを確保するために、ランダム化または匿名化された識別子(ハッシュIDやデバイス生成のUUIDなど)を使用することをお勧めします。 ## キッズモードを有効にする \{#enabling-kids-mode\} ### Adapty ダッシュボードでの設定 \{#updates-in-the-adapty-dashboard\} Adapty ダッシュボードで、IPアドレスの収集を無効化する必要があります。[App settings](https://app.adapty.io/settings/general)に移動し、**Collect users' IP address**の下にある**Disable IP address collection**をクリックしてください。 ### モバイルアプリのコードへの変更 \{#updates-in-your-mobile-app-code\} ポリシーに準拠するために、ユーザーのIDFA(iOS向け)、GAID/AAID(Android向け)、およびIPアドレスの収集を無効化してください。 **Android:SDK設定を更新する** ```dart showLineNumbers title="Dart" try { await Adapty().activate( configuration: AdaptyConfiguration(apiKey: 'YOUR_API_KEY') // highlight-start ..withGoogleAdvertisingIdCollectionDisabled(true), // set to `true` ..withIpAddressCollectionDisabled(true), // set to `true` // highlight-end ); } catch (e) { // handle the error } ``` **iOS:CocoaPodsを使用してキッズモードを有効にする** 1. Podfileを更新します。 - `post_install`セクションが**ない**場合は、以下のコードブロック全体を追加してください。 - `post_install`セクションが**ある**場合は、ハイライトされた行をそこにマージしてください。 ```ruby showLineNumbers title="Podfile" def adapty_enable_kids_mode(installer) installer.pods_project.targets.each do |target| next unless target.name == 'Adapty' target.build_configurations.each do |config| flags = config.build_settings['OTHER_SWIFT_FLAGS'] || '$(inherited)' flags = flags.join(' ') if flags.is_a?(Array) config.build_settings['OTHER_SWIFT_FLAGS'] = "#{flags} -DADAPTY_KIDS_MODE" end target.frameworks_build_phase.files.dup.each do |bf| target.frameworks_build_phase.remove_build_file(bf) if bf.display_name.to_s.include?('AdSupport') end end installer.pods_project.save Dir.glob(File.join(installer.sandbox.root, 'Target Support Files', '**', '*.xcconfig')).each do |xc| File.write(xc, File.read(xc).gsub(/\s*-framework\s+"?AdSupport"?/, '')) end end post_install do |installer| # ... keep your existing post_install body (Flutter adds one automatically) ... adapty_enable_kids_mode(installer) # <-- enable Adapty Kids Mode end ``` 2. 以下のコマンドを実行して変更を適用します。 ```sh showLineNumbers title="Shell" pod install ``` --- # File: flutter-get-onboardings --- --- title: "Flutter SDK でオンボーディングを取得する" description: "Flutter 向け Adapty でオンボーディングを取得する方法を説明します。" --- Adapty ダッシュボードのビルダーで[オンボーディングのビジュアル部分をデザイン](design-onboarding)したら、Flutter アプリに表示できます。この処理の最初のステップは、以下で説明するように、プレースメントに関連付けられたオンボーディングとそのビュー設定を取得することです。 始める前に、次の点を確認してください。 1. [Adapty Flutter SDK](sdk-installation-flutter) バージョン 3.8.0 以降がインストールされていること。 2. [オンボーディングを作成](create-onboarding)していること。 3. オンボーディングを[プレースメント](placements)に追加していること。 ## オンボーディングを取得する \{#fetch-onboarding\} ノーコードビルダーで[オンボーディング](onboardings)を作成すると、アプリが取得して表示する必要のある設定を含むコンテナとして保存されます。このコンテナは、表示されるコンテンツ、表示方法、ユーザーのインタラクション(クイズの回答やフォームへの入力など)の処理方法といった、エクスペリエンス全体を管理します。また、コンテナは分析イベントを自動的に追跡するため、ビュートラッキングを別途実装する必要はありません。 パフォーマンスを最大限に発揮するため、ユーザーに表示する前に画像のダウンロードを完了できるよう、早めにオンボーディング設定を取得してください。 オンボーディングを取得するには、`getOnboarding` メソッドを使用します。 ```dart showLineNumbers try { final onboarding = await Adapty().getOnboarding(placementId: "YOUR_PLACEMENT_ID"); } on AdaptyError catch (e) { //handle error } catch (e) { //handle error } ``` 次に、`createOnboardingView` メソッドを呼び出して、表示するビューを取得します。 :::warning `createOnboardingView` メソッドの結果は一度しか使用できません。再度使用する必要がある場合は、`createOnboardingView` メソッドを新たに呼び出してください。再作成せずに 2 回呼び出すと、`AdaptyUIError.viewAlreadyPresented` エラーが発生する場合があります。 ::: ```dart showLineNumbers try { final onboardingView = await Adapty().createOnboardingView(onboarding: onboarding); } on AdaptyError catch (e) { //handle error } catch (e) { //handle error } ``` パラメーター: | パラメーター | 必須/任意 | 説明 | |---------|--------|------| | **placementId** | 必須 | 目的の[プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** | <p>任意</p><p>デフォルト: `en`</p> | <p>オンボーディングのローカライズ識別子。このパラメーターは、マイナス(**-**)文字で区切られた 1 つまたは 2 つのサブタグで構成される言語コードを指定します。最初のサブタグは言語、2 番目のサブタグは地域を表します。</p><p></p><p>例:`en` は英語、`pt-br` はブラジルポルトガル語を表します。</p> | | **fetchPolicy** | デフォルト: `.reloadRevalidatingCacheData` | <p>デフォルトでは、SDK はサーバーからデータを読み込もうとし、失敗した場合はキャッシュされたデータを返します。このオプションを推奨します。ユーザーが常に最新のデータを取得できるためです。</p><p></p><p>ただし、ユーザーが不安定なインターネット接続を使用していると考えられる場合は、`.returnCacheDataElseLoad` を使用して、キャッシュが存在する場合はキャッシュデータを返すことを検討してください。このシナリオでは、ユーザーが最新のデータを取得できない場合がありますが、インターネット接続が不安定な場合でも読み込み時間が短くなります。キャッシュは定期的に更新されるため、セッション中にネットワークリクエストを避けるために使用しても安全です。</p><p></p><p>キャッシュはアプリの再起動後も保持され、アプリの再インストールまたは手動でのクリーンアップ時にのみ消去されます。</p><p></p><p>Adapty SDK はオンボーディングをローカルに 2 層で保存します。1 層目は上記の定期更新キャッシュで、2 層目はフォールバックオンボーディングです。また、CDN を使用してオンボーディングをより速く取得し、CDN が利用できない場合に備えたスタンドアロンのフォールバックサーバーも用意されています。このシステムは、インターネット接続が不安定な場合でも信頼性を確保しながら、常に最新バージョンのオンボーディングを取得できるように設計されています。</p> | | **loadTimeout** | デフォルト: 5 秒 | <p>このメソッドのタイムアウトを制限する値です。タイムアウトに達した場合、キャッシュデータまたはローカルフォールバックが返されます。</p><p>この処理は内部で複数のリクエストで構成されている場合があるため、まれに `loadTimeout` で指定した時間よりも少し遅れてタイムアウトすることがあります。</p> | レスポンスパラメーター: | パラメーター | 説明 | |:----------|:-----| | Onboarding | オンボーディングの識別子と設定、リモートコンフィグ、その他いくつかのプロパティを含む [`AdaptyOnboarding`](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyOnboarding-class.html) オブジェクト。 | ## デフォルトオーディエンスのオンボーディングでフェッチを高速化する \{#speed-up-onboarding-fetching-with-default-audience-onboarding\} 通常、オンボーディングはほぼ瞬時に取得されるため、このプロセスの高速化を心配する必要はありません。ただし、オーディエンスやオンボーディングが多数あり、ユーザーのインターネット接続が遅い場合、オンボーディングの取得に想定より時間がかかる場合があります。そのような状況では、オンボーディングをまったく表示しないよりも、スムーズなユーザー体験を確保するためにデフォルトのオンボーディングを表示したい場合があります。 この問題を解決するために、`getOnboardingForDefaultAudience` メソッドを使用できます。このメソッドは、指定されたプレースメントの **All Users** オーディエンス向けオンボーディングを取得します。ただし、推奨されるアプローチは、上記の[オンボーディングを取得する](#fetch-onboarding)セクションで説明したように、`getOnboarding` メソッドでオンボーディングを取得することです。 :::warning `getOnboardingForDefaultAudience` の代わりに `getOnboarding` の使用を検討してください。後者には重要な制限があります: - **互換性の問題**: 複数のアプリバージョンをサポートする際に問題が生じる場合があります。後方互換性のあるデザインが必要になるか、古いバージョンで表示が崩れる可能性を受け入れる必要があります。 - **パーソナライズなし**: "All Users" オーディエンスのコンテンツのみ表示され、国、アトリビューション、またはカスタム属性に基づくターゲティングが行われません。 ユースケースにおいて高速なフェッチがこれらのデメリットを上回る場合は、以下に示すように `getOnboardingForDefaultAudience` を使用してください。それ以外の場合は、[上記](#fetch-onboarding)の説明に従って `getOnboarding` を使用してください。 ::: ```dart showLineNumbers try { final onboarding = await Adapty().getOnboardingForDefaultAudience(placementId: 'YOUR_PLACEMENT_ID'); } on AdaptyError catch (adaptyError) { // handle error } catch (e) { // handle unknown error } ``` パラメーター: | パラメーター | 必須/任意 | 説明 | |------------|---------|------| | **placementId** | 必須 | 目的の[プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** | <p>任意</p><p>デフォルト: `en`</p> | <p>オンボーディングのローカライズ識別子。このパラメーターは、マイナス(**-**)文字で区切られた 1 つまたは 2 つのサブタグで構成される言語コードを指定します。最初のサブタグは言語、2 番目のサブタグは地域を表します。</p><p></p><p>例:`en` は英語、`pt-br` はブラジルポルトガル語を表します。</p> | | **fetchPolicy** | デフォルト: `.reloadRevalidatingCacheData` | <p>デフォルトでは、SDK はサーバーからデータを読み込もうとし、失敗した場合はキャッシュされたデータを返します。このオプションを推奨します。ユーザーが常に最新のデータを取得できるためです。</p><p></p><p>ただし、ユーザーが不安定なインターネット接続を使用していると考えられる場合は、`.returnCacheDataElseLoad` を使用して、キャッシュが存在する場合はキャッシュデータを返すことを検討してください。このシナリオでは、ユーザーが最新のデータを取得できない場合がありますが、インターネット接続が不安定な場合でも読み込み時間が短くなります。キャッシュは定期的に更新されるため、セッション中にネットワークリクエストを避けるために使用しても安全です。</p><p></p><p>キャッシュはアプリの再起動後も保持され、アプリの再インストールまたは手動でのクリーンアップ時にのみ消去されます。</p><p></p><p>Adapty SDK はオンボーディングをローカルに 2 層で保存します。1 層目は上記の定期更新キャッシュで、2 層目はフォールバックオンボーディングです。また、CDN を使用してオンボーディングをより速く取得し、CDN が利用できない場合に備えたスタンドアロンのフォールバックサーバーも用意されています。このシステムは、インターネット接続が不安定な場合でも信頼性を確保しながら、常に最新バージョンのオンボーディングを取得できるように設計されています。</p> | --- # File: flutter-present-onboardings --- --- title: "Flutter SDKでオンボーディングを表示する" description: "コンバージョンを高めるためにオンボーディングを効果的に表示する方法を学びましょう。" --- ビルダーでオンボーディングをカスタマイズした場合、Flutter アプリのコードでレンダリング処理を記述しなくても、ユーザーに表示できます。カスタマイズ済みのオンボーディングには、表示する内容と表示方法がすべて含まれています。 始める前に、以下を確認してください: 1. [Adapty Flutter SDK](sdk-installation-flutter) 3.8.0 以降がインストールされていること。 2. [オンボーディングが作成済み](create-onboarding)であること。 3. オンボーディングが[プレースメント](placements)に追加済みであること。 Adapty Flutter SDK では、オンボーディングを表示する方法が2つあります: - **スタンドアロン画面** - **埋め込みウィジェット** ## スタンドアロン画面として表示する \{#present-as-standalone-screen\} オンボーディングをスタンドアロン画面として表示するには、`createOnboardingView` メソッドで作成した `onboardingView` に対して `onboardingView.present()` メソッドを使用します。各 `view` は一度しか使用できません。再度オンボーディングを表示する必要がある場合は、`createOnboardingView` をもう一度呼び出して新しい `onboardingView` インスタンスを作成してください。 :::warning 同じ `onboardingView` を再作成せずに再利用すると、`AdaptyUIError.viewAlreadyPresented` エラーが発生することがあります。 ::: ```javascript showLineNumbers title="Flutter" try { await onboardingView.present(); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` ### オンボーディングを閉じる \{#dismiss-the-onboarding\} プログラムでオンボーディングを閉じる必要がある場合は、`dismiss()` メソッドを使用します: ```dart showLineNumbers title="Flutter" try { await onboardingView.dismiss(); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` ### iOS の表示スタイルを設定する \{#configure-ios-presentation-style\} `present()` メソッドに `iosPresentationStyle` パラメータを渡すことで、iOS でのオンボーディングの表示方法を設定できます。このパラメータには `AdaptyUIIOSPresentationStyle.fullScreen`(デフォルト)または `AdaptyUIIOSPresentationStyle.pageSheet` を指定できます。 ```dart showLineNumbers try { await onboardingView.present(iosPresentationStyle: AdaptyUIIOSPresentationStyle.pageSheet); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` ## ウィジェットツリーに埋め込む \{#embed-in-widget-hierarchy\} 既存のウィジェットツリーにオンボーディングを埋め込むには、Flutter のウィジェット階層内で `AdaptyUIOnboardingPlatformView` ウィジェットを直接使用します。 ```javascript showLineNumbers title="Flutter" AdaptyUIOnboardingPlatformView( onboarding: onboarding, // The onboarding object you fetched onDidFinishLoading: (meta) { }, onDidFailWithError: (error) { }, onCloseAction: (meta, actionId) { }, onPaywallAction: (meta, actionId) { }, onCustomAction: (meta, actionId) { }, onStateUpdatedAction: (meta, elementId, params) { }, onAnalyticsEvent: (meta, event) { }, ) ``` :::note Android のプラットフォームビューを動作させるには、`MainActivity` が `FlutterFragmentActivity` を継承していることを確認してください: ```kotlin showLineNumbers title="Kotlin" class MainActivity : FlutterFragmentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) } } ``` ::: ## オンボーディング中のローダー \{#loader-during-onboarding\} オンボーディングを表示する際、ビューが初期化される間、スプラッシュ画面とオンボーディングの間に短いローディング画面が表示されることがあります。用途に応じてこれをさまざまな方法で制御できます。 #### onDidFinishLoading を使用してスプラッシュ画面を制御する \{#control-splash-screen-using-ondidfinishloading\} :::note このアプローチは、オンボーディングをウィジェットとして埋め込む場合にのみ利用できます。スタンドアロン画面として表示する場合には使用できません。 ::: 推奨されるクロスプラットフォームのアプローチは、オンボーディングが完全に読み込まれるまでスプラッシュ画面またはカスタムオーバーレイを表示し続け、その後手動で非表示にする方法です。 埋め込みウィジェットを使用する場合は、ウィジェットの上に独自のウィジェットをオーバーレイし、`onDidFinishLoading` が発火したタイミングでオーバーレイを非表示にします: ```dart showLineNumbers title="Flutter" AdaptyUIOnboardingPlatformView( onboarding: onboarding, onDidFinishLoading: (meta) { // Hide your custom splash screen or overlay here }, // ... other callbacks ) ``` ### ネイティブローダーをカスタマイズする \{#customize-native-loader\} :::important このアプローチはプラットフォーム固有であり、ネイティブ UI コードのメンテナンスが必要です。アプリで既に別のネイティブレイヤーをメンテナンスしている場合を除き、推奨しません。 ::: デフォルトのローダー自体をカスタマイズしたい場合は、プラットフォーム固有のレイアウトに置き換えることができます。このアプローチでは、Android と iOS それぞれに個別の実装が必要です: - **iOS**: Xcode プロジェクトに `AdaptyOnboardingPlaceholderView.xib` を追加する - **Android**: `res/layout` に `adapty_onboarding_placeholder_view.xml` を作成し、プレースホルダーを定義する ## オンボーディング内のリンクの開き方をカスタマイズする \{#customize-how-links-open-in-onboardings\} :::important オンボーディング内のリンクの開き方のカスタマイズは、Adapty SDK v3.15.1 以降でサポートされています。 ::: デフォルトでは、オンボーディング内のリンクはアプリ内ブラウザで開かれます。これにより、アプリを切り替えることなくウェブページを表示できるシームレスなユーザー体験が提供されます。 外部ブラウザでリンクを開くようにしたい場合は、`externalUrlsPresentation` パラメータを `AdaptyWebPresentation.externalBrowser` に設定することでこの動作をカスタマイズできます: <Tabs> <TabItem value="standalone" label="スタンドアロン画面" default> ```dart showLineNumbers title="Flutter" final onboardingView = await AdaptyUI().createOnboardingView( onboarding: onboarding, externalUrlsPresentation: AdaptyWebPresentation.externalBrowser, // default – AdaptyWebPresentation.inAppBrowser ); try { await onboardingView.present(); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` </TabItem> <TabItem value="embedded" label="埋め込みウィジェット"> ```dart showLineNumbers title="Flutter" AdaptyUIOnboardingPlatformView( onboarding: onboarding, externalUrlsPresentation: AdaptyWebPresentation.externalBrowser, // default – AdaptyWebPresentation.inAppBrowser onDidFinishLoading: (meta) { }, onDidFailWithError: (error) { }, onCloseAction: (meta, actionId) { }, onPaywallAction: (meta, actionId) { }, onCustomAction: (meta, actionId) { }, onStateUpdatedAction: (meta, elementId, params) { }, onAnalyticsEvent: (meta, event) { }, ) ``` </TabItem> </Tabs> ## セーフエリアのパディングを無効にする(Android) \{#disable-safe-area-paddings-android\} デフォルトでは、Android デバイスでオンボーディングビューはステータスバーやナビゲーションバーなどのシステム UI 要素を避けるためにセーフエリアのパディングを自動的に適用します。この動作を無効にしてレイアウトを完全に制御したい場合は、アプリに boolean リソースを追加することで設定できます: 1. `android/app/src/main/res/values` に移動します。`bools.xml` ファイルが存在しない場合は作成します。 2. 以下のリソースを追加します: ```xml <resources> <bool name="adapty_onboarding_enable_safe_area_paddings">false</bool> </resources> ``` この変更はアプリ内のすべてのオンボーディングにグローバルに適用されます。 --- # File: flutter-handling-onboarding-events --- --- title: "Flutter SDKでオンボーディングイベントを処理する" description: "AdaptyのFlutterでオンボーディング関連イベントを処理する。" --- ビルダーで設定されたオンボーディングは、アプリが対応できるイベントを生成します。これらのイベントをどのように処理するかは、使用しているプレゼンテーション方式によって異なります。 - **フルスクリーン表示**: すべてのオンボーディングビューのイベントを処理するグローバルイベントオブザーバーのセットアップが必要 - **埋め込みウィジェット**: ウィジェット内のインラインコールバックパラメーターを通じてイベントを処理 始める前に、以下を確認してください: 1. [Adapty Flutter SDK](sdk-installation-flutter) 3.8.0以降がインストールされていること。 2. [オンボーディングが作成されている](create-onboarding)こと。 3. オンボーディングが[プレースメント](placements)に追加されていること。 ## フルスクリーン表示のイベント \{#full-screen-presentation-events\} ### イベントオブザーバーの設定 \{#set-up-event-observer\} フルスクリーンオンボーディングのイベントを処理するには、`AdaptyUIOnboardingsEventsObserver`を実装して、表示前に設定します: ```javascript showLineNumbers title="Flutter" AdaptyUI().setOnboardingsEventsObserver(this); try { await onboardingView.present(); } on AdaptyError catch (e) { // handle the error } catch (e) { // handle the error } ``` ### イベントの処理 \{#handle-events\} オブザーバーに以下のメソッドを実装します: ```javascript showLineNumbers title="Flutter" void onboardingViewDidFinishLoading( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, ) { // Onboarding finished loading } void onboardingViewDidFailWithError( AdaptyUIOnboardingView view, AdaptyError error, ) { // Handle loading errors } void onboardingViewOnCloseAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, String actionId, ) { // Handle close action view.dismiss(); } void onboardingViewOnPaywallAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, String actionId, ) { // Dismiss onboarding before presenting paywall view.dismiss().then((_) { _openPaywall(actionId); }); } void onboardingViewOnCustomAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, String actionId, ) { // Handle custom actions } void onboardingViewOnStateUpdatedAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, String elementId, AdaptyOnboardingsStateUpdatedParams params, ) { // Handle user input updates } void onboardingViewOnAnalyticsEvent( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, AdaptyOnboardingsAnalyticsEvent event, ) { // Track analytics events } ``` ## 埋め込みウィジェットのイベント \{#embedded-widget-events\} `AdaptyUIOnboardingPlatformView`を使用する場合、ウィジェット内のインラインコールバックパラメーターを通じてイベントを処理できます。イベントはウィジェットのコールバックとグローバルオブザーバー(設定されている場合)の両方に送信されますが、グローバルオブザーバーは任意です: ```javascript showLineNumbers title="Flutter" AdaptyUIOnboardingPlatformView( onboarding: onboarding, onDidFinishLoading: (meta) { // Onboarding finished loading }, onDidFailWithError: (error) { // Handle loading errors }, onCloseAction: (meta, actionId) { // Handle close action }, onPaywallAction: (meta, actionId) { _openPaywall(actionId); }, onCustomAction: (meta, actionId) { // Handle custom actions }, onStateUpdatedAction: (meta, elementId, params) { // Handle user input updates }, onAnalyticsEvent: (meta, event) { // Track analytics events }, ) ``` ## イベントの種類 \{#event-types\} 以下のセクションでは、使用しているプレゼンテーション方式に関わらず処理できる各種イベントについて説明します。 ### カスタムアクションの処理 \{#handle-custom-actions\} ビルダーでは、ボタンに **custom** アクションを追加してIDを割り当てることができます。 <img src="/assets/shared/img/ios-events-1.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> このIDをコードで使用し、カスタムアクションとして処理できます。たとえば、**Login** や **Allow notifications** などのカスタムボタンをユーザーがタップすると、デリゲートメソッド `onboardingController` が `.custom(id:)` ケースでトリガーされ、`actionId` パラメーターにはビルダーの **Action ID** が入ります。"allowNotifications" のような独自のIDを作成できます。 ```javascript // Full-screen presentation void onboardingViewOnCustomAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, String actionId, ) { switch (actionId) { case 'login': _login(); break; case 'allow_notifications': _allowNotifications(); break; } } // Embedded widget onCustomAction: (meta, actionId) { _handleCustomAction(actionId); } ``` <Details> <summary>イベント例(クリックして展開)</summary> ```json { "actionId": "allowNotifications", "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 0, "screensTotal": 3 } } ``` </Details> ### オンボーディングの読み込み完了 \{#finishing-loading-onboarding\} オンボーディングの読み込みが完了すると、このイベントがトリガーされます: ```javascript showLineNumbers title="Flutter" // Full-screen presentation void onboardingViewDidFinishLoading( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, ) { print('Onboarding loaded: ${meta.onboardingId}'); } // Embedded widget onDidFinishLoading: (meta) { print('Onboarding loaded: ${meta.onboardingId}'); } ``` <Details> <summary>イベント例(クリックして展開)</summary> ```json { "meta": { "onboarding_id": "onboarding_123", "screen_cid": "welcome_screen", "screen_index": 0, "total_screens": 4 } } ``` </Details> ### オンボーディングのクローズ \{#closing-onboarding\} ユーザーが **Close** アクションが割り当てられたボタンをタップしたとき、オンボーディングはクローズされたと見なされます。 <img src="/assets/shared/img/ios-events-2.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> :::important ユーザーがオンボーディングをクローズしたときの動作を管理する必要があります。たとえば、オンボーディング自体の表示を停止する処理が必要です。 ::: ```javascript showLineNumbers title="Flutter" // Full-screen presentation void onboardingViewOnCloseAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, String actionId, ) { await view.dismiss(); } // Embedded widget onCloseAction: (meta, actionId) { Navigator.of(context).pop(); } ``` <Details> <summary>イベント例(クリックして展開)</summary> ```json { "action_id": "close_button", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "final_screen", "screen_index": 3, "total_screens": 4 } } ``` </Details> ### ペイウォールを開く \{#opening-a-paywall\} :::tip オンボーディング内でペイウォールを開きたい場合は、このイベントを処理してください。クローズ後にペイウォールを開く場合は、クローズアクションを処理してイベントデータに依存せずにペイウォールを開く方が簡単です。 ::: オンボーディング内でペイウォールを扱う最もシームレスな方法は、アクションIDをペイウォールのプレースメントIDと同じにすることです: iOSでは、一度に表示できるビュー(ペイウォールまたはオンボーディング)は1つだけです。オンボーディングの上にペイウォールを表示すると、バックグラウンドのオンボーディングをプログラムで操作できなくなります。オンボーディングをdismissしようとすると、代わりにペイウォールが閉じられ、オンボーディングが表示されたままになります。これを避けるために、ペイウォールを表示する前に必ずオンボーディングビューをdismissしてください。 ```javascript showLineNumbers title="Flutter" // Full-screen presentation void onboardingViewOnPaywallAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, String actionId, ) { // Dismiss onboarding before presenting paywall view.dismiss().then((_) { _openPaywall(actionId); }); } Future<void> _openPaywall(String actionId) async { // Implement your paywall opening logic here } // Embedded widget onPaywallAction: (meta, actionId) { _openPaywall(actionId); } ``` <Details> <summary>イベント例(クリックして展開)</summary> ```json { "action_id": "premium_offer_1", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "pricing_screen", "screen_index": 2, "total_screens": 4 } } ``` </Details> ### ナビゲーションのトラッキング \{#tracking-navigation\} オンボーディングフロー中にナビゲーション関連のイベントが発生すると、アナリティクスイベントを受け取ります: ```javascript showLineNumbers title="Flutter" // Full-screen presentation void onboardingViewOnAnalyticsEvent( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, AdaptyOnboardingsAnalyticsEvent event, ) { trackEvent(event.type, meta.onboardingId); } // Embedded widget onAnalyticsEvent: (meta, event) { trackEvent(event.type, meta.onboardingId); } ``` `event` オブジェクトは以下のいずれかのタイプになります: |タイプ | 説明 | |------------|-------------| | `onboardingStarted` | オンボーディングが読み込まれたとき | | `screenPresented` | いずれかの画面が表示されたとき | | `screenCompleted` | 画面が完了したとき。オプションの `elementId`(完了した要素の識別子)とオプションの `reply`(ユーザーからの返答)を含む。ユーザーが画面を離れるためのアクションを行ったときにトリガーされる。 | | `secondScreenPresented` | 2番目の画面が表示されたとき | | `userEmailCollected` | 入力フィールドからユーザーのメールアドレスが収集されたときにトリガーされる | | `onboardingCompleted` | ユーザーが `final` IDを持つ画面に到達したときにトリガーされる。このイベントが必要な場合は、[最後の画面に `final` IDを割り当てる](design-onboarding)。 | | `unknown` | 認識されないイベントタイプの場合。`name`(不明なイベントの名前)と `meta`(追加のメタデータ)を含む | 各イベントには以下の `meta` 情報が含まれます: | フィールド | 説明 | |------------|-------------| | `onboardingId` | オンボーディングフローの一意の識別子 | | `screenClientId` | 現在の画面の識別子 | | `screenIndex` | フロー内の現在の画面の位置 | | `screensTotal` | フロー内の画面の合計数 | <Details> <summary>イベント例(クリックして展開)</summary> ```javascript // onboardingStarted { "name": "onboarding_started", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "welcome_screen", "screen_index": 0, "total_screens": 4 } } // screenPresented { "name": "screen_presented", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "interests_screen", "screen_index": 2, "total_screens": 4 } } // screenCompleted { "name": "screen_completed", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "profile_screen", "screen_index": 1, "total_screens": 4 }, "params": { "element_id": "profile_form", "reply": "success" } } // secondScreenPresented { "name": "second_screen_presented", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "profile_screen", "screen_index": 1, "total_screens": 4 } } // userEmailCollected { "name": "user_email_collected", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "profile_screen", "screen_index": 1, "total_screens": 4 } } // onboardingCompleted { "name": "onboarding_completed", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "final_screen", "screen_index": 3, "total_screens": 4 } } ``` </Details> --- # File: flutter-onboarding-input --- --- title: "Flutter SDKでオンボーディングのデータを処理する" description: "Adapty SDKを使ってFlutterアプリでオンボーディングのデータを保存・活用する方法を説明します。" --- ユーザーがクイズの質問に回答したり、入力フィールドにデータを入力したりすると、`onStateUpdatedAction` メソッドが呼び出されます。フィールドの種類をコード内で保存または処理できます。 例: ```dart // フルスクリーン表示 void onboardingViewOnStateUpdatedAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, String elementId, AdaptyOnboardingsStateUpdatedParams params, ) { // Process data } // 埋め込みウィジェット onStateUpdatedAction: (meta, elementId, params) { // Process data } ``` アクションのフォーマットは[こちら](https://pub.dev/documentation/adapty_flutter/latest/adapty_flutter/AdaptyUIOnboardingPlatformView/onStateUpdatedAction.html)を参照してください。 <Details> <summary>保存されたデータの例(実装によってフォーマットが異なる場合があります)</summary> ```javascript // Example of a saved select action { "elementId": "preference_selector", "meta": { "onboardingId": "onboarding_123", "screenClientId": "preferences_screen", "screenIndex": 1, "screensTotal": 3 }, "params": { "type": "select", "value": { "id": "option_1", "value": "premium", "label": "Premium Plan" } } } // Example of a saved multi-select action { "elementId": "interests_selector", "meta": { "onboardingId": "onboarding_123", "screenClientId": "interests_screen", "screenIndex": 2, "screensTotal": 3 }, "params": { "type": "multiSelect", "value": [ { "id": "interest_1", "value": "sports", "label": "Sports" }, { "id": "interest_2", "value": "music", "label": "Music" } ] } } // Example of a saved input action { "elementId": "name_input", "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 0, "screensTotal": 3 }, "params": { "type": "input", "value": { "type": "text", "value": "John Doe" } } } // Example of a saved date picker action { "elementId": "birthday_picker", "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 0, "screensTotal": 3 }, "params": { "type": "datePicker", "value": { "day": 15, "month": 6, "year": 1990 } } } ``` </Details> ## ユースケース \{#use-cases\} ### ユーザープロファイルにデータを追加する \{#enrich-user-profiles-with-data\} 入力されたデータをすぐにユーザープロファイルと紐付け、同じ情報を二度聞かないようにするには、アクションを処理する際に入力データで[ユーザープロファイルを更新](flutter-setting-user-attributes)する必要があります。 たとえば、`name` というIDのテキストフィールドでユーザーに名前を入力してもらい、その値をユーザーの名(first name)として設定したい場合や、`email` フィールドでメールアドレスを入力してもらう場合、アプリのコードは次のようになります。 ```dart showLineNumbers // フルスクリーン表示 void onboardingViewOnStateUpdatedAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, String elementId, AdaptyOnboardingsStateUpdatedParams params, ) { // Store user preferences or responses if (params is AdaptyOnboardingsInputParams) { final builder = AdaptyProfileParametersBuilder(); // Map elementId to appropriate profile field switch (elementId) { case 'name': if (params.input is AdaptyOnboardingsTextInput) { builder.setFirstName((params.input as AdaptyOnboardingsTextInput).value); } break; case 'email': if (params.input is AdaptyOnboardingsEmailInput) { builder.setEmail((params.input as AdaptyOnboardingsEmailInput).value); } break; } // Update profile Adapty().updateProfile(builder.build()).catchError((error) { // handle the error }); } } // 埋め込みウィジェット onStateUpdatedAction: (meta, elementId, params) { // Store user preferences or responses if (params is AdaptyOnboardingsInputParams) { final builder = AdaptyProfileParametersBuilder(); // Map elementId to appropriate profile field switch (elementId) { case 'name': if (params.input is AdaptyOnboardingsTextInput) { builder.setFirstName((params.input as AdaptyOnboardingsTextInput).value); } break; case 'email': if (params.input is AdaptyOnboardingsEmailInput) { builder.setEmail((params.input as AdaptyOnboardingsEmailInput).value); } break; } // Update profile Adapty().updateProfile(builder.build()).catchError((error) { // handle the error }); } } ``` ### 回答に基づいてペイウォールをカスタマイズする \{#customize-paywalls-based-on-answers\} オンボーディングのクイズを活用して、オンボーディング完了後にユーザーに表示するペイウォールをカスタマイズすることもできます。 たとえば、スポーツの経験について質問し、異なるユーザーグループに対して異なるCTAやプロダクトを表示できます。 1. オンボーディングビルダーで[クイズを追加](onboarding-quizzes)し、選択肢に意味のあるIDを割り当てます。 2. IDに基づいてクイズの回答を処理し、ユーザーに[カスタム属性を設定](flutter-setting-user-attributes)します。 ```dart showLineNumbers // フルスクリーン表示 void onboardingViewOnStateUpdatedAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, String elementId, AdaptyOnboardingsStateUpdatedParams params, ) { // Handle quiz responses and set custom attributes if (params is AdaptyOnboardingsSelectParams) { final builder = AdaptyProfileParametersBuilder(); // Map quiz responses to custom attributes switch (elementId) { case 'experience': // Set custom attribute 'experience' with the selected value (beginner, amateur, pro) builder.setCustomStringAttribute(params.value, 'experience'); break; } // Update profile Adapty().updateProfile(builder.build()).catchError((error) { // handle the error }); } } // 埋め込みウィジェット onStateUpdatedAction: (meta, elementId, params) { // Handle quiz responses and set custom attributes if (params is AdaptyOnboardingsSelectParams) { final builder = AdaptyProfileParametersBuilder(); // Map quiz responses to custom attributes switch (elementId) { case 'experience': // Set custom attribute 'experience' with the selected value (beginner, amateur, pro) builder.setCustomStringAttribute(params.value, 'experience'); break; } // Update profile Adapty().updateProfile(builder.build()).catchError((error) { // handle the error }); } } ``` 3. カスタム属性の値ごとに[セグメントを作成](segments)します。 4. [プレースメント](placements)を作成し、作成した各セグメントに対して[オーディエンス](audience)を追加します。 5. アプリのコードでそのプレースメントの[ペイウォールを表示](flutter-paywalls)します。オンボーディングにペイウォールを開くボタンがある場合は、[そのボタンのアクションへのレスポンス](flutter-handling-onboarding-events#opening-a-paywall)としてペイウォールのコードを実装してください。 --- # File: flutter-sdk-call-order --- --- title: "Flutter SDK のコール順序" description: "Adapty SDK メソッドを正しい順序でコールすることで、プレミアムアクセスの喪失、アトリビューションの欠落、断続的な #2002 エラーを防ぎます。" --- `Adapty().activate()` が完了してから、他の Adapty SDK メソッドを呼び出してください。解決されるまで SDK には状態がありません。`activate()` より前、または並行して発行されたコールはすべて [`#2002 notActivated`](error-handling-on-flutter-react-native-unity#custom-network-codes) でエラーになります。 アプリがユーザー認証を行い、起動後に customer user ID を収集する場合は、そのタイミングで `Adapty().identify()` を呼び出してください。`identify` が解決されるまでユーザーアクションメソッドを呼び出してはいけません。`identify` と競合するコールは [`#3006 profileWasChanged`](error-handling-on-flutter-react-native-unity#custom-network-codes) でエラーになるか、アクティベーション時に作成された匿名プロファイルに対して実行されてしまいます。これが起きると、アトリビューション、`appsflyer_id` などの MMP ID、およびインストールの所有権が識別済みプロファイルに引き継がれないことがあります。アプリがユーザー認証を行わない場合は `identify` をスキップし、匿名プロファイルのまま使用し続けてください。 MMP やアナリティクス SDK(AppsFlyer、Adjust、Branch、PostHog)も同じルールに従います。それらを先に初期化し、UID コールバックを受け取ってから `Adapty().activate` を呼び出してください。そうしないと MMP ID が一時的な匿名プロファイルに記録され、識別済みプロファイルに必ずしも引き継がれません。AppsFlyer の詳細については [AppsFlyer](appsflyer) をご覧ください。 ## 正しい順序 \{#the-correct-order\} どのパスをたどるかは、customer user ID をいつ取得できるか、および MMP やアナリティクス SDK を使用するかどうかの 2 点によって決まります。 - **ステップ 2 と 5**: すべてのアプリで必須です。SDK をアクティベートしてから SDK メソッドを呼び出します。 - **ステップ 1 と 3**: MMP やアナリティクス SDK(AppsFlyer、Adjust、Branch、PostHog)を統合する場合のみ必要です。 - **ステップ 4**: アプリがユーザー認証を行い、起動後に customer user ID を収集する場合のみ必要です。 アプリ起動時に customer user ID が分かっている場合は、`activate()` に直接渡してください(ステップ 2a)。このパスでは匿名プロファイルが作成されないため、ステップ 4 は不要です。 | ステップ | コール | タイミング | 備考 | |------|---------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------| | 1 | MMP またはアナリティクス SDK(AppsFlyer、Adjust、PostHog、Branch)を初期化する | アプリ起動時、最初に | MMP の UID コールバック(例: `getAppsFlyerUID`)を待ちます。 | | 2a | `Adapty().activate(configuration: ...)` に `withCustomerUserId` を設定して呼び出す | アプリ起動時、ステップ 1 の後、customer user ID が分かっている場合 | 推奨。匿名プロファイルは一切作成されません。 | | 2b | `Adapty().activate(configuration: ...)` を `withCustomerUserId` なしで呼び出す | アプリ起動時、ステップ 1 の後、customer user ID が分からない場合(または収集しない場合) | Adapty が匿名プロファイルを作成します。 | | 3 | 各 MMP に対して `Adapty().setIntegrationIdentifier(key: ..., value: ...)` を呼び出す | ステップ 2 の後、ユーザーアクションコールの前 | MMP ID が正しいプロファイルに記録されるために必要です。 | | 4 | `await Adapty().identify(customerUserId)` | ステップ 3 の後(MMP がない場合はステップ 2 の後)、ステップ 5 の前 — 認証ありのパス 2b の場合のみ | 必ず `await` してください。`identify` 中の並行コールは `#3006 profileWasChanged` を引き起こします。 | | 5 | `getPaywall`、`getPaywallProducts`、`restorePurchases`、`makePurchase`、`updateAttribution`、`updateProfile` | `identify` を呼び出す場合はステップ 4 の後、それ以外はステップ 3 の後(MMP がない場合はステップ 2 の後) | これらのコールには安定したプロファイルが必要です。 | :::important これらのステップをスキップすると、復帰ユーザーのプレミアムアクセスが失われたり、プロファイルに `appsflyer_id` が記録されなかったり、間違ったオーディエンスに対してペイウォールが返されたりする原因になります。 ::: ## Web2app およびウェブファネル経由のインストール \{#web2app-and-web-funnel-installs\} ユーザーがウェブのチェックアウト(Stripe、Paddle)で購入してからネイティブアプリをインストールする場合、デバイス上で最初に `activate()` を呼び出すと新しい匿名プロファイルが作成されます。このプロファイルはウェブのプロファイルとは紐付けられません。アプリ起動前に(認証フローやインストールリファラーから)customer user ID を解決できる場合は、`activate()` に直接渡してください。そうでない場合、`identify("YOUR_USER_ID")` を呼び出してから `restorePurchases` を実行するまで、ウェブでの購入はデバイス上で表示されません。 各ウェブチェックアウトで送信するメタデータについては以下をご覧ください。 - [Stripe](stripe) - [Paddle](paddle) --- # File: flutter-optimize-paywall-fetching --- --- title: "Flutter SDKでペイウォールの取得を最適化する" description: "Adapty ペイウォールを確実に取得する: Flutter向けのタイミング、キャッシュ、フォールバックパターン。" --- Flutter での確実なペイウォール取得には、高速なレンダリング、オーディエンスターゲットされたペイウォールの返却、そしてネットワークが遅い場合のグレースフルなフォールバックという3つの要素が必要です。以下のルールでは、それを実現するためのタイミング、キャッシュ、フォールバックパターンについて説明します。 :::tip これらのルールは、`Adapty().activate()` と `Adapty().identify()` がすでに解決済みであることを前提としています。[Flutter SDK のコール順序](flutter-sdk-call-order)を参照してください。 ::: ## ルールと注意点 \{#rules-and-pitfalls\} | こうする | こうしない | 理由 | |---|---|---| | 表示しようとしているプレースメントを取得する。 | 起動時にすべてのプレースメントを同時にプリフェッチする。 | 一括プリフェッチはメインスレッドをブロックし、バースト中にブラックスクリーンが発生する。 | | アトリビューションが解決される機会を得た後(例: `activate` から1〜2秒後、または `didUpdateProfileStream` が発火した後)に `getPaywall` を呼び出す。 | `runApp` の前に `main()` で `getPaywall` を呼び出す。 | アトリビューションがまだ反映されていない。ペイウォールがデフォルトのオーディエンスに対して解決され、セグメントやASAのパーソナライゼーションが暗黙的にバイパスされる。 | | `loadTimeout` を設定し、すべてのプレースメントに対して[フォールバックペイウォール](fallback-paywalls)を構成する。 | `getPaywall` を無期限に待機する。 | タイムアウトがない場合、接続状況の悪いユーザーはネットワークが解決されるまで(またはアプリを閉じるまで)白紙の画面を見続ける。 | `fetchPolicy` および `loadTimeout` パラメーターのリファレンスについては[ペイウォールとプロダクトの取得](fetch-paywalls-and-products-flutter)を、適切なプレースメントの選択については[プレースメント](placements)を参照してください。 ## 接続状況が悪い環境向けのチューニング \{#tune-for-poor-connectivity\} 接続状況が慢性的に悪い市場(農村部、移動中、ルーティングの問題がある地域)向けには: - 最初の取得以外のすべての取得で `fetchPolicy: AdaptyPaywallFetchPolicy.returnCacheDataElseLoad` を設定する。 - Adapty ダッシュボードですべてのプレースメントに[フォールバックペイウォール](fallback-paywalls)を設定する。 - `loadTimeout` を3〜5秒に設定し、タイムアウトが発火した場合はフォールバックを受け入れる。 - `getProfile()` にペイウォールの表示を依存させない。`getPaywall` を独立して呼び出すことで、プロファイルの取得が遅くてもUIをブロックしないようにする。 --- # File: flutter-test --- --- title: "Flutter SDK でのテストとリリース" description: "AdaptyでFlutterアプリのサブスクリプション状態を確認する方法を説明します。" --- Flutter アプリに Adapty SDK をすでに組み込んでいる場合は、すべてが正しく設定されており、iOS と Android の両プラットフォームで購入が期待どおりに機能することを確認するテストを行いましょう。これには、SDK の統合テストと、Apple のサンドボックス環境および Google Play のテスト環境を使った実際の購入フローのテストが含まれます。 ## アプリをテストする \{#test-your-app\} アプリ内課金の包括的なテストについては、プラットフォーム別のテストガイドを参照してください: [iOS テストガイド](test-purchases-in-sandbox) および [Android テストガイド](testing-on-android)。 ## リリースの準備 \{#prepare-for-release\} アプリをストアに申請する前に、[リリースチェックリスト](release-checklist) に従って以下を確認してください: - ストアの接続とサーバー通知が設定されている - 購入が完了し、Adapty に報告されている - アクセスが正しくアンロックおよび復元される - プライバシーおよびレビュー要件を満たしている --- # File: InvalidProductIdentifiers-flutter --- --- title: "Flutter SDK の Code-1000 noProductIDsFound エラーの修正方法" description: "Adapty でサブスクリプションを管理する際の無効なプロダクト識別子エラーを解決します。" --- 1000 コードエラー `noProductIDsFound` は、ペイウォールでリクエストしたプロダクトが App Store に登録されているにもかかわらず、購入可能な状態ではないことを示します。このエラーには `InvalidProductIdentifiers` 警告が伴う場合があります。エラーなしで警告のみが表示される場合は、無視して問題ありません。 `noProductIDsFound` エラーが発生している場合は、以下の手順で解決してください。 ## ステップ 1. バンドル ID を確認する \{#step-2-check-bundle-id\} --- no_index: true --- 1. [App Store Connect](https://appstoreconnect.apple.com/apps) を開きます。アプリを選択し、**General** → **App Information** セクションに進みます。 2. **General Information** サブセクションで **Bundle ID** をコピーします。 <Zoom> <img src="/docs/img/afd5012-bundle_id_apple.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> </Zoom> 3. Adapty のトップメニューから [**App settings** -> **iOS SDK** タブ](https://app.adapty.io/settings/ios-sdk) を開き、コピーした値を **Bundle ID** フィールドに貼り付けます。 <Zoom> <img src="/docs/img/2d64163-bundle_id.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> </Zoom> 4. App Store Connect の **App information** ページに戻り、**Apple ID** をコピーします。 5. Adapty ダッシュボードの [**App settings** -> **iOS SDK**](https://app.adapty.io/settings/ios-sdk) ページで、**Apple app ID** フィールドにその ID を貼り付けます。 ## ステップ 2. プロダクトを確認する \{#step-3-check-products\} 1. **App Store Connect** を開き、左側のメニューから [**Monetization** → **Subscriptions**](https://appstoreconnect.apple.com/apps/6477523342/distribution/subscriptions) に移動します。 <img src="/assets/shared/img/subscription_group_open.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. サブスクリプショングループ名をクリックすると、**Subscriptions** セクションにプロダクトの一覧が表示されます。 3. テスト対象のプロダクトが **Ready to Submit** になっていることを確認します。 <img src="/assets/shared/img/ready-to-submit.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. テーブルのプロダクト ID と Adapty ダッシュボードの [**Products**](https://app.adapty.io/products) タブのプロダクト ID を比較します。ID が一致しない場合は、テーブルからプロダクト ID をコピーし、Adapty ダッシュボードでそれを使って[プロダクトを作成](create-product)してください。 <img src="/assets/shared/img/product-id-copy.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## ステップ 3. プロダクトの販売状況を確認する \{#step-4-check-product-availability\} 1. **App Store Connect** に戻り、同じ **Subscriptions** セクションを開きます。 <img src="/assets/shared/img/subscription_group_open.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. サブスクリプショングループ名をクリックしてプロダクト一覧を表示します。 3. テスト対象のプロダクトを選択します。 <img src="/assets/shared/img/click-product.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **Availability** セクションまでスクロールし、必要な国と地域がすべて表示されていることを確認します。 <img src="/assets/shared/img/product-availability.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## ステップ 4. プロダクトの価格を確認する \{#step-5-check-product-prices\} 1. **App Store Connect** の **Monetization** → **Subscriptions** セクションに移動します。 <img src="/assets/shared/img/subscription_group_open.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. サブスクリプショングループ名をクリックします。 3. テスト対象のプロダクトを選択します。 <img src="/assets/shared/img/click-product.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **Subscription Pricing** までスクロールし、**Current Pricing for New Subscribers** セクションを展開します。 <img src="/assets/shared/img/check-prices.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. 必要な価格がすべて表示されていることを確認します。 <img src="/assets/shared/img/product-pricing.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## ステップ 5. アプリの有料ステータス、銀行口座、税務フォームがアクティブであることを確認する \{#step-5-check-app-paid-status-bank-account-and-tax-forms-are-active\} 1. [**App Store Connect**](https://appstoreconnect.apple.com/) のホームページで **Business** をクリックします。 <img src="/assets/shared/img/business.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. 会社名を選択します。 <img src="/assets/shared/img/business-name.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. スクロールして、**Paid Apps Agreement**、**Bank Account**、**Tax forms** がいずれも **Active** になっていることを確認します。 <img src="/assets/shared/img/appstore-connect-status.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 以上の手順を実施することで、`InvalidProductIdentifiers` 警告を解消し、プロダクトをストアで公開できるようになります。 ## ステップ 6. 解決しない場合はプロダクトを作り直す \{#step-6-recreate-the-product-if-its-stuck\} ステップ 1〜5 をすべてクリアしても — ステータスが `Approved`、バンドル ID が一致、API キーが有効 — SDK が依然として `1000 noProductIDsFound` を返す場合があります。この場合、プロダクトが Apple のレジストリで詰まっている可能性があります。App Store Connect の UI 上にはプロダクトが存在しているにもかかわらず、StoreKit のルックアップパスに公開されていない状態になることがあります。 App Store Connect でそのプロダクトを削除し、同じプロダクト ID で再作成してください。再作成後、反映されるまで最大 24 時間かかる場合があります。 --- # File: cantMakePayments-flutter --- --- title: "Flutter SDKにおけるコード1003 cantMakePaymentエラーの修正" description: "Adaptyでサブスクリプションをサブスクリプションをサブスクリプションをサブスクリプションをサブスクリプションを管理する際のアプリ内課金エラーを解消します。" --- 1003エラー(`cantMakePayments`)は、このデバイスでアプリ内課金ができないことを示しています。 `cantMakePayments`エラーが発生している場合、通常は以下のいずれかの原因が考えられます: - デバイスの制限:このエラーはAdaptyとは無関係です。以下の解決方法を参照してください。 - オブザーバーモードの設定:`makePurchase`メソッドとオブザーバーモードは同時に使用できません。以下のセクションを参照してください。 ## 問題:デバイスの制限 \{#issue-device-restrictions\} | 問題 | 解決方法 | |-----------------------------|---------------------------------------------------------| | スクリーンタイムの制限 | [スクリーンタイム](https://support.apple.com/en-us/102470)でアプリ内課金の制限を無効にする | | アカウントの停止 | Appleサポートに連絡してアカウントの問題を解決する | | 地域の制限 | 対応地域のApp Storeアカウントを使用する | ## 問題:オブザーバーモードとmakePurchaseの併用 \{#issue-using-both-observer-mode-and-makepurchase\} 購入処理に`makePurchase`を使用している場合、オブザーバーモードを使用する必要はありません。[オブザーバーモード](observer-vs-full-mode)が必要なのは、購入ロジックを自分で実装する場合のみです。 したがって、`makePurchase`を使用している場合は、SDK有効化コードからオブザーバーモードの有効化を安全に削除できます。 --- # File: flutter-migration-guide-310 --- --- title: "Flutter Adapty SDK 3.10.0 への移行ガイド" description: "" --- Adapty SDK 3.10.0 はメジャーリリースであり、いくつかの改善が含まれていますが、移行作業が必要になる場合があります。 1. `makePurchase` メソッドを、個別のパラメーターの代わりに `AdaptyPurchaseParameters` を使用するように更新する。 2. `AdaptyPaywall` モデル内の `vendorProductIds` を `productIdentifiers` に置き換える。 ## makePurchase メソッドの更新 \{#update-makepurchase-method\} `makePurchase` メソッドは、個別の `subscriptionUpdateParams` および `isOfferPersonalized` 引数の代わりに `AdaptyPurchaseParameters` を使用するようになりました。これにより、型の安全性が向上し、将来的に購入パラメーターを拡張しやすくなります。 ```diff showLineNumbers - final purchaseResult = await adapty.makePurchase( - product: product, - subscriptionUpdateParams: subscriptionUpdateParams, - isOfferPersonalized: true, - ); + final parameters = AdaptyPurchaseParametersBuilder() + ..setSubscriptionUpdateParams(subscriptionUpdateParams) + ..setIsOfferPersonalized(true) + ..setObfuscatedAccountId('your-account-id') + ..setObfuscatedProfileId('your-profile-id'); + final purchaseResult = await adapty.makePurchase( + product: product, + parameters: parameters.build(), + ); ``` 追加のパラメーターが不要な場合は、次のようにシンプルに記述できます。 ```dart showLineNumbers final purchaseResult = await adapty.makePurchase( product: product, ); ``` ## AdaptyPaywall モデルの使用方法の更新 \{#update-adaptypaywall-model-usage\} `vendorProductIds` プロパティは非推奨となり、`productIdentifiers` が推奨されるようになりました。新しいプロパティは、単純な文字列の代わりに `AdaptyProductIdentifier` オブジェクトを返すため、プロダクト情報がより構造化されています。 ```diff showLineNumbers - paywall.vendorProductIds.map((vendorId) => - ListTextTile(title: vendorId) - ).toList() + paywall.productIdentifiers.map((productId) => + ListTextTile(title: productId.vendorProductId) + ).toList() ``` `AdaptyProductIdentifier` オブジェクトは `vendorProductId` プロパティを通じてベンダープロダクト ID にアクセスでき、同等の機能を維持しながら将来の拡張に向けてより良い構造を提供します。 ## 後方互換性 \{#backward-compatibility\} どちらの変更も後方互換性を維持しています。 - `makePurchase` の旧パラメーターは非推奨ですが、引き続き機能します - `vendorProductIds` プロパティは非推奨ですが、引き続きアクセス可能です - 既存のコードは動作し続けますが、非推奨の警告が表示されます 新しい API を使用するようにコードを更新することを推奨します。これにより、将来の互換性が確保され、改善された型の安全性と拡張性のメリットを活用できます。 --- # File: flutter-migration-guide-38 --- --- title: "Adapty Flutter SDK を v3.8 へ移行する" description: "Adapty Flutter SDK v3.8 へ移行して、パフォーマンス向上と新しいマネタイズ機能を利用しましょう。" --- Adapty SDK 3.8.0 はメジャーリリースで、いくつかの改善が加えられています。ただし、移行作業が必要になる場合があります。 1. オブザーバークラスとメソッド名を更新する。 2. フォールバックペイウォールのメソッド名を更新する。 3. イベントハンドリングメソッドのビュークラス名を更新する。 ## オブザーバークラスとメソッド名を更新する \{#update-observer-class-and-method-names\} オブザーバークラスとその登録メソッドの名前が変更されました: ```diff showLineNumbers - class MyObserver extends AdaptyUIObserver { + class MyObserver extends AdaptyUIPaywallsEventsObserver { @override void paywallViewDidPerformAction(AdaptyUIView view, AdaptyUIAction action) { // Handle action } } // Register observer - AdaptyUI().setObserver(this); + AdaptyUI().setPaywallsEventsObserver(this); ``` ## フォールバックペイウォールのメソッド名を更新する \{#update-fallback-paywalls-method-name\} フォールバックペイウォールを設定するメソッドが簡略化されました: ```diff showLineNumbers try { - await Adapty.setFallbackPaywalls(assetId); + await Adapty.setFallback(assetId); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` ## イベントハンドリングメソッドのビュークラス名を更新する \{#update-view-class-name-in-event-handling-methods\} すべてのイベントハンドリングメソッドで、`AdaptyUIView` の代わりに新しい `AdaptyUIPaywallView` クラスが使用されるようになりました: ```diff showLineNumbers - void paywallViewDidPerformAction(AdaptyUIView view, AdaptyUIAction action) + void paywallViewDidPerformAction(AdaptyUIPaywallView view, AdaptyUIAction action) - void paywallViewDidSelectProduct(AdaptyUIView view, AdaptyPaywallProduct product) + void paywallViewDidSelectProduct(AdaptyUIPaywallView view, AdaptyPaywallProduct product) - void paywallViewDidStartPurchase(AdaptyUIView view, AdaptyPaywallProduct product) + void paywallViewDidStartPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product) - void paywallViewDidFinishPurchase(AdaptyUIView view, AdaptyPaywallProduct product, AdaptyProfile profile) + void paywallViewDidFinishPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product, AdaptyProfile profile) - void paywallViewDidFailPurchase(AdaptyUIView view, AdaptyPaywallProduct product, AdaptyError error) + void paywallViewDidFailPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product, AdaptyError error) - void paywallViewDidFinishRestore(AdaptyUIView view, AdaptyProfile profile) + void paywallViewDidFinishRestore(AdaptyUIPaywallView view, AdaptyProfile profile) - void paywallViewDidFailRestore(AdaptyUIView view, AdaptyError error) + void paywallViewDidFailRestore(AdaptyUIPaywallView view, AdaptyError error) - void paywallViewDidFailLoadingProducts(AdaptyUIView view, AdaptyIOSProductsFetchPolicy? fetchPolicy, AdaptyError error) + void paywallViewDidFailLoadingProducts(AdaptyUIPaywallView view, AdaptyIOSProductsFetchPolicy? fetchPolicy, AdaptyError error) - void paywallViewDidFailRendering(AdaptyUIView view, AdaptyError error) + void paywallViewDidFailRendering(AdaptyUIPaywallView view, AdaptyError error) ``` --- # File: migration-to-flutter-sdk-34 --- --- title: "Adapty Flutter SDK を v3.4 に移行する" description: "パフォーマンス向上と新しいマネタイズ機能のために Adapty Flutter SDK v3.4 に移行します。" --- Adapty SDK 3.4.0 はメジャーリリースであり、お客様側での移行手順が必要な改善が含まれています。 ## フォールバックペイウォールファイルを更新する \{#update-fallback-paywall-files\} 新しい SDK バージョンとの互換性を確保するため、フォールバックペイウォールファイルを更新してください。 1. Adapty ダッシュボードから[更新されたフォールバックペイウォールファイルをダウンロード](fallback-paywalls)します。 2. モバイルアプリ内の既存のフォールバックペイウォールを[新しいファイルに置き換え](flutter-use-fallback-paywalls)ます。 ## オブザーバーモードの実装を更新する \{#update-implementation-of-observer-mode\} オブザーバーモードを使用している場合は、その実装を更新してください。 以前は、トランザクションを Adapty に報告するために異なるメソッドが使用されていました。新しいバージョンでは、Android と iOS の両方で `reportTransaction` メソッドを一貫して使用する必要があります。このメソッドは各トランザクションを Adapty に明示的に報告し、認識されることを保証します。ペイウォールが使用された場合は、バリエーション ID を渡してトランザクションをペイウォールに紐付けてください。 :::warning **トランザクションの報告をスキップしないでください!** `reportTransaction` を呼び出さない場合、Adapty はトランザクションを認識せず、アナリティクスに表示されず、インテグレーションにも送信されません。 ::: ```diff showLineNumbers - // every time when calling transaction.finish() - if (Platform.isAndroid) { - try { - await Adapty().restorePurchases(); - } on AdaptyError catch (adaptyError) { - // handle the error - } catch (e) { - } - } try { // every time when calling transaction.finish() await Adapty().reportTransaction( "YOUR_TRANSACTION_ID", variationId: "PAYWALL_VARIATION_ID", // optional ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` --- # File: migration-to-flutter330 --- --- title: "Adapty Flutter SDK を v3.3 に移行する" description: "パフォーマンス向上と新しいマネタイズ機能のために Adapty Flutter SDK v3.3 に移行します。" --- Adapty SDK 3.3.0 はメジャーリリースであり、いくつかの改善が加えられましたが、移行作業が必要になる場合があります。 1. フォールバックペイウォールを提供するメソッドを更新する。 2. `getProductsIntroductoryOfferEligibility` メソッドを削除する。 3. Adjust、AirBridge、Amplitude、AppMetrica、Appsflyer、Branch、Facebook Ads、Firebase and Google Analytics、Mixpanel、OneSignal、Pushwoosh のインテグレーション設定を更新する。 4. Observer モードの実装を更新する。 ## フォールバックペイウォールを提供するメソッドを更新する \{#update-method-for-providing-fallback-paywalls\} 以前は、メソッドにフォールバックペイウォールを JSON 文字列(`jsonString`)として渡していましたが、現在はローカルのフォールバックファイルへのパス(`assetId`)を渡すように変更されました。 ```diff showLineNumbers import 'dart:async' show Future; import 'dart:io' show Platform; -import 'package:flutter/services.dart' show rootBundle; -final filePath = Platform.isIOS ? 'assets/ios_fallback.json' : 'assets/android_fallback.json'; -final jsonString = await rootBundle.loadString(filePath); +final assetId = Platform.isIOS ? 'assets/ios_fallback.json' : 'assets/android_fallback.json'; try { - await adapty.setFallbackPaywalls(jsonString); + await adapty.setFallbackPaywalls(assetId); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { } ``` 完全なコード例については、[フォールバックペイウォールを使用する](flutter-use-fallback-paywalls)ページをご覧ください。 ## `getProductsIntroductoryOfferEligibility` メソッドを削除する \{#remove-getproductsintroductoryoffereligibility-method\} Adapty iOS SDK 3.3.0 より前は、ユーザーが適格かどうかに関わらず、プロダクトオブジェクトには常にオファーが含まれていました。そのため、オファーを使用する前に適格性を手動で確認する必要がありました。 現在は、ユーザーが適格な場合にのみプロダクトオブジェクトにオファーが含まれます。つまり、適格性を確認する必要がなくなりました。オファーが存在していれば、ユーザーは適格です。 ## サードパーティインテグレーションの SDK 設定を更新する \{#update-third-party-integration-sdk-configuration\} Adapty Flutter SDK 3.3.0 以降でインテグレーションが正しく動作するよう、以下のセクションに従って各インテグレーションの SDK 設定を更新してください。 ### Adjust 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[Adjust インテグレーションの SDK 設定](adjust#connect-your-app-to-adjust)をご覧ください。 ```diff showLineNumbers import 'package:adjust_sdk/adjust.dart'; import 'package:adjust_sdk/adjust_config.dart'; try { final adid = await Adjust.getAdid(); if (adid == null) { // handle the error } + await Adapty().setIntegrationIdentifier( + key: "adjust_device_id", + value: adid, + ); final attributionData = await Adjust.getAttribution(); var attribution = Map<String, String>(); if (attributionData.trackerToken != null) attribution['trackerToken'] = attributionData.trackerToken!; if (attributionData.trackerName != null) attribution['trackerName'] = attributionData.trackerName!; if (attributionData.network != null) attribution['network'] = attributionData.network!; if (attributionData.adgroup != null) attribution['adgroup'] = attributionData.adgroup!; if (attributionData.creative != null) attribution['creative'] = attributionData.creative!; if (attributionData.clickLabel != null) attribution['clickLabel'] = attributionData.clickLabel!; if (attributionData.costType != null) attribution['costType'] = attributionData.costType!; if (attributionData.costAmount != null) attribution['costAmount'] = attributionData.costAmount!.toString(); if (attributionData.costCurrency != null) attribution['costCurrency'] = attributionData.costCurrency!; if (attributionData.fbInstallReferrer != null) attribution['fbInstallReferrer'] = attributionData.fbInstallReferrer!; - Adapty().updateAttribution( - attribution, - source: AdaptyAttributionSource.adjust, - networkUserId: adid, - ); + await Adapty().updateAttribution(attribution, source: "adjust"); } catch (e) { // handle the error } on AdaptyError catch (adaptyError) { // handle the error } ``` ### AirBridge 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[AirBridge インテグレーションの SDK 設定](airbridge#connect-your-app-to-airbridge)をご覧ください。 ```diff showLineNumbers import 'package:airbridge_flutter_sdk/airbridge_flutter_sdk.dart'; final deviceUUID = await Airbridge.state.deviceUUID; try { - final builder = AdaptyProfileParametersBuilder() - ..setAirbridgeDeviceId(deviceUUID); - await Adapty().updateProfile(builder.build()); + await Adapty().setIntegrationIdentifier( + key: "airbridge_device_id", + value: deviceUUID, + ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` ### Amplitude 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[Amplitude インテグレーションの SDK 設定](amplitude#sdk-configuration)をご覧ください。 ```diff showLineNumbers import 'package:amplitude_flutter/amplitude.dart'; final Amplitude amplitude = Amplitude.getInstance(instanceName: "YOUR_INSTANCE_NAME"); final deviceId = await amplitude.getDeviceId(); final userId = await amplitude.getUserId(); try { - final builder = AdaptyProfileParametersBuilder() - ..setAmplitudeDeviceId(deviceId) - ..setAmplitudeUserId(userId); - await adapty.updateProfile(builder.build()); + await Adapty().setIntegrationIdentifier( + key: "amplitude_user_id", + value: userId, + ); + await Adapty().setIntegrationIdentifier( + key: "amplitude_device_id", + value: deviceId, + ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` ### AppMetrica 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[AppMetrica インテグレーションの SDK 設定](appmetrica#sdk-configuration)をご覧ください。 ```diff showLineNumbers import 'package:appmetrica_plugin/appmetrica_plugin.dart'; final deviceId = await AppMetrica.deviceId; if (deviceId != null) { try { - final builder = AdaptyProfileParametersBuilder() - ..setAppmetricaDeviceId(deviceId) - ..setAppmetricaProfileId("YOUR_ADAPTY_CUSTOMER_USER_ID"); - - await adapty.updateProfile(builder.build()); + await Adapty().setIntegrationIdentifier( + key: "appmetrica_device_id", + value: deviceId, + ); + await Adapty().setIntegrationIdentifier( + key: "appmetrica_profile_id", + value: "YOUR_ADAPTY_CUSTOMER_USER_ID", + ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } } ``` ### AppsFlyer 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[AppsFlyer インテグレーションの SDK 設定](appsflyer#connect-your-app-to-appsflyer)をご覧ください。 ```diff showLineNumbers import 'package:appsflyer_sdk/appsflyer_sdk.dart'; AppsflyerSdk appsflyerSdk = AppsflyerSdk(<YOUR_OPTIONS>); appsflyerSdk.onInstallConversionData((data) async { try { final appsFlyerUID = await appsFlyerSdk.getAppsFlyerUID(); - await Adapty().updateAttribution( - data, - source: AdaptyAttributionSource.appsflyer, - networkUserId: appsFlyerUID, - ); + await Adapty().setIntegrationIdentifier( + key: "appsflyer_id", + value: appsFlyerUID, + ); + + await Adapty().updateAttribution(data, source: "appsflyer"); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } }); appsflyerSdk.initSdk( registerConversionDataCallback: true, registerOnAppOpenAttributionCallback: true, registerOnDeepLinkingCallback: true, ); ``` ### Branch 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[Branch インテグレーションの SDK 設定](branch#connect-your-app-to-branch)をご覧ください。 ```diff showLineNumbers FlutterBranchSdk.initSession().listen((data) async { try { + await Adapty().setIntegrationIdentifier( + key: "branch_id", + value: <BRANCH_IDENTITY_ID>, + ); - await Adapty().updateAttribution(data, source: AdaptyAttributionSource.branch); + await Adapty().updateAttribution(data, source: "branch"); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ); ``` ### Firebase and Google Analytics 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[Firebase and Google Analytics インテグレーションの SDK 設定](firebase-and-google-analytics)をご覧ください。 ```diff showLineNumbers final appInstanceId = await FirebaseAnalytics.instance.appInstanceId; try { - final builder = AdaptyProfileParametersBuilder() - ..setFirebaseAppInstanceId(appInstanceId); - await adapty.updateProfile(builder.build()); + await Adapty().setIntegrationIdentifier( + key: "firebase_app_instance_id", + value: appInstanceId, + ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` ### Mixpanel 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[Mixpanel インテグレーションの SDK 設定](mixpanel#sdk-configuration)をご覧ください。 ```diff showLineNumbers final mixpanel = await Mixpanel.init("Your Token", trackAutomaticEvents: true); final distinctId = await mixpanel.getDistinctId(); try { - final builder = AdaptyProfileParametersBuilder() - ..setMixpanelUserId(distinctId); - await Adapty().updateProfile(builder.build()); + await Adapty().setIntegrationIdentifier( + key: "mixpanel_user_id", + value: distinctId, + ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` ### OneSignal 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[OneSignal インテグレーションの SDK 設定](onesignal#sdk-configuration)をご覧ください。 ```diff showLineNumbers OneSignal.shared.setSubscriptionObserver((changes) { final playerId = changes.to.userId; if (playerId != null) { - final builder = - AdaptyProfileParametersBuilder() - ..setOneSignalPlayerId(playerId); - // ..setOneSignalSubscriptionId(playerId); try { - Adapty().updateProfile(builder.build()); + await Adapty().setIntegrationIdentifier( + key: "one_signal_player_id", + value: playerId, + ); } on AdaptyError catch (adaptyError) { // handle error } catch (e) { // handle error } } }); ``` ### Pushwoosh 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[Pushwoosh インテグレーションの SDK 設定](pushwoosh#sdk-configuration)をご覧ください。 ```diff showLineNumbers final hwid = await Pushwoosh.getInstance.getHWID; - final builder = AdaptyProfileParametersBuilder() - ..setPushwooshHWID(hwid); try { - await adapty.updateProfile(builder.build()); + await Adapty().setIntegrationIdentifier( + key: "pushwoosh_hwid", + value: hwid, + ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` ## Observer モードの実装を更新する \{#update-observer-mode-implementation\} ペイウォールとトランザクションを紐付ける方法を更新してください。以前は `setVariationId` メソッドを使って `variationId` を割り当てていましたが、現在は新しい `reportTransaction` メソッドでトランザクションを記録する際に `variationId` を直接含めることができます。最終的なコード例については、[Observer モードでペイウォールを購入トランザクションに関連付ける](report-transactions-observer-mode-flutter)をご覧ください。 :::warning `reportTransaction` メソッドを使ってトランザクションを必ず記録してください。この手順を省略すると、Adapty はトランザクションを認識できず、アクセスレベルの付与、アナリティクスへの記録、インテグレーションへの送信がいずれも行われません。この手順は必須です! ::: ```diff showLineNumbers try { - await Adapty().setVariationId("YOUR_TRANSACTION_ID", "PAYWALL_VARIATION_ID"); + // every time when calling transaction.finish() + await Adapty().reportTransaction( + "YOUR_TRANSACTION_ID", + variationId: "PAYWALL_VARIATION_ID", // optional + ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` --- # File: migration-to-flutter-sdk-v3 --- --- title: "Adapty Flutter SDK v3.0 への移行" description: "より良いパフォーマンスと新しいマネタイズ機能のために、Adapty Flutter SDK v3.0 に移行しましょう。" --- Adapty SDK v3.0 では、ペイウォールを作成するための新しいノーコードツール [Adapty ペイウォールビルダー](adapty-paywall-builder) がサポートされました。最大限の柔軟性と豊富なデザイン機能により、ペイウォールをより効果的かつ収益性の高いものにできます。 :::info AdaptyUI ライブラリは非推奨となり、AdaptySDK の一部として組み込まれました。 ::: ## AdaptyUI SDK の削除 \{#remove-adaptyu-sdk\} 1. AdaptyUI は Adapty SDK のモジュールになったため、`pubspec.yaml` ファイルから `adapty_ui_flutter` を削除してください。 ```diff showLineNumbers dependencies: + adapty_flutter: ^3.2.1 - adapty_flutter: ^2.10.3 - adapty_ui_flutter: ^2.1.3 ``` 2. 以下を実行します。 ```bash showLineNumbers title="Bash" flutter pub get ``` ## Adapty SDK の設定 \{#configure-adapty-sdks\} これまでは、Adapty SDK の設定に `Adapty-Info.plist` および `AndroidManifest.xml` ファイルを使用する必要がありました。 現在は、追加ファイルは不要です。代わりに、アクティベーション時に必要なパラメータをすべて指定できます。 Adapty SDK の設定は、通常アプリのライフサイクル開始時に一度だけ行います。 ### Adapty SDK の Adapty モジュールをアクティベートする \{#activate-adapty-module-of-adapty-sdk\} 1. アプリケーションから AdaptyUI SDK のインポートを次のように削除します。 ```diff showLineNumbers import 'package:adapty_flutter/adapty_flutter.dart'; - import 'package:adapty_ui_flutter/adapty_ui_flutter.dart'; ``` 2. Adapty SDK のアクティベーションを次のように更新します。 ```diff showLineNumbers try { - Adapty().activate(); + await Adapty().activate( + configuration: AdaptyConfiguration(apiKey: 'YOUR_API_KEY') + ..withLogLevel(AdaptyLogLevel.debug) + ..withObserverMode(false) + ..withCustomerUserId(null) + ..withIdfaCollectionDisabled(false) + ..withIpAddressCollectionDisabled(false), + ); } catch (e) { // handle the error } ``` パラメータ: | パラメータ | 必須/任意 | 説明 | | ----------------------------------- | --------- | ------------------------------------------------------------ | | **PUBLIC_SDK_KEY** | 必須 | Adapty のアプリ設定にある **Public SDK key** フィールドで確認できるキーです: [**App settings** -> **General** タブ -> **API keys** セクション](https://app.adapty.io/settings/general) | | **withLogLevel** | 任意 | Adapty はエラーやその他の重要な情報をログに記録し、アプリの動作状況を把握できるようにします。利用可能なレベルは以下のとおりです。<ul><li>error: エラーのみがログに記録されます。</li><li>warn: エラーと、重大なエラーではないが注意が必要な SDK からのメッセージがログに記録されます。</li><li>info: エラー、警告、および各モジュールのライフサイクルなどの重要な情報メッセージがログに記録されます。</li><li>verbose: 関数呼び出し、API クエリなど、デバッグ時に役立つ追加情報がすべてログに記録されます。</li></ul> | | **withObserverMode** | 任意 | <p>[オブザーバーモード](observer-vs-full-mode)を制御する真偽値です。購入とサブスクリプションの状態を自分で管理し、サブスクリプションイベントの送信と分析に Adapty を使用する場合は有効にしてください。</p><p>デフォルト値は `false` です。</p><p></p><p>🚧 オブザーバーモードで動作している場合、Adapty SDK はトランザクションをクローズしないため、自前で処理する必要があります。</p> | | **withCustomerUserId** | 任意 | 自社システムにおけるユーザーの識別子です。サブスクリプションおよび分析イベントに含めて送信し、イベントを正しいプロファイルに紐付けます。[**Profiles and Segments**](https://app.adapty.io/profiles/users) メニューで `customerUserId` によるユーザー検索も可能です。 | | **withIdfaCollectionDisabled** | 任意 | <p>IDFA の収集と共有を無効にするには `true` を設定します。</p><p>ユーザーの IP アドレス共有も無効になります。</p><p>デフォルト値は `false` です。</p><p>IDFA 収集の詳細については、[Analytics integration](analytics-integration#disable-collection-of-advertising-identifiers) セクションをご参照ください。</p> | | **withIpAddressCollectionDisabled** | 任意 | <p>ユーザーの IP アドレスの収集と共有を無効にするには `true` を設定します。</p><p>デフォルト値は `false` です。</p> | ### Adapty SDK の AdaptyUI モジュールをアクティベートする \{#activate-adaptyu-module-of-adapty-sdk\} AdaptyUI モジュールの設定が必要なのは、[ペイウォールビルダー](adapty-paywall-builder)を使用する予定がある場合のみです。 ```dart showLineNumbers title="Dart" try { final mediaCache = AdaptyUIMediaCacheConfiguration( memoryStorageTotalCostLimit: 100 * 1024 * 1024, // 100MB memoryStorageCountLimit: 2147483647, // 2^31 - 1, max int value in Dart diskStorageSizeLimit: 100 * 1024 * 1024, // 100MB ); await AdaptyUI().activate( configuration: AdaptyUIConfiguration(mediaCache: mediaCache), observer: <AdaptyUIObserver Implementation>, ); } catch (e) { // handle the error } ``` AdaptyUI の設定はオプションであり、設定なしで AdaptyUI モジュールをアクティベートすることも可能です。ただし、設定を使用する場合はすべてのパラメータが必須となります。 パラメータ: | パラメータ | 必須/任意 | 説明 | | :------------------------------ | :-------- | :----------------------------------------------------------- | | **memoryStorageTotalCostLimit** | 必須 | ストレージの合計コスト上限(バイト単位)。 | | **memoryStorageCountLimit** | 必須 | メモリストレージのアイテム数上限。 | | **diskStorageSizeLimit** | 必須 | ディスク上のストレージファイルサイズ上限(バイト単位)。0 は上限なしを意味します。 | --- # End of Documentation _Generated on: 2026-06-24T14:36:28.520Z_ _Successfully processed: 41/41 files_ # IOS - Adapty Documentation (Full Content) This file contains the complete content of all documentation pages for this platform. Locale: ja Generated on: 2026-06-24T14:36:28.522Z Total files: 44 --- # File: sdk-installation-ios --- --- title: "iOS SDKのインストールと設定" description: "サブスクリプションアプリ向けに、iOS で Adapty SDK をインストールするステップバイステップガイド。" --- Adapty SDK には、モバイルアプリにシームレスに統合するための 2 つの主要モジュールが含まれています。 - **Core Adapty**: アプリで Adapty を正しく動作させるために必要な必須 SDK です。 - **AdaptyUI**: ノーコードでクロスプラットフォームのペイウォールを簡単に作成できるツール [Adapty ペイウォールビルダー](adapty-paywall-builder) を使用する場合に必要なオプションモジュールです。 :::tip 実際のモバイルアプリへの Adapty SDK 統合例を見たい方は、[サンプルアプリ](https://github.com/adaptyteam/AdaptySDK-iOS/tree/master/Examples)をご覧ください。ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップが確認できます。 ::: 実装の詳細なウォークスルーは、以下の動画でも確認できます。 <Tabs groupId="current-os" queryString> <TabItem value="swiftui" label="iOS (SwiftUI)" default> <div style={{ textAlign: 'center' }}> <iframe width="560" height="315" src="https://www.youtube.com/embed/cSChHc8k2zA?si=KhNFhqXccIzYwTcm" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe> </div> </TabItem> <TabItem value="uikit" label="iOS (UIKit)" default> <div style={{ textAlign: 'center' }}> <iframe width="560" height="315" src="https://www.youtube.com/embed/WEUnlaAjSI0?si=sjXKVVb56tEHDKzJ" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe> </div> </TabItem> </Tabs> ## 必要要件 \{#requirements\} Adapty iOS SDK は iOS 15.0 以降が必要です。 :::important Xcode 26.4 以降でビルドする場合は、Adapty SDK 3.15.7 以上が必要です。 ::: --- no_index: true --- import Callout from '../../../components/Callout.astro'; <Callout type="info"> SDKのインストールは、Adaptyセットアップのステップ5です。アプリ内で課金が機能するようにするには、アプリをストアに接続し、Adapty ダッシュボードでプロダクト、ペイウォール、プレースメントを作成する必要があります。[クイックスタートガイド](quickstart)では、必要なすべての手順を説明しています。 </Callout> ## Adapty SDK のインストール \{#install-adapty-sdk\} [![Release](https://img.shields.io/github/v/release/adaptyteam/AdaptySDK-iOS.svg?style=flat&logo=apple)](https://github.com/adaptyteam/AdaptySDK-iOS/releases) Adapty SDK は Swift Package Manager でインストールします。Xcode で **File** -> **Add Package Dependency...** を選択してください。パッケージ依存関係の追加手順は Xcode のバージョンによって異なる場合があるため、必要に応じて Xcode のドキュメントを参照してください。 1. リポジトリ URL を入力します。 ``` https://github.com/adaptyteam/AdaptySDK-iOS.git ``` 2. バージョンを選択し(最新の安定版を推奨)、**Add Package** をクリックします。 3. **Choose Package Products** ウィンドウで、必要なモジュールを選択します。 - **Adapty**(コアモジュール) - **AdaptyUI**(オプション - ペイウォールビルダーを使用する場合のみ) :::note 注意: - [キッズモード](kids-mode)を有効にするには、**Adapty** の代わりに **Adapty_KidsMode** を選択してください。 - リストに表示される他のパッケージは選択しないでください。それらは不要です。 ::: 4. **Add Package** をクリックしてインストールを完了します。 5. **インストールの確認:** プロジェクトナビゲーターの **Package Dependencies** 以下に「Adapty」(および選択した場合は「AdaptyUI」)が表示されていることを確認してください。 :::important Adapty iOS SDK 4.0 はプレリリース版です。Swift Package Manager は **Up to Next Major Version**(`from:`)ルールではベータ版を解決しないため、正確なバージョンを固定する必要があります。Xcode では **Dependency Rule** を **Exact Version** に設定し、`4.0.0-beta.1` と入力してください。`Package.swift` では `.exact("4.0.0-beta.1")` を使用します。詳しくは [Adapty iOS SDK を v4 へ移行する](migration-to-ios-sdk-v4)をご覧ください。 ::: ## Adapty SDK の Adapty モジュールを有効化する \{#activate-adapty-module-of-adapty-sdk\} アプリのコードで Adapty SDK を有効化します。 :::note Adapty SDK の有効化はアプリ内で 1 度だけ行えば十分です。 ::: **Public SDK Key** を取得するには: 1. Adapty ダッシュボードを開き、[**App settings → General**](https://app.adapty.io/settings/general) に移動します。 2. **Api keys** セクションから **Public SDK Key**(Secret Key ではない方)をコピーします。 3. コード内の `"YOUR_PUBLIC_SDK_KEY"` を置き換えます。 :::important - Adapty の初期化には必ず **Public SDK key** を使用してください。**Secret key** は[サーバーサイド API](getting-started-with-server-side-api) 専用です。 - **SDK keys** はアプリごとに固有です。複数のアプリがある場合は、正しいキーを選択してください。 ::: <Tabs groupId="current-os" queryString> <TabItem value="swiftui" label="SwiftUI"> ```swift showLineNumbers @main struct YourApp: App { init() { // Configure Adapty SDK let configurationBuilder = AdaptyConfiguration .builder(withAPIKey: "YOUR_PUBLIC_SDK_KEY") // Get from Adapty dashboard Adapty.logLevel = .verbose // recommended for development and the first production release let config = configurationBuilder.build() // Activate Adapty SDK asynchronously Task { do { try await Adapty.activate(with: config) } catch { // Handle error appropriately for your app print("Adapty activation failed: ", error) } } var body: some Scene { WindowGroup { // Your content view } } } } ``` </TabItem> <TabItem value="swift" label="UIKit" default> ```swift showLineNumbers // In your AppDelegate class: // If you only use an AppDelegate, place the following code in the // application(_:didFinishLaunchingWithOptions:) method. // If you use a SceneDelegate, place the following code in the // scene(_:willConnectTo:options:) method. Task { do { let configurationBuilder = AdaptyConfiguration .builder(withAPIKey: "YOUR_PUBLIC_SDK_KEY") // Get from Adapty dashboard .with(logLevel: .verbose) // recommended for development and the first production release let config = configurationBuilder.build() try await Adapty.activate(with: config) } catch { // Handle error appropriately for your app print("Adapty activation failed: ", error) } } ``` </TabItem> </Tabs> :::important 他の Adapty SDK メソッドを呼び出す前に、`activate` の完了を待ってください。完全な呼び出し順序については [iOS SDK の呼び出し順序](ios-sdk-call-order)をご覧ください。 ::: 次に、アプリでペイウォールを設定します。 - [Adapty ペイウォールビルダー](adapty-paywall-builder)を使用する場合は、まず下記の [AdaptyUI モジュールを有効化する](#activate-adaptyui-module-of-adapty-sdk)を行い、その後[ペイウォールビルダーのクイックスタート](ios-quickstart-paywalls)に従ってください。 - 独自のペイウォール UI を構築する場合は、[カスタムペイウォールのクイックスタート](ios-quickstart-manual)をご覧ください。 ## Adapty SDK の AdaptyUI モジュールを有効化する \{#activate-adaptyui-module-of-adapty-sdk\} [ペイウォールビルダー](adapty-paywall-builder)を使用する予定があり、[AdaptyUI モジュールをインストール済み](sdk-installation-ios#install-adapty-sdk)の場合は、AdaptyUI も有効化する必要があります。 :::important コード内では、AdaptyUI を有効化する前に必ずコアの Adapty モジュールを有効化してください。 ::: <Tabs groupId="current-os" queryString> <TabItem value="swiftui" label="SwiftUI"> ```swift showLineNumbers title="Swift" @main struct YourApp: App { init() { // ...ConfigurationBuilder steps // Activate Adapty SDK asynchronously Task { do { try await Adapty.activate(with: config) try await AdaptyUI.activate() } catch { // Handle error appropriately for your app print("Adapty activation failed: ", error) } } // main body... } } ``` </TabItem> <TabItem value="uikit" label="UIKit" default> ```swift showLineNumbers title="UIKit" // If you only use an AppDelegate, place the following code in the // application(_:didFinishLaunchingWithOptions:) method. // If you use a SceneDelegate, place the following code in the // scene(_:willConnectTo:options:) method. Task { do { let configurationBuilder = AdaptyConfiguration .builder(withAPIKey: "YOUR_PUBLIC_SDK_KEY") // Get from Adapty dashboard .with(logLevel: .verbose) // recommended for development let config = configurationBuilder.build() try await Adapty.activate(with: config) try await AdaptyUI.activate() } catch { // Handle error appropriately for your app print("Adapty activation failed: ", error) } } ``` </TabItem> </Tabs> :::tip AdaptyUI を有効化する際に、オプションとして[ペイウォールのデフォルトキャッシュ設定を上書き](#set-up-media-cache-configuration-for-adaptyui)することができます。 ::: ## オプション設定 \{#optional-setup\} ### ログ \{#logging\} #### ログシステムの設定 \{#set-up-the-logging-system\} Adapty は、何が起きているかを把握できるように、エラーや重要な情報をログに記録します。利用可能なレベルは以下のとおりです。 | レベル | 説明 | | ---------- | ------------------------------------------------------------ | | `error` | エラーのみをログに記録します | | `warn` | エラーと、重大なエラーではないが注意が必要な SDK からのメッセージをログに記録します | | `info` | エラー、警告、および各種情報メッセージをログに記録します | | `verbose` | 関数呼び出し、API クエリなど、デバッグ時に役立つ追加情報をすべてログに記録します | ```swift showLineNumbers let configurationBuilder = AdaptyConfiguration .builder(withAPIKey: "YOUR_PUBLIC_SDK_KEY") .with(logLevel: .verbose) // recommended for development ``` #### ログシステムのメッセージをリダイレクトする \{#redirect-the-logging-system-messages\} Adapty のログメッセージを独自のシステムに送信したり、ファイルに保存したりする必要がある場合は、`setLogHandler` メソッドを使用して、その中にカスタムのログロジックを実装してください。このハンドラーは、メッセージ内容と重大度レベルを含むログレコードを受け取ります。 ```swift showLineNumbers title="Swift" Adapty.setLogHandler { record in writeToLocalFile("Adapty \(record.level): \(record.message)") } ``` ### データポリシー \{#data-policies\} Adapty は、明示的に送信しない限りユーザーの個人データを保存しませんが、ストアや各国のガイドラインに準拠するために、追加のデータセキュリティポリシーを実装することができます。 #### IDFA の収集と共有を無効にする \{#disable-idfa-collection-and-sharing\} Adapty モジュールを有効化する際に、`idfaCollectionDisabled` を `true` に設定すると、IDFA の収集と共有を無効にできます。 このパラメーターは、App Store レビューガイドラインに準拠する場合や、アプリで IDFA が不要なときに App Tracking Transparency のプロンプトが表示されるのを避けるために使用してください。デフォルト値は `false` です。IDFA 収集の詳細については、[アナリティクス連携](analytics-integration#disable-collection-of-advertising-identifiers)セクションを参照してください。 ```swift showLineNumbers let configurationBuilder = AdaptyConfiguration .builder(withAPIKey: "YOUR_PUBLIC_SDK_KEY") .with(idfaCollectionDisabled: true) ``` #### IP の収集と共有を無効にする \{#disable-ip-collection-and-sharing\} Adapty モジュールを有効化する際に、`ipAddressCollectionDisabled` を `true` に設定すると、ユーザーの IP アドレスの収集と共有を無効にできます。デフォルト値は `false` です。 このパラメーターは、ユーザーのプライバシーを強化する場合、GDPR や CCPA などの地域データ保護規制に準拠する場合、またはアプリで IP ベースの機能が不要なときに不要なデータ収集を減らす場合に使用してください。 ```swift showLineNumbers let configurationBuilder = AdaptyConfiguration .builder(withAPIKey: "YOUR_PUBLIC_SDK_KEY") .with(ipAddressCollectionDisabled: true) ``` #### AdaptyUI のペイウォール向けメディアキャッシュ設定 \{#set-up-media-cache-configuration-for-adaptyui\} AdaptyUI の設定はオプションです。設定なしで AdaptyUI モジュールを有効化することもできます。ただし、設定を使用する場合はすべてのパラメーターが必須です。 ```swift showLineNumbers title="Swift" // Configure AdaptyUI let adaptyUIConfiguration = AdaptyUI.Configuration( mediaCacheConfiguration: .init( memoryStorageTotalCostLimit: 100 * 1024 * 1024, memoryStorageCountLimit: .max, diskStorageSizeLimit: 100 * 1024 * 1024 ) ) // Activate AdaptyUI AdaptyUI.activate(configuration: adaptyUIConfiguration) ``` パラメーター: | パラメーター | 必須/任意 | 説明 | | :-------------------------- | :------- | :----------------------------------------------------------- | | memoryStorageTotalCostLimit | 必須 | ストレージの合計コスト上限(バイト単位)。 | | memoryStorageCountLimit | 必須 | メモリストレージのアイテム数上限。 | | diskStorageSizeLimit | 必須 | ストレージのディスク上のファイルサイズ上限(バイト単位)。0 は上限なしを意味します。 | ### トランザクション終了の動作 \{#transaction-finishing-behavior\} :::info この機能は SDK バージョン 3.12.0 以降で利用できます。 ::: デフォルトでは、Adapty は検証が成功した後にトランザクションを自動的に終了します。ただし、高度なトランザクション検証(サーバーサイドのレシート検証、不正検出、カスタムビジネスロジックなど)が必要な場合は、SDK が手動でトランザクションを終了するように設定できます。 ```swift showLineNumbers title="Swift" let configurationBuilder = AdaptyConfiguration .builder(withAPIKey: "YOUR_PUBLIC_SDK_KEY") .with(transactionsFinishBehavior: .manual) // .auto is the default ``` トランザクションの終了方法の詳細については、[ガイド](ios-transaction-management)をご覧ください。 ### バックアップ復元時のデータ消去 \{#clear-data-on-backup-restore\} `clearDataOnBackup` を `true` に設定すると、SDK はアプリが iCloud バックアップから復元されたことを検知し、キャッシュされたプロファイル情報、プロダクト詳細、ペイウォールを含むローカルに保存されたすべての SDK データを削除します。SDK はその後クリーンな状態で初期化されます。デフォルト値は `false` です。 :::note 削除されるのはローカルの SDK キャッシュのみです。Apple とのトランザクション履歴および Adapty サーバー上のユーザーデータは変更されません。 ::: ```swift showLineNumbers let configurationBuilder = AdaptyConfiguration .builder(withAPIKey: "YOUR_PUBLIC_SDK_KEY") .with(clearDataOnBackup: true) // default – false ``` ## トラブルシューティング \{#troubleshooting\} #### Tuist での Swift 6 並行性エラー \{#swift-6-concurrency-error-with-tuist\} [Tuist](https://tuist.dev/) でビルドすると、Swift 6 の strict concurrency コンパイルエラーが発生することがあります。典型的な症状としては、`AdaptyUIBuilderLogic` での `@Sendable` 属性の不一致や、類似したモジュール間の Sendability エラーがあります。 これは、Tuist が SPM パッケージから Xcode プロジェクトを生成する際に `swift-tools-version: 6.0` の設定を保持しないために発生します。その結果、一部の Adapty ターゲット(`Adapty`、`AdaptyUI`、`AdaptyUIBuilder`)が Swift 5 のルールでコンパイルされ、他のターゲットが Swift 6 を使用するため、モジュール間で `@Sendable` の不一致が生じます。 **修正方法**: Adapty SDK **3.15.5** 以降にアップグレードしてください。Swift の言語バージョンが混在していても問題が解消されます。 **回避策**: アップグレードできない場合は、Tuist の設定で 3 つの Adapty ターゲットすべてに対して明示的に Swift 6 を設定してください。 ```swift showLineNumbers targetSettings: [ "Adapty": .init().swiftVersion("6"), "AdaptyUI": .init().swiftVersion("6"), "AdaptyUIBuilder": .init().swiftVersion("6"), ] ``` --- # File: ios-quickstart-paywalls --- --- title: "iOS SDKでFlow Builderを使ってアプリ内課金を有効にする" description: "Adapty Flow Builderを使ったアプリ内課金のクイックスタートガイド。" --- アプリ内課金を有効にするには、3つの重要なコンセプトを理解する必要があります。 - [**プロダクト**](product) – ユーザーが購入できるもの(サブスクリプション、消耗型アイテム、永続アクセスなど) - [**フロー**](adapty-flow-builder) – ノーコードのFlow Builderで作成された、ユーザーにプロダクトを提示する画面シーケンス。SDKは`getFlow`を通じてフローを取得します。UIを自分のコードで構築したい場合はペイウォールを使ってください。詳しくは[ペイウォールを手動で実装する](ios-quickstart-manual)を参照してください。 - [**プレースメント**](placements) – アプリのどこでいつフローを表示するかを定義します(`main`、`onboarding`、`settings`など)。ダッシュボードでフローをプレースメントに紐付けて、コードではプレースメントIDで取得します。これにより、A/Bテストの実行や異なるユーザーへの異なるフロー表示が簡単になります。 Adaptyでは、アプリ内課金を有効にする3つの方法を提供しています。アプリの要件に応じて選択してください。 | 実装方法 | 複雑さ | 使用タイミング | |---|---|---| | Adapty Flow Builder | ✅ 簡単 | [ノーコードビルダーで購入準備が整ったフローを作成](quickstart-paywalls)します。Adaptyが自動的にレンダリングし、複雑な購入フロー、レシート検証、サブスクリプション管理をすべて処理します。 | | 手動で作成したペイウォール | 🟡 中程度 | アプリのコードでペイウォールUIを実装しつつ、プロダクト提供の柔軟性を保つためにAdaptyからフローオブジェクトを取得します。詳しくは[ガイド](ios-quickstart-manual)を参照してください。 | | オブザーバーモード | 🔴 難しい | すでに独自の購入処理インフラがあり、それを継続して使いたい場合。オブザーバーモードにはAdaptyでの制限があります。詳しくは[こちら](observer-vs-full-mode)を参照してください。 | :::important **以下の手順は、Adapty Flow Builderで作成したフローを実装する方法を示しています。** ペイウォールUIを自分で構築したい場合は、[ペイウォールを手動で実装する](ios-quickstart-manual)を参照してください。 ::: Adapty Flow Builderで作成したフローをアプリで表示するには、コードで行うことは次の3つだけです。 1. **フローの取得**: Adaptyからフローを取得します。 2. **表示する — 購入はAdaptyが処理**: アプリにビューを表示します。 3. **ボタンアクションの処理**: ユーザーの操作をアプリの応答に紐付けます。例えば、リンクを開いたり、ユーザーがボタンをタップしたときにフローを閉じたりします。 ## 始める前に \{#before-you-start\} 始める前に、以下の手順を完了してください。 1. Adapty ダッシュボードで[アプリをApp Storeに接続](initial_ios)する。 2. Adaptyで[プロダクトを作成](create-product)する。 3. [フローを作成してプロダクトを追加](create-paywall)する。 4. [プレースメントを作成してフローを追加](create-placement)する。 5. アプリのコードに[Adapty SDKをインストールして有効化](sdk-installation-ios)する。このガイドではAdapty iOS SDK v4(ベータ版)のAPIを使用します。 ## 1. フローを取得する \{#1-get-the-flow\} フローはダッシュボードで設定したプレースメントに紐付けられています。プレースメントを使うと、異なるオーディエンスに対して異なるフローを実行したり、[A/Bテスト](ab-tests)を実行したりできます。 Adapty Flow Builderで作成したフローを取得するには、次の手順を行います。 1. `getFlow`メソッドを使って[プレースメント](placements)IDからフローオブジェクトを取得し、ビュー設定があるかどうかを確認する。 2. `getFlowConfiguration`メソッドを使ってビュー設定を取得する。このビュー設定には、フローの表示に必要なUI要素とスタイリングが含まれています。 ```swift func loadFlow() async { let flow = try await Adapty.getFlow(placementId: "YOUR_PLACEMENT_ID") guard flow.hasViewConfiguration else { print("Flow doesn't have a view configuration") return } flowConfiguration = try await AdaptyUI.getFlowConfiguration(forFlow: flow) } ``` ## 2. フローを表示する \{#2-display-the-flow\} フロー設定を取得したら、数行追加するだけでフローを表示できます。 <Tabs groupId="current-os" queryString> <TabItem value="swiftui" label="SwiftUI" default> SwiftUIでは、フローを表示する際にイベントも処理する必要があります。`didFailPurchase`、`didFinishRestore`、`didFailRestore`、`didReceiveError`は必須です。テスト中は、以下のスニペットのコードをコピーしてこれらのイベントをログ出力することができます。 :::tip `didFinishPurchase`の処理は必須ではありませんが、購入成功後にアクションを実行したい場合に便利です。このコールバックを実装しない場合、フローは自動的に閉じられます。 ::: ```swift .flow( isPresented: $flowPresented, flowConfiguration: flowConfiguration, didFailPurchase: { product, error in print("Purchase failed: \(error)") }, didFinishRestore: { profile in print("Restore finished successfully") }, didFailRestore: { error in print("Restore failed: \(error)") }, didReceiveError: { error in flowPresented = false print("Flow error: \(error)") } ) ``` </TabItem> <TabItem value="uikit" label="UIKit" default> ```swift func presentFlow(with config: AdaptyUI.FlowConfiguration) { let flowController = try AdaptyUI.flowController( with: config, delegate: self ) present(flowController, animated: true) } ``` イベントを処理するために`AdaptyFlowControllerDelegate`を実装します。最低限、デフォルト実装がない3つのメソッド(必須のエラーハンドラー)を実装してください。 ```swift extension YourViewController: AdaptyFlowControllerDelegate { func flowController(_ controller: AdaptyFlowController, didFailPurchase product: AdaptyPaywallProduct, error: AdaptyError) { print("Purchase failed: \(error)") } func flowController(_ controller: AdaptyFlowController, didFinishRestoreWith profile: AdaptyProfile) { print("Restore finished successfully") } func flowController(_ controller: AdaptyFlowController, didFailRestoreWith error: AdaptyError) { print("Restore failed: \(error)") } } ``` </TabItem> </Tabs> :::info フローの表示方法の詳細については、[ガイド](ios-present-paywalls)を参照してください。 ::: ## 3. ボタンアクションを処理する \{#3-handle-button-actions\} ユーザーがボタンをタップすると、iOS SDKは購入、復元、フローのクローズ、リンクの開封を自動的に処理します。 ただし、他のボタンにはカスタムまたは事前定義されたIDがあり、コードでアクションを処理する必要があります。または、デフォルトの動作を上書きしたい場合もあります。 例えば、クローズボタンの処理方法を次に示します。UIKitでは、`.close`が発火すると SDKが自動的にコントローラーを閉じます — カスタム動作が必要な場合のみオーバーライドしてください。SwiftUIでは、`isPresented`バインディングを自分で`false`に設定する必要があります。 :::tip ボタンの[アクション](handle-paywall-actions)と[イベント](ios-handling-events)の処理方法については、各ガイドを参照してください。 ::: <Tabs groupId="current-os" queryString> <TabItem value="swiftui" label="SwiftUI" default> ```swift .flow( isPresented: $flowPresented, flowConfiguration: flowConfiguration, didPerformAction: { action in switch action { case .close: flowPresented = false // dismiss the flow when the user taps close default: break } }, didFailPurchase: { product, error in /* handle the error */ }, didFinishRestore: { profile in /* check access level and dismiss */ }, didFailRestore: { error in /* handle the error */ }, didReceiveError: { error in flowPresented = false } ) ``` </TabItem> <TabItem value="uikit" label="UIKit" default> ```swift extension YourViewController: AdaptyFlowControllerDelegate { func flowController(_ controller: AdaptyFlowController, didPerform action: AdaptyUI.Action) { switch action { case .close: controller.dismiss(animated: true) // default behavior — override only if needed default: break } } } ``` </TabItem> </Tabs> ## 次のステップ \{#next-steps\} --- no_index: true --- import Callout from '../../../components/Callout.astro'; <Callout type="tip"> ご質問やお困りのことがあれば、[サポートフォーラム](https://adapty.featurebase.app/)をご覧ください。よくある質問への回答を見つけたり、ご自身の質問を投稿することができます。チームとコミュニティがサポートいたします! </Callout> フローをアプリで表示する準備ができました。[サンドボックスモードで購入をテスト](test-purchases-in-sandbox)して、テスト購入が正常に完了できることを確認してください。 次に、適切なユーザーにフローを表示したり有料機能へのアクセスを付与したりするために、[ユーザーのアクセスレベルを確認](ios-check-subscription-status)する必要があります。 ## 完全なサンプル \{#full-example\} このガイドのすべての手順をアプリに統合した例を以下に示します。 <Tabs groupId="current-os" queryString> <TabItem value="swiftui" label="SwiftUI" default> ```swift struct ContentView: View { @State private var flowPresented = false @State private var flowConfiguration: AdaptyUI.FlowConfiguration? @State private var isLoading = false @State private var hasInitialized = false var body: some View { VStack { if isLoading { ProgressView("Loading...") } else { Text("Your App Content") } } .task { guard !hasInitialized else { return } await initializeFlow() hasInitialized = true } .flow( isPresented: $flowPresented, flowConfiguration: flowConfiguration, didPerformAction: { action in switch action { case .close: flowPresented = false default: break } }, didFailPurchase: { product, error in print("Purchase failed: \(error)") }, didFinishRestore: { profile in print("Restore finished successfully") }, didFailRestore: { error in print("Restore failed: \(error)") }, didReceiveError: { error in print("Flow error: \(error)") flowPresented = false } ) } private func initializeFlow() async { isLoading = true defer { isLoading = false } await loadFlow() flowPresented = true } private func loadFlow() async { do { let flow = try await Adapty.getFlow(placementId: "YOUR_PLACEMENT_ID") guard flow.hasViewConfiguration else { print("Flow doesn't have a view configuration") return } flowConfiguration = try await AdaptyUI.getFlowConfiguration(forFlow: flow) } catch { print("Failed to load: \(error)") } } } ``` </TabItem> <TabItem value="uikit" label="UIKit" default> ```swift class ViewController: UIViewController { private var flowConfiguration: AdaptyUI.FlowConfiguration? override func viewDidLoad() { super.viewDidLoad() Task { await initializeFlow() } } private func initializeFlow() async { do { flowConfiguration = try await loadFlow() if let flowConfiguration { await MainActor.run { presentFlow(with: flowConfiguration) } } } catch { print("Error initializing: \(error)") } } private func loadFlow() async throws -> AdaptyUI.FlowConfiguration? { let flow = try await Adapty.getFlow(placementId: "YOUR_PLACEMENT_ID") guard flow.hasViewConfiguration else { print("Flow doesn't have a view configuration") return nil } return try await AdaptyUI.getFlowConfiguration(forFlow: flow) } private func presentFlow(with config: AdaptyUI.FlowConfiguration) { guard let flowController = try? AdaptyUI.flowController( with: config, delegate: self ) else { return } present(flowController, animated: true) } } extension ViewController: AdaptyFlowControllerDelegate { func flowController(_ controller: AdaptyFlowController, didFailPurchase product: AdaptyPaywallProduct, error: AdaptyError) { print("Purchase failed for \(product.vendorProductId): \(error)") guard error.adaptyErrorCode != .paymentCancelled else { return } let message = switch error.adaptyErrorCode { case .paymentNotAllowed: "Purchases are not allowed on this device." default: "Purchase failed. Please try again." } let alert = UIAlertController(title: "Purchase Error", message: message, preferredStyle: .alert) alert.addAction(UIAlertAction(title: "OK", style: .default)) present(alert, animated: true) } func flowController(_ controller: AdaptyFlowController, didFinishRestoreWith profile: AdaptyProfile) { print("Restore finished successfully") controller.dismiss(animated: true) } func flowController(_ controller: AdaptyFlowController, didFailRestoreWith error: AdaptyError) { print("Restore failed: \(error)") } func flowController(_ controller: AdaptyFlowController, didReceiveError error: AdaptyUIError) { print("Flow error: \(error)") controller.dismiss(animated: true) } } ``` </TabItem> </Tabs> --- # File: ios-check-subscription-status --- --- title: "iOS SDKでサブスクリプションステータスを確認する" description: "AdaptyでiOSアプリのサブスクリプションステータスを確認する方法を学びます。" --- ユーザーが有料コンテンツにアクセスできるか、ペイウォールを表示するかを判断するには、プロファイルの[アクセスレベル](access-level)を確認する必要があります。 この記事では、プロファイルの状態にアクセスして、ユーザーにペイウォールを表示するか有料機能へのアクセスを許可するかを判断する方法を説明します。 ## サブスクリプションステータスを取得する \{#get-subscription-status\} ペイウォールまたは有料コンテンツを表示するかどうかを決める際は、プロファイルの[アクセスレベル](access-level)を確認します。方法は2つあります: - 最新のプロファイルデータが即座に必要な場合(アプリ起動時など)や強制的に更新したい場合は `getProfile` を呼び出す。 - **プロファイルの自動更新**を設定して、サブスクリプションステータスが変わるたびにローカルコピーを自動更新する。 :::important デフォルトでは、`premium` アクセスレベルがAdaptyにすでに存在します。アクセスレベルを複数設定する必要がない場合は、`premium` をそのまま使用できます。 ::: ### プロファイルを取得する \{#get-profile\} サブスクリプションステータスを取得する最も簡単な方法は、`getProfile` メソッドを使ってプロファイルにアクセスすることです: <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift showLineNumbers do { let profile = try await Adapty.getProfile() if profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false { // grant access to premium features } } catch { // handle the error } ``` </TabItem> <TabItem value="swift-callback" label="Swift-Callback" default> ```swift showLineNumbers Adapty.getProfile { result in if let profile = try? result.get() { // check the access profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false { // grant access to premium features } } } ``` </TabItem> </Tabs> ### サブスクリプション更新を受け取る \{#listen-to-subscription-updates\} アプリでプロファイルの更新を自動的に受け取りたい場合: 1. 任意の型で `AdaptyDelegate` プロトコルに準拠し、`didLoadLatestProfile` メソッドを実装します。ユーザーのサブスクリプションステータスが変わるたびに、Adaptyがこのメソッドを自動的に呼び出します。以下の例では、サブスクリプションのワークフローやユーザープロファイルの処理を支援する `SubscriptionManager` 型を使用しています。この型は依存性注入で渡したり、UIKitアプリのシングルトンとして設定したり、アプリのメイン構造体からSwiftUI環境に追加したりできます。 2. このメソッドが呼び出されたときに更新されたプロファイルデータを保存して、追加のネットワークリクエストなしにアプリ全体で使用できるようにします。 ```swift class SubscriptionManager: AdaptyDelegate { nonisolated func didLoadLatestProfile(_ profile: AdaptyProfile) { let hasAccess = profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false // Update UI, unlock content, etc. } } // Set delegate after Adapty activation Adapty.delegate = subscriptionManager ``` :::note Adaptyはアプリ起動時に `didLoadLatestProfile` を自動的に呼び出し、デバイスがオフラインの場合でもキャッシュされたサブスクリプションデータを提供します。 ::: ## プロファイルとペイウォールのロジックを連携させる \{#connect-profile-with-paywall-logic\} ペイウォールを表示するか有料機能へのアクセスを許可するかを即座に判断したい場合、ユーザーのプロファイルを直接確認できます。このアプローチは、アプリ起動時、プレミアムセクションへの入場時、特定コンテンツを表示する前などのシナリオで役立ちます。 <Tabs> <TabItem value="swiftui" label="SwiftUI" default> ```swift private func checkAccessLevel() async -> Bool { do { let profile = try await Adapty.getProfile() return profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false } catch { print("Error checking access level: \(error)") return false } } // In your initialization logic: let hasAccess = await checkAccessLevel() if !hasAccess { paywallPresented = true // Show paywall if no access } ``` </TabItem> <TabItem value="uikit" label="UIKit"> ```swift private func checkAccessLevel() async throws -> Bool { let profile = try await Adapty.getProfile() return profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false } // In your initialization logic: let hasAccess = try await checkAccessLevel() if !hasAccess { presentPaywall(with: paywallConfiguration) } ``` </TabItem> </Tabs> ## 次のステップ \{#next-steps\} サブスクリプションステータスの追跡方法がわかったところで、[ユーザープロファイルの操作方法](ios-quickstart-identify)を確認して、既存の認証システムや有料アクセスの共有設定と適切に連携していることを確かめましょう。 独自の認証システムがない場合でも、Adaptyがユーザーを管理しますので問題はありません。ただし、Adaptyが匿名ユーザーをどのように扱うかについては[ガイド](ios-quickstart-identify)を参照することをおすすめします。 --- # File: ios-quickstart-identify --- --- title: "iOS SDKでのユーザー識別" description: "アプリ内サブスクリプション管理のためのAdaptyセットアップ クイックスタートガイド。" --- :::important このガイドは、独自の認証システムをお持ちの方を対象としています。ここでは、既存の認証システムに合わせてAdaptyのユーザープロファイルを管理する方法を説明します。 ::: ユーザーの購入履歴をどのように管理するかは、アプリの認証モデルによって異なります。 - バックエンド認証を使用せず、ユーザーデータを保存しないアプリの場合は、[匿名ユーザーに関するセクション](#anonymous-users)を参照してください。 - バックエンド認証を使用している(または使用予定の)アプリの場合は、[識別済みユーザーに関するセクション](#identified-users)を参照してください。 **主要な概念**: - **プロファイル**はSDKが動作するために必要なエンティティです。Adaptyが自動的に作成します。 - プロファイルは匿名 **(カスタマーユーザーIDなし)** または識別済み **(カスタマーユーザーIDあり)** のどちらかになります。 - **カスタマーユーザーID**を提供することで、Adaptyのプロファイルと社内の認証システムを紐付けられます。 匿名ユーザーと識別済みユーザーの違いは次のとおりです。 | | 匿名ユーザー | 識別済みユーザー | |-------------------------|---------------------------------------------------|-------------------------------------------------------------------------| | **購入管理** | ストアレベルの購入復元 | カスタマーユーザーIDを通じたデバイス間での購入履歴の維持 | | **プロファイル管理** | 再インストールのたびに新しいプロファイルが作成される | セッションとデバイスをまたいで同一プロファイルを使用 | | **データの永続性** | 匿名ユーザーのデータはアプリインストールに紐付く | 識別済みユーザーのデータはアプリインストールをまたいで保持される | ## 匿名ユーザー \{#anonymous-users\} バックエンド認証を使用していない場合、**アプリコード内で認証処理を実装する必要はありません**。 1. アプリの初回起動時にSDKが有効化されると、Adaptyは**ユーザーの新しいプロファイルを作成します**。 2. ユーザーがアプリ内で何かを購入すると、その購入は**ユーザーのAdaptyプロファイルとストアアカウントに紐付けられます**。 3. ユーザーがアプリを**再インストール**したり、**新しいデバイス**にインストールしたりすると、Adaptyは有効化時に**新しい匿名プロファイルを作成します**。 4. ユーザーがアプリ内で以前に購入を行っていた場合、デフォルトではSDKの有効化時にApp Storeから購入履歴が自動的に同期されます。 :::note バックアップからの復元は再インストールとは動作が異なります。デフォルトでは、ユーザーがバックアップから復元した場合、SDKはキャッシュデータを保持し、新しいプロファイルを作成しません。この動作は`clearDataOnBackup`設定で変更できます。[詳細はこちら](sdk-installation-ios#clear-data-on-backup-restore)。 ::: 匿名ユーザーの場合、インストールのたびに新しいプロファイルが作成されますが、Adaptyのアナリティクスで[新規インストールとして扱う基準を設定できる](general#4-installs-definition-for-analytics)ため、問題ありません。 匿名ユーザーの場合、インストール数は**デバイスID**でカウントする必要があります。この場合、再インストールを含め、デバイスでのアプリインストールが1件としてカウントされます。 ## 識別済みユーザー \{#identified-users\} アプリ内でユーザーを識別する方法は2つあります。 - [**ログイン/サインアップ時:**](#during-loginsignup) アプリ起動後にユーザーがサインインする場合、認証時にカスタマーユーザーIDを指定して`identify()`を呼び出します。 - [**SDK有効化時:**](#during-the-sdk-activation) アプリ起動時にカスタマーユーザーIDが既にわかっている場合は、`activate()`を呼び出す際に送信します。 :::important デフォルトでは、Adaptyが別のカスタマーユーザーIDに現在紐付いているカスタマーユーザーIDから購入を受け取った場合、アクセスレベルは共有されます。つまり、両方のプロファイルが有料アクセスを持つことになります。この設定を変更して、一方のプロファイルから他方へ有料アクセスを移行したり、共有を完全に無効にしたりすることもできます。詳細は[こちらの記事](general#6-sharing-paid-access-between-user-accounts)を参照してください。 ::: <img src="/assets/shared/img/identify-diagram.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### ログイン/サインアップ時 \{#during-loginsignup\} アプリ起動後にユーザーを識別する場合(たとえば、アプリへのログイン後やサインアップ後)、`identify`メソッドを使用してカスタマーユーザーIDを設定します。 - **このカスタマーユーザーIDを以前使用したことがない**場合、Adaptyは自動的に現在のプロファイルに紐付けます。 - **このカスタマーユーザーIDでユーザーを以前識別したことがある**場合、AdaptyはそのカスタマーユーザーIDに紐付いたプロファイルに切り替えます。 :::important カスタマーユーザーIDはユーザーごとに一意である必要があります。パラメーター値をハードコードすると、すべてのユーザーが同一として扱われます。 ::: 他のSDKメソッドを呼び出す前に、必ず`identify`を`await`してください。並列呼び出しを行うと`#3006 profileWasChanged`が発生するか、匿名プロファイルが対象になります。詳細は[iOS SDKの呼び出し順序](ios-sdk-call-order)を参照してください。 <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift showLineNumbers do { try await Adapty.identify("YOUR_USER_ID") // Unique for each user } catch { // handle the error } ``` </TabItem> <TabItem value="swift-callback" label="Swift-Callback" default> ```swift showLineNumbers // User IDs must be unique for each user Adapty.identify("YOUR_USER_ID") { error in if let error { // handle the error } } ``` </TabItem> </Tabs> ### SDK有効化時 \{#during-the-sdk-activation\} SDKを有効化する時点でカスタマーユーザーIDが既にわかっている場合は、`identify`を別途呼び出す代わりに、`activate`メソッドで送信できます。 カスタマーユーザーIDがわかっているにもかかわらず、有効化後にのみ設定した場合、有効化時にAdaptyが新しい匿名プロファイルを作成し、`identify`を呼び出した後に既存のプロファイルへ切り替えることになります。 既存のカスタマーユーザーID(以前使用したもの)でも新しいものでも渡すことができます。新しいものを渡した場合、有効化時に作成された新しいプロファイルが自動的にそのカスタマーユーザーIDに紐付けられます。 :::note デフォルトでは、匿名プロファイルの作成はアナリティクスのダッシュボードに影響しません。これはインストール数がデバイスIDに基づいてカウントされるためです。 デバイスIDはデバイス上のストアからのアプリの単一インストールを表し、アプリの再インストール後にのみ再生成されます。 初回インストールか再インストールかに関わらず、また既存のカスタマーユーザーIDを使用するかどうかにも依存しません。 プロファイルの作成(SDKの有効化またはログアウト時)、ログイン、または再インストールなしのアプリアップグレードでは、追加のインストールイベントは発生しません。 デバイスではなくユニークユーザーに基づいてインストールをカウントしたい場合は、**App settings**で[**Installs definition for analytics**](general#4-installs-definition-for-analytics)を設定してください。 ::: <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift showLineNumbers // Place in the app main struct for SwiftUI or in AppDelegate for UIKit let configurationBuilder = AdaptyConfiguration .builder(withAPIKey: "PUBLIC_SDK_KEY") .with(customerUserId: "YOUR_USER_ID") // Customer user IDs must be unique for each user. If you hardcode the parameter value, all users will be considered as one. do { try await Adapty.activate(with: configurationBuilder.build()) } catch { // handle the error } ``` </TabItem> <TabItem value="swift-callback" label="Swift-Callback" default> ```swift showLineNumbers // Place in the app main struct for SwiftUI or in AppDelegate for UIKit let configurationBuilder = AdaptyConfiguration .builder(withAPIKey: "PUBLIC_SDK_KEY") .with(customerUserId: "YOUR_USER_ID") // Customer user IDs must be unique for each user. If you hardcode the parameter value, all users will be considered as one. Adapty.activate(with: configurationBuilder.build()) { error in // handle the error } ``` </TabItem> </Tabs> ### ユーザーのログアウト \{#log-users-out\} ユーザーをログアウトさせるボタンがある場合は、`logout`メソッドを使用します。 :::important ユーザーをログアウトすると、そのユーザーの新しい匿名プロファイルが作成されます。 ::: <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift showLineNumbers do { try await Adapty.logout() } catch { // handle the error } ``` </TabItem> <TabItem value="swift-callback" label="Swift-Callback" default> ```swift showLineNumbers Adapty.logout { error in if error == nil { // successful logout } } ``` </TabItem> </Tabs> :::info ユーザーをアプリに再ログインさせるには、`identify`メソッドを使用します。 ::: ### ログインなしでの購入を許可する \{#allow-purchases-without-login\} ユーザーがアプリにログインする前後どちらでも購入できる場合、ログイン後もアクセスが維持されるようにする必要があります。 1. ログアウト状態のユーザーが購入を行うと、Adaptyはその購入を匿名プロファイルIDに紐付けます。 2. ユーザーがアカウントにログインすると、Adaptyは識別済みプロファイルへの切り替えを行います。 - 新しいカスタマーユーザーIDの場合(たとえば、登録前に購入が行われた場合)、AdaptyはカスタマーユーザーIDを現在のプロファイルに割り当て、購入履歴がすべて維持されます。 - 既存のカスタマーユーザーIDの場合(カスタマーユーザーIDがすでにプロファイルに紐付いている場合)、プロファイル切り替え後に実際のアクセスレベルを取得する必要があります。識別後すぐに[`getProfile`](ios-check-subscription-status)を呼び出すか、データが自動的に同期されるよう[プロファイルの更新をリッスンする](ios-check-subscription-status)ことができます。 ## 次のステップ \{#next-steps\} おめでとうございます!アプリにアプリ内決済のロジックを実装できました!アプリのマネタイズがうまくいくことを願っています。 Adaptyをさらに活用するために、以下のトピックもご覧ください。 - [**テスト**](test-purchases-in-sandbox): すべてが期待どおりに動作するか確認する - [**オンボーディング**](ios-onboardings): オンボーディングでユーザーを引き込みリテンションを高める - [**インテグレーション**](configuration): マーケティングアトリビューションおよびアナリティクスサービスとわずか1行のコードで連携する - [**カスタムプロファイル属性の設定**](setting-user-attributes): ユーザープロファイルにカスタム属性を追加してセグメントを作成し、A/B テストを実施したり異なるユーザーに異なるペイウォールを表示したりする --- # File: adapty-sdk-integration-skill --- --- title: "SDKインテグレーションスキルを使ってAdaptyをiOSアプリに統合する" description: "adapty-sdk-integrationスキルを使用して、AIコーディングツールでAdapty SDKをiOSアプリにエンドツーエンドで統合します。" --- :::important このスキルはベータ版です。途中で止まったり、予期しない動作をした場合は、代わりに[ステップバイステップの統合ガイド](adapty-cursor)を参照してください。AIツールが各ステップを適切なドキュメントとともに進められるように案内します。 ::: --- no_index: true --- [adapty-sdk-integration スキル](https://github.com/adaptyteam/adapty-sdk-integration-skill)は、Adapty のインテグレーションをエンドツーエンドで自動化します。ダッシュボードのセットアップ、SDK のインストール、ペイウォール、各ステージの検証まで対応しています。プラットフォームを自動検出し、各ステージで関連する Adapty ドキュメントを取得します。 **対応ツール**: Claude Code、GitHub Copilot CLI、OpenAI Codex、Gemini CLI。 インストールするには、お使いのツール向けのフォームを選択してください。完全なリストは[スキルの README](https://github.com/adaptyteam/adapty-sdk-integration-skill) をご覧ください。 **Claude Code** ``` claude plugin marketplace add adaptyteam/adapty-sdk-integration-skill claude plugin install adapty-sdk-integration@adapty ``` **GitHub Copilot CLI** ``` gh skill install adaptyteam/adapty-sdk-integration-skill ``` **Gemini CLI** ``` gemini skills install https://github.com/adaptyteam/adapty-sdk-integration-skill ``` **OpenAI Codex またはその他のツール**: リポジトリをクローンし、`plugins/adapty-sdk-integration/skills/adapty-sdk-integration/` をツールのスキルディレクトリにコピーしてください。 インストール後、プロジェクト内でスキルを実行します: ``` /adapty-sdk-integration ``` スキルがいくつかのセットアップ質問を行い、その後ダッシュボードのセットアップ、SDK のインストール、ペイウォール、検証の手順を案内します。 --- # File: adapty-cursor --- --- title: "AIアシスタントを使ってAdaptyをiOSアプリに組み込む" description: "Cursor、Context7、ChatGPT、Claude、その他のAIツールを使ってAdaptyをiOSアプリに組み込むためのステップバイステップガイドです。" --- このガイドでは、AIコーディングツールを使ってAdaptyをiOSアプリに段階的に組み込む方法を説明します。正しいAdaptyドキュメントを正しい順序でAIに渡すことがポイントです。 For a fully automated integration, use the [adapty-sdk-integration skill](https://github.com/adaptyteam/adapty-sdk-integration-skill): it runs the whole integration from your AI coding tool in one command. ## 始める前に:ダッシュボードのセットアップ \{#before-you-start-dashboard-setup\} AdaptyはSDKコードを書く前に、ダッシュボードでいくつかの設定が必要です。インタラクティブなLLMスキルを使うか、ダッシュボードから手動で設定することができます。 ### スキルを使う方法(推奨) \{#skill-approach-recommended\} Adapty CLIスキルを使うと、LLMがアプリ、プロダクト、アクセスレベル、ペイウォール、プレースメントを直接設定できます。ダッシュボードを各ステップで開く必要はありません。[ストアの接続](integrate-payments)だけはダッシュボードで行う必要があります。 ``` npx skills add adaptyteam/adapty-cli --skill adapty-cli ``` スキルを追加したら、エージェントで `/adapty-cli` を実行してください。ストアの接続のためにダッシュボードを開くタイミングも含め、各ステップをガイドしてくれます。 ### ダッシュボードを使う方法 \{#dashboard-approach\} すべてを手動で設定したい場合は、コードを書く前に以下の準備が必要です。LLMはダッシュボードの値を自動で調べることはできないので、自分で確認して提供する必要があります。 1. **アプリストアに接続する**: Adapty ダッシュボードで **App settings → General** を開きます。購入機能を動かすために必須の設定です。 [App Store に接続する](integrate-payments) 2. **公開SDKキーをコピーする**: Adapty ダッシュボードで **App settings → General** を開き、**API keys** セクションを確認します。コード上では、`Adapty.activate("YOUR_PUBLIC_SDK_KEY")` に渡す文字列です。 3. **プロダクトを少なくとも1つ作成する**: Adapty ダッシュボードの **Products** ページで作成します。コードからプロダクトを直接参照することはありません — Adaptlyはフローやペイウォールを通じてプロダクトを配信します。 [プロダクトを追加する](quickstart-products) 4. **フローまたはペイウォールとプレースメントを作成する**: Adapty ダッシュボードでフロー(またはUIを自分で作る場合はペイウォール)を作成し、**Placements** ページでプレースメントに割り当てます。コード上では、`Adapty.getFlow("YOUR_PLACEMENT_ID")` に渡すプレースメントIDが該当します。 [フローを作成する](quickstart-paywalls) 5. **アクセスレベルを設定する**: Adapty ダッシュボードの **Products** ページで各プロダクトに設定します。コード上では、`profile.accessLevels["premium"]` で確認する文字列です。ほとんどのアプリではデフォルトの `premium` アクセスレベルで十分です。プロダクトによって(たとえば `basic` プランと `pro` プラン)ユーザーがアクセスできる機能が異なる場合は、コーディングを始める前に[追加のアクセスレベルを作成](assigning-access-level-to-a-product)してください。 :::tip 5つすべてが揃ったら、コードを書く準備完了です。LLMに「公開SDKキーはX、プレースメントIDはY」と伝えておくと、正確な初期化コードとペイウォール取得コードを生成してもらえます。 ::: ### 後から設定するもの \{#set-up-when-ready\} コーディングを始めるためには必須ではありませんが、組み込みが進んだ段階で必要になります。 - **A/B テスト**: **Placements** ページで設定します。コードの変更は不要です。 [A/B テスト](ab-tests) - **フローやプレースメントの追加**: 別のプレースメントIDで `getFlow` を追加で呼び出します。 - **アナリティクス連携**: **Integrations** ページで設定します。連携ごとに設定方法が異なります。[アナリティクス連携](analytics-integration)と[アトリビューション連携](attribution-integration)を参照してください。 ## AdaptyドキュメントをLLMに渡す \{#feed-adapty-docs-to-your-llm\} ### Context7を使う(推奨) \{#use-context7-recommended\} [Context7](https://context7.com)は、LLMが最新のAdaptyドキュメントに直接アクセスできるようにするMCPサーバーです。質問内容に応じて適切なドキュメントを自動で取得するため、URLを手動で貼り付ける手間がありません。 Context7は**Cursor**、**Claude Code**、**Windsurf**、その他のMCP対応ツールで動作します。セットアップするには以下を実行してください。 ``` npx ctx7 setup ``` このコマンドがエディタを自動検出してContext7サーバーを設定します。手動でセットアップする場合は、[Context7 GitHubリポジトリ](https://github.com/upstash/context7)を参照してください。 設定後は、プロンプト内でAdaptyライブラリを参照してください。 ``` Use the adaptyteam/adapty-docs library to look up how to install the iOS SDK ``` :::warning Context7を使えばドキュメントのURLを手動で貼り付ける必要はなくなりますが、実装の順序は重要です。すべてが正しく動くよう、以下の[実装ウォークスルー](#implementation-walkthrough)をステップごとに進めてください。 ::: ### プレーンテキストのドキュメントを使う \{#use-plain-text-docs\} AdaptyのドキュメントはプレーンテキストのMarkdownとして取得できます。URLの末尾に `.md` を付けるか、記事タイトルの下にある **Copy for LLM** をクリックしてください。例: [adapty-cursor.md](https://adapty.io/docs/ja/adapty-cursor.md) 以下の[実装ウォークスルー](#implementation-walkthrough)の各ステージには、「LLMに送る内容」ブロックがあり、貼り付け用の `.md` リンクが含まれています。 まとめて多くのドキュメントが必要な場合は、以下の[インデックスファイルとプラットフォーム別のサブセット](#plain-text-doc-index-files)を参照してください。 ## 実装ウォークスルー \{#implementation-walkthrough\} このガイドの残りの部分では、実装の順序に沿ってAdaptyの組み込みを進めていきます。各ステージには、LLMに送るドキュメント、完了時に確認できる内容、よくある問題が記載されています。 ### 組み込みを計画する \{#plan-your-integration\} コードに入る前に、LLMにプロジェクトを分析させて実装計画を立ててもらいましょう。AIツールにプランニングモード(CursorやClaude Codeのプランモードなど)があれば、コードを書く前にプロジェクト構造とAdaptyドキュメントの両方を確認させるために活用してください。 購入処理にどのアプローチを使うかをLLMに伝えてください — これによって参照すべきガイドが変わります。 - [**Adapty Flow Builder**](adapty-flow-builder): Adaptのノーコードビルダーでフローを作成し、SDKが自動でレンダリングします。 - [**手動作成のペイウォール**](ios-quickstart-manual): 独自のペイウォールUIをコードで構築しますが、プロダクトの取得と購入処理にはAdaptyを使います。 - [**オブザーバーモード**](observer-vs-full-mode): 既存の購入インフラをそのまま維持し、アナリティクスと連携のみAdaptyを使います。 どれを選べばよいかわからない場合は、[クイックスタートの比較表](ios-quickstart-paywalls)をご覧ください。 ### SDKをインストールして設定する \{#install-and-configure-the-sdk\} XcodeのSwift Package ManagerでAdapty SDKパッケージをインストールし、公開SDKキーで有効化します。これが基盤となるステップで、これなしには他の機能は動きません。 **ガイド:** [Adapty SDKのインストールと設定](sdk-installation-ios) LLMに送る内容: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/sdk-installation-ios.md ``` :::tip[チェックポイント] - **期待される結果:** アプリがビルドして起動する。XcodeコンソールにAdaptyの有効化ログが表示される。 - **注意点:** "Public API key is missing" → App settingsで取得した実際のキーがプレースホルダーと置き換えられているか確認する。 ::: ### フローまたはペイウォールを表示して購入を処理する \{#show-flows-or-paywalls-and-handle-purchases\} プレースメントIDでフローまたはペイウォールを取得して表示し、購入イベントを処理します。必要なガイドは購入の処理方法によって異なります。 進めながらサンドボックスで都度購入をテストしてください — 最後まで待たずに行いましょう。セットアップ手順は[サンドボックスでの購入テスト](test-purchases-in-sandbox)を参照してください。 <Tabs groupId="paywall-approach"> <TabItem value="builder" label="Flow Builder" default> **ガイド:** - [Flow Builderで購入を有効にする(クイックスタート)](ios-quickstart-paywalls) - [フローとその設定を取得する](get-pb-paywalls) - [フローを表示する](ios-present-paywalls) - [フローのイベントを処理する](ios-handling-events) - [ボタンアクションに対応する](handle-paywall-actions) LLMに送る内容: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/ios-quickstart-paywalls.md - https://adapty.io/docs/ja/get-pb-paywalls.md - https://adapty.io/docs/ja/ios-present-paywalls.md - https://adapty.io/docs/ja/ios-handling-events.md - https://adapty.io/docs/ja/handle-paywall-actions.md ``` :::tip[チェックポイント] - **期待される結果:** 設定したプロダクトがフローに表示される。プロダクトをタップするとサンドボックスの購入ダイアログが表示される。 - **注意点:** フローが空または `getFlow` エラー → プレースメントIDがダッシュボードと完全に一致しているか、プレースメントにオーディエンスが割り当てられているか確認する。 ::: </TabItem> <TabItem value="manual" label="Manual paywalls"> **ガイド:** - [カスタムペイウォールで購入を有効にする(クイックスタート)](ios-quickstart-manual) - [ペイウォールとプロダクトを取得する](fetch-paywalls-and-products) - [リモートコンフィグで設計されたペイウォールを表示する](present-remote-config-paywalls) - [購入を行う](making-purchases) - [購入を復元する](restore-purchase) LLMに送る内容: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/ios-quickstart-manual.md - https://adapty.io/docs/ja/fetch-paywalls-and-products.md - https://adapty.io/docs/ja/present-remote-config-paywalls.md - https://adapty.io/docs/ja/making-purchases.md - https://adapty.io/docs/ja/restore-purchase.md ``` :::tip[チェックポイント] - **期待される結果:** カスタムペイウォールにAdaptyから取得したプロダクトが表示される。プロダクトをタップするとサンドボックスの購入ダイアログが表示される。 - **注意点:** プロダクト配列が空 → ダッシュボードでペイウォールにプロダクトが割り当てられているか、プレースメントにオーディエンスがあるか確認する。 ::: </TabItem> <TabItem value="observer" label="Observer mode"> **ガイド:** - [オブザーバーモードの概要](observer-vs-full-mode) - [オブザーバーモードを実装する](implement-observer-mode) - [オブザーバーモードでトランザクションを報告する](report-transactions-observer-mode) LLMに送る内容: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/observer-vs-full-mode.md - https://adapty.io/docs/ja/implement-observer-mode.md - https://adapty.io/docs/ja/report-transactions-observer-mode.md ``` :::tip[チェックポイント] - **期待される結果:** 既存の購入フローでサンドボックス購入を行った後、Adaptのダッシュボード **Event Feed** にトランザクションが表示される。 - **注意点:** イベントが表示されない → Adaptにトランザクションを報告しているか、App Store Server Notificationsが設定されているか確認する。 ::: </TabItem> </Tabs> ### サブスクリプションのステータスを確認する \{#check-subscription-status\} 購入後、ユーザープロファイルでアクティブなアクセスレベルを確認して、プレミアムコンテンツへのアクセスを制限します。 **ガイド:** [サブスクリプションのステータスを確認する](ios-check-subscription-status) LLMに送る内容: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/ios-check-subscription-status.md ``` :::tip[チェックポイント] - **期待される結果:** サンドボックス購入後、`profile.accessLevels["premium"]?.isActive` が `true` を返す。 - **注意点:** 購入後も `accessLevels` が空 → ダッシュボードでプロダクトにアクセスレベルが割り当てられているか確認する。 ::: ### ユーザーを識別する \{#identify-users\} アプリのユーザーアカウントをAdaptyのプロファイルに紐付けて、デバイスをまたいで購入が引き継がれるようにします。 :::important アプリに認証機能がない場合はこのステップをスキップしてください。 ::: **ガイド:** [ユーザーを識別する](ios-quickstart-identify) LLMに送る内容: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/ios-quickstart-identify.md ``` :::tip[チェックポイント] - **期待される結果:** `Adapty.identify("your-user-id")` を呼び出した後、ダッシュボードの **Profiles** セクションにカスタムユーザーIDが表示される。 - **注意点:** 匿名プロファイルへのアトリビューションを避けるため、`identify` はアクティベーション後、ペイウォール取得前に呼び出す。 ::: ### リリースの準備をする \{#prepare-for-release\} サンドボックスで組み込みが動作したら、すべてが本番環境に対応しているかリリースチェックリストを確認しましょう。 **ガイド:** [リリースチェックリスト](release-checklist) LLMに送る内容: ``` Read these Adapty docs before releasing: - https://adapty.io/docs/ja/release-checklist.md ``` :::tip[チェックポイント] - **期待される結果:** すべてのチェックリスト項目が確認済み:ストア接続、サーバー通知、購入フロー、アクセスレベルチェック、プライバシー要件。 - **注意点:** App Store Server Notificationsが未設定 → **App settings → iOS SDK** で設定しないと、イベントがダッシュボードに表示されません。 ::: ## プレーンテキストのドキュメントインデックスファイル \{#plain-text-doc-index-files\} 個別ページを超えてLLMに広いコンテキストを提供したい場合、Adaptyドキュメント全体をリスト化または統合したインデックスファイルを提供しています。 - [`llms.txt`](https://adapty.io/docs/ja/llms.txt): すべてのページを `.md` リンク付きでリスト化しています。LLMがウェブサイトにアクセスしやすくするための[新興標準](https://llmstxt.org/)です。一部のAIエージェント(ChatGPTなど)では、`llms.txt` をダウンロードしてチャットにファイルとしてアップロードする必要があります。 - [`llms-full.txt`](https://adapty.io/docs/ja/llms-full.txt): Adaptyドキュメントサイト全体を1つのファイルにまとめたものです。非常に大きいため、全体像が必要な場合のみ使用してください。 - iOS専用の [`ios-llms.txt`](https://adapty.io/docs/ja/ios-llms.txt) と [`ios-llms-full.txt`](https://adapty.io/docs/ja/ios-llms-full.txt): サイト全体と比べてトークンを節約できる、プラットフォーム別のサブセットです。 --- # File: get-pb-paywalls --- --- title: "フローとペイウォールを取得する - iOS" description: "iOSアプリでAdaptyからフローとペイウォールを取得する方法。" --- <SDKv4> <MethodPromo method="getFlow" /> [フローまたはペイウォールビルダーのペイウォールを設計](adapty-paywall-builder)したら、それをモバイルアプリに表示できます。最初のステップは、以下の説明に従って、プレースメントに関連付けられたフローまたはペイウォールとそのビュー設定を取得することです。 :::tip Adapty SDK をモバイルアプリに統合した実例を見たいですか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを示す[サンプルアプリ](sample-apps)をご確認ください。 ::: <details> <summary>始める前に</summary> 1. Adapty ダッシュボードで[プロダクトを作成](create-product)します。 2. Adapty ダッシュボードで[フロー/ペイウォールを作成し、プロダクトを組み込み](create-paywall)ます。 3. Adapty ダッシュボードで[プレースメントを作成し、フロー/ペイウォールを組み込み](create-placement)ます。 4. モバイルアプリに [Adapty SDK](sdk-installation-ios) をインストールします。 </details> ## フローまたはペイウォールの取得 \{#fetch-flowpaywall\} フロービルダーまたはペイウォールビルダーを使ってフローやペイウォールをデザインした場合、それをモバイルアプリのコードでレンダリングしてユーザーに表示することを心配する必要はありません。このようなフローやペイウォールには、表示する内容と表示方法の両方が含まれています。ただし、プレースメントを通じてIDを取得し、ビュー設定を準備した上で、モバイルアプリに表示する必要があります。 フローまたはペイウォールとその[ビュー設定](get-pb-paywalls#fetch-the-view-configuration)は、できるだけ早い段階で取得してください。表示する直前ではなく、理想的にはずっと前に取得しましょう。ビュー設定を取得した時点で、SDKはバックグラウンドで画像のダウンロードとキャッシュを開始します。早く取得するほど、ダウンロードが完了するまでの時間が長く確保できます。フローまたはペイウォールを表示する頃には、設定と画像がすでにキャッシュ済みで表示できる状態になっています。 フローまたはペイウォールを取得するには、`getFlow` メソッドを使用します: <Tabs> <TabItem value="swift" label="Swift"> ```swift showLineNumbers do { let flow = try await Adapty.getFlow(placementId: "YOUR_PLACEMENT_ID") // the requested flow/paywall } catch { // handle the error } ``` </TabItem> <TabItem value="callback" label="Swift-Callback"> ```swift showLineNumbers Adapty.getFlow(placementId: "YOUR_PLACEMENT_ID") { result in switch result { case let .success(flow): // the requested flow/paywall case let .failure(error): // handle the error } } ``` </TabItem> </Tabs> パラメーター: | パラメータ | 必須/任意 | 説明 | |---------|--------|-----------| | **placementId** | 必須 | 取得したい[プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **fetchPolicy** | デフォルト: `.reloadRevalidatingCacheData` | <p>デフォルトでは、SDK はサーバーからデータを読み込もうとし、失敗した場合はキャッシュデータを返します。この方法を推奨するのは、ユーザーが常に最新のデータを受け取れるためです。</p><p></p><p>ただし、ユーザーが不安定なインターネット環境を利用していると想定される場合は、`.returnCacheDataElseLoad` を使用することを検討してください。これにより、キャッシュが存在する場合はキャッシュデータを返します。この場合、最新のデータが取得できないことがありますが、通信環境に左右されずに読み込み時間を短縮できます。キャッシュは定期的に更新されるため、セッション中にネットワークリクエストを避けたい場面での使用も安全です。</p><p></p><p>キャッシュはアプリを再起動しても保持され、アプリの再インストールや手動でのクリアを行った場合にのみ削除されます。</p><p></p><p>Adapty SDK はペイウォールをローカルに2つの層で保存しています。1つは上記の定期更新キャッシュ、もう1つは[フォールバックペイウォール](fallback-paywalls)です。また、CDN を使用してペイウォールをより高速に取得し、CDN に接続できない場合のスタンドアロンフォールバックサーバーも用意しています。このシステムは、常にペイウォールの最新バージョンを取得しつつ、インターネット接続が不安定な場合でも信頼性を確保するよう設計されています。</p> | | **loadTimeout** | デフォルト: 5秒 | <p>このメソッドのタイムアウト上限を設定します。タイムアウトに達した場合、キャッシュデータまたはローカルフォールバックが返されます。</p><p>まれに、内部で複数のリクエストが発生する場合があるため、`loadTimeout` に指定した時間よりわずかに遅くタイムアウトすることがあります。</p> | レスポンスパラメーター: | パラメーター | 説明 | | :-------- | :---------- | | Flow | プレースメント、識別子(`id`、`variationId`)、名前、リモートコンフィグ、およびフローにビュー設定が含まれるかどうかを示す `hasViewConfiguration` フラグを含む `AdaptyFlow` オブジェクトです。プリロード、カスタム UI、またはプログラムによるチェック用に実際のプロダクトを取得するには、`getPaywallProducts(flow:)` を呼び出してください。 | ## ビュー設定の取得 \{#fetch-the-view-configuration\} フローまたはペイウォールを取得したら、`flow.hasViewConfiguration` を使ってビュー設定が含まれているかどうかを確認します。このフラグは、Adapty ダッシュボードでプレースメントがどのように設計されたかを示します。 - **`true`** — プレースメントが **Flow Builder**(フロー)または **Paywall Builder**(ペイウォール)で設計されています。Adapty が UI をレンダリングします。以降の手順に従い、ビュー設定を取得して[フローまたはペイウォールを表示](ios-present-paywalls)してください。 - **`false`** — プレースメントはビルダー UI を持たないカスタムペイウォールです。 `getFlowConfiguration` メソッドを使用してビュー設定を読み込みます。 ```swift showLineNumbers guard flow.hasViewConfiguration else { // handle as remote config paywall return } let flowConfiguration = try await AdaptyUI.getFlowConfiguration(forFlow: flow) ``` パラメーター: | パラメーター | 必須/任意 | 説明 | | :----------------------- | :------------- | :---------- | | **forFlow** | 必須 | `Adapty.getFlow` で取得した `AdaptyFlow` オブジェクト。 | | **locale** | <p>任意</p><p>デフォルト: `nil`</p> | [ペイウォールのローカライズ](add-paywall-locale-in-adapty-paywall-builder)の識別子。`-` で区切られた1つまたは2つのサブタグを持つ言語コードで指定します(例: `en`、`pt-br`)。詳細は[ローカライズとロケールコード](localizations-and-locale-codes)を参照してください。 | | **loadTimeout** | デフォルト: 5秒 | このメソッドのタイムアウトを制限する値です。タイムアウトに達した場合、キャッシュされたデータまたはローカルのフォールバックが返されます。内部で複数のリクエストが発生する場合があるため、`loadTimeout` で指定した時間よりわずかに遅れてタイムアウトすることがあります。 | | **products** | 任意 | 画面上のプロダクト表示タイミングを最適化するために、`AdaptyPaywallProduct` オブジェクトの配列を指定します。`nil` を渡すと、AdaptyUI が必要なプロダクトを自動的に取得します。 | | **systemRequestsHandler** | 任意 | フローのアクションによってトリガーされるシステムの権限リクエストやレビューリクエストを処理する、`AdaptySystemRequestsHandler` に準拠したオブジェクト。フローにそのようなアクションが含まれる場合にのみ必要です。 | | **assetsResolver** | 任意 | フロー/ペイウォール内の画像や動画を上書きする `[String: AdaptyCustomAsset]` 辞書。詳細は[アセットのカスタマイズ](#customize-assets)を参照してください。 | | **timerResolver** | 任意 | 開発者が定義したタイマーの終了日時を提供する、`AdaptyTimerResolver` に準拠したオブジェクト。詳細は[開発者定義タイマーの設定](#set-up-developer-defined-timers)を参照してください。 | 読み込みが完了したら、[フロー/ペイウォールを表示](ios-present-paywalls)します。 ## デフォルトオーディエンスのフローまたはペイウォールを取得して高速化する \{#get-a-flow-or-paywall-for-a-default-audience-to-fetch-it-faster\} 通常、フローやペイウォールはほぼ瞬時に取得されるため、このプロセスの高速化を特に気にする必要はありません。ただし、オーディエンスやプレースメントが多数あり、ユーザーのインターネット接続が不安定な場合は、フローやペイウォールの取得に想定以上の時間がかかることがあります。そのような状況では、何も表示しないよりもスムーズなユーザー体験を提供するために、デフォルトのフローまたはペイウォールを表示したいと思うかもしれません。 これに対処するために、`getFlowForDefaultAudience` メソッドを使用できます。このメソッドは、指定されたプレースメントの **All Users** オーディエンス向けのフローまたはペイウォールを取得します。ただし、推奨されるアプローチは `getFlow` メソッドでフローまたはペイウォールを取得することであり、詳細は上記の[ペイウォール情報の取得](get-pb-paywalls#fetch-paywall-designed-with-paywall-builder)セクションをご覧ください。 :::warning `getFlow` を推奨する理由 `getFlowForDefaultAudience` メソッドにはいくつかの重大な欠点があります: - **後方互換性の問題**: 異なるアプリバージョン(現在と将来)で別々のペイウォールを表示する必要がある場合、課題が生じる可能性があります。現在の(レガシー)バージョンに対応したペイウォールを設計するか、現在の(レガシー)バージョンのユーザーがレンダリングされないペイウォールで問題が発生することを許容するかのどちらかを選択することになります。 - **ターゲティングの喪失**: すべてのユーザーに **All Users** オーディエンス向けに設計された同じペイウォールが表示されるため、パーソナライズされたターゲティング(国、マーケティングアトリビューション、独自のカスタム属性に基づくものを含む)が失われます。 これらのデメリットを許容してでもフローやペイウォールの取得を高速化したい場合は、以下のように `getFlowForDefaultAudience` メソッドを使用してください。それ以外の場合は、[上記](get-pb-paywalls#fetch-paywall-designed-with-paywall-builder)で説明した `getFlow` を使用してください。 ::: ```swift showLineNumbers Adapty.getFlowForDefaultAudience(placementId: "YOUR_PLACEMENT_ID") { result in switch result { case let .success(flow): // the requested flow case let .failure(error): // handle the error } } ``` | パラメーター | 必須/任意 | 説明 | |---------|--------|-----------| | **placementId** | 必須 | [プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成した際に指定した値です。 | | **fetchPolicy** | デフォルト: `.reloadRevalidatingCacheData` | <p>デフォルトでは、SDK はサーバーからデータを読み込もうとし、失敗した場合はキャッシュされたデータを返します。この方式はユーザーが常に最新のデータを受け取れるため、こちらをお勧めします。</p><p></p><p>ただし、ユーザーのインターネット接続が不安定だと思われる場合は、`.returnCacheDataElseLoad` を使用すると、キャッシュが存在する場合にそれを返すことができます。この場合、ユーザーが最新データを取得できないことがありますが、接続状況に関わらず読み込みが速くなります。キャッシュはセッション中でも定期的に更新されるため、ネットワークリクエストを避ける目的でのキャッシュ使用は安全です。</p><p></p><p>なお、キャッシュはアプリを再起動しても保持され、アプリの再インストールまたは手動でのクリーンアップ時にのみ削除されます。</p> | ## アセットのカスタマイズ \{#customize-assets\} ペイウォール/フローの画像や動画をカスタマイズするには、カスタムアセットを実装します。 ヒーロー画像と動画には事前定義済みのID(`hero_image`と`hero_video`)が割り当てられています。カスタムアセットバンドルでは、これらのIDを使って各要素を指定し、動作をカスタマイズします。 その他の画像や動画については、Adapty ダッシュボードで[カスタムIDを設定する](custom-media)必要があります。 たとえば、次のようなことができます。 - 一部のユーザーに別の画像や動画を表示する。 - リモートのメイン画像の読み込み中に、ローカルのプレビュー画像を表示する。 - 動画を再生する前にプレビュー画像を表示する。 - 動画が読み込まれる前にプレイヤーがレイアウトスペースを確保できるよう、動画のピクセル解像度を指定する(アスペクト比 = `width / height`)。スキップするには `nil` を渡す。 カスタムアセットをシンプルな辞書で提供する方法の例を以下に示します: ```swift showLineNumbers let customAssets: [String: AdaptyCustomAsset] = [ // Show a local image using a custom ID "custom_image": .image( .uiImage(value: UIImage(named: "image_name")!) ), // Show a local preview image while a remote main image is loading "hero_image": .image( .remote( url: URL(string: "https://example.com/image.jpg")!, preview: UIImage(named: "preview_image") ) ), // Show a local video with a preview image and a known resolution "hero_video": .video( .file( url: Bundle.main.url(forResource: "custom_video", withExtension: "mp4")!, preview: .uiImage(value: UIImage(named: "video_preview")!), resolution: CGSize(width: 1080, height: 1920) ) ), ] let flowConfig = try await AdaptyUI.getFlowConfiguration( forFlow: flow, assetsResolver: customAssets ) ``` :::note アセットが見つからない場合、ペイウォール/フローはデフォルトの外観にフォールバックします。 ::: ## 開発者定義タイマーの設定 \{#set-up-developer-defined-timers\} モバイルアプリでカスタムタイマーを使用するには、`AdaptyTimerResolver` プロトコルに準拠したオブジェクトを作成します。このオブジェクトは、各カスタムタイマーのレンダリング方法を定義します。必要であれば、このプロトコルにすでに準拠している `[String: Date]` ディクショナリを直接使用することもできます。以下に例を示します: ```swift showLineNumbers @MainActor struct AdaptyTimerResolverImpl: AdaptyTimerResolver { func timerEndAtDate(for timerId: String) -> Date { switch timerId { case "CUSTOM_TIMER_6H": Date(timeIntervalSinceNow: 3600.0 * 6.0) // 6 hours case "CUSTOM_TIMER_NY": Calendar.current.date(from: DateComponents(year: 2025, month: 1, day: 1)) ?? Date(timeIntervalSinceNow: 3600.0) default: Date(timeIntervalSinceNow: 3600.0) // 1 hour } } } ``` この例では、`CUSTOM_TIMER_NY` と `CUSTOM_TIMER_6H` は、Adapty ダッシュボードで設定した開発者定義タイマーの **Timer ID** です。`timerResolver` により、アプリは各タイマーを正しい値で動的に更新できます。例えば: - `CUSTOM_TIMER_NY`: 元日など、タイマーの終了までの残り時間。 - `CUSTOM_TIMER_6H`: ユーザーがペイウォールを開いてから始まった6時間のうち、残りの時間。 </SDKv4> <SDKv3> [Adapty ダッシュボード](adapty-paywall-builder)のペイウォールビルダーで[ペイウォールのビジュアルデザインを作成](adapty-paywall-builder)したら、それをモバイルアプリに表示できます。最初のステップは、以下の説明に従ってプレースメントに関連付けられたペイウォールとそのビュー設定を取得することです。 このトピックはペイウォールビルダーでカスタマイズされたペイウォールに関するものです。ペイウォールを手動で実装する場合は、[リモートコンフィグペイウォール用のペイウォールとプロダクトの取得](fetch-paywalls-and-products)を参照してください。 :::tip Adapty SDK をモバイルアプリに統合した実際の例を見たい方は、[サンプルアプリ](sample-apps)をご覧ください。ペイウォールの表示、購入処理、その他の基本的な機能を含む完全なセットアップを確認できます。 ::: <details> <summary>モバイルアプリでペイウォールを表示する前に</summary> 1. Adapty ダッシュボードで[プロダクトを作成する](create-product)。 2. Adapty ダッシュボードで[ペイウォールを作成し、プロダクトを追加する](create-paywall)。 3. Adapty ダッシュボードで[プレースメントを作成し、ペイウォールを追加する](create-placement)。 4. モバイルアプリに [Adapty SDK](sdk-installation-ios) をインストールする。 </details> ## ペイウォールビルダーで作成したペイウォールを取得する \{#fetch-paywall-designed-with-paywall-builder\} [ペイウォールビルダーを使ってペイウォールをデザインした](adapty-paywall-builder)場合、ユーザーに表示するためのレンダリングコードをアプリに書く必要はありません。このようなペイウォールには、表示する内容と表示方法の両方が含まれています。ただし、プレースメントを通じてペイウォールのIDを取得し、ビュー設定を取得してから、アプリ内に表示する必要があります。 最適なパフォーマンスを確保するために、ペイウォールとその[ビュー設定](get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder)をできるだけ早く取得し、ユーザーに表示する前に画像のダウンロードに十分な時間を確保することが重要です。 ペイウォールを取得するには、`getPaywall` メソッドを使用します: <Tabs> <TabItem value="swift" label="Swift"> ```swift showLineNumbers do { let paywall = try await Adapty.getPaywall("YOUR_PLACEMENT_ID") // the requested paywall } catch { // handle the error } ``` </TabItem> <TabItem value="callback" label="Swift-Callback"> ```swift showLineNumbers Adapty.getPaywall(placementId: "YOUR_PLACEMENT_ID", locale: "en") { result in switch result { case let .success(paywall): // the requested paywall case let .failure(error): // handle the error } } ``` </TabItem> </Tabs> パラメーター: | パラメータ | 必須/任意 | 説明 | |---------|--------|-----------| | **placementId** | 必須 | 取得したい[プレースメント](placements)の識別子です。Adapty ダッシュボードでプレースメントを作成する際に指定した値を使用します。 | | **locale** | <p>任意</p><p>デフォルト: `en`</p> | <p>[ペイウォールのローカライズ](add-paywall-locale-in-adapty-paywall-builder)の識別子です。このパラメータは、マイナス(**-**)で区切られた1つまたは2つのサブタグで構成された言語コードを指定します。最初のサブタグは言語、2番目のサブタグは地域を表します。</p><p></p><p>例: `en` は英語、`pt-br` はブラジルポルトガル語を表します。</p><p>ロケールコードの詳細と推奨される使い方については、[ローカライズとロケールコード](localizations-and-locale-codes)を参照してください。</p> | | **fetchPolicy** | デフォルト: `.reloadRevalidatingCacheData` | <p>デフォルトでは、SDK はサーバーからデータを読み込もうとし、失敗した場合はキャッシュされたデータを返します。ユーザーが常に最新のデータを受け取れるようになるため、この設定を推奨します。</p><p></p><p>ただし、ユーザーの通信環境が不安定な場合は、`.returnCacheDataElseLoad` を使用してキャッシュが存在する場合はキャッシュデータを返すことを検討してください。この設定では最新データが取得できないことがありますが、通信が不安定な環境でも読み込みが速くなります。キャッシュはセッション中に定期的に更新されるため、ネットワークリクエストを減らす目的でキャッシュを利用しても問題ありません。</p><p></p><p>キャッシュはアプリを再起動しても保持され、アプリの再インストールまたは手動でのクリアによってのみ削除されます。</p><p></p><p>Adapty SDK はペイウォールをローカルに2層で保存します。1つは上記の定期更新キャッシュ、もう1つは[フォールバックペイウォール](fallback-paywalls)です。また、ペイウォールをより速く取得するために CDN を使用し、CDN に接続できない場合に備えてスタンドアロンのフォールバックサーバーも用意しています。このシステムは、通信環境が悪い場合でも常にペイウォールの最新バージョンを確実に取得できるよう設計されています。</p> | | **loadTimeout** | デフォルト: 5秒 | <p>このメソッドのタイムアウト上限を設定します。タイムアウトに達した場合、キャッシュデータまたはローカルのフォールバックが返されます。</p><p>内部的に複数のリクエストが発生する場合があるため、まれに `loadTimeout` で指定した時間よりもわずかに遅くタイムアウトすることがあります。</p> | レスポンスパラメーター: | パラメーター | 説明 | | :-------- | :---------- | | Paywall | プロダクトIDのリスト、ペイウォール識別子、リモートコンフィグ、その他いくつかのプロパティを含む [`AdaptyPaywall`](https://swift.adapty.io/documentation/adapty/adaptypaywall) オブジェクト。 | ## ペイウォールビルダーで作成したペイウォールのビュー設定を取得する \{#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder\} :::important ペイウォールビルダーで **Show on device** トグルを有効にしてください。このオプションがオンになっていない場合、ビュー設定を取得できません。 ::: ペイウォールを取得したら、ビュー設定が含まれているかどうかを確認してください。ビュー設定が存在する場合は、そのペイウォールがペイウォールビルダーで作成されたことを意味します。これにより、ペイウォールの表示方法が決まります。ビュー設定がある場合はペイウォールビルダーのペイウォールとして扱い、ない場合は[リモートコンフィグのペイウォールとして処理してください](present-remote-config-paywalls)。 `getPaywallConfiguration` メソッドを使って、ビュー設定を読み込みます。 ```swift showLineNumbers guard paywall.hasViewConfiguration else { // use your custom logic return } do { let paywallConfiguration = try await AdaptyUI.getPaywallConfiguration( forPaywall: paywall, products: products ) // use loaded configuration } catch { // handle the error } ``` パラメーター: | パラメータ | 必須/任意 | 説明 | | :----------------------- | :------------- | :---------- | | **paywall** | 必須 | 対象のペイウォールのコントローラーを取得するための `AdaptyPaywall` オブジェクト。 | | **loadTimeout** | デフォルト: 5秒 | このメソッドのタイムアウト上限を設定します。タイムアウトに達した場合、キャッシュされたデータまたはローカルのフォールバックが返されます。内部で複数のリクエストが発生する場合があるため、まれに `loadTimeout` で指定した時間よりもわずかに遅れてタイムアウトすることがあります。 | | **products** | 任意 | 画面上でのプロダクト表示タイミングを最適化するために、`AdaptyPaywallProduct` オブジェクトの配列を指定します。`nil` を渡した場合、AdaptyUI が自動的に必要なプロダクトを取得します。 | :::note 複数の言語を使用している場合は、[ペイウォールビルダーのローカライゼーションを追加する方法](add-paywall-locale-in-adapty-paywall-builder)と、ロケールコードを正しく使用する方法を[こちら](localizations-and-locale-codes)でご確認ください。 ::: 読み込みが完了したら、[ペイウォールを表示](ios-present-paywalls)してください。 ## デフォルトオーディエンス向けペイウォールを取得してより速く表示する \{#get-a-paywall-for-a-default-audience-to-fetch-it-faster\} 通常、ペイウォールはほぼ瞬時に取得されるため、速度を気にする必要はありません。ただし、オーディエンスやペイウォールの数が多く、ユーザーのインターネット接続が不安定な場合は、ペイウォールの取得に想定以上の時間がかかることがあります。そのような状況では、ペイウォールをまったく表示しないよりも、デフォルトのペイウォールを表示してスムーズなユーザー体験を提供することを検討するとよいでしょう。 この問題に対処するために、`getPaywallForDefaultAudience` メソッドを使用できます。このメソッドは、指定されたプレースメントの **All Users** オーディエンス向けペイウォールを取得します。ただし、推奨されるアプローチは `getPaywall` メソッドでペイウォールを取得することであり、詳細は上記の [ペイウォール情報の取得](get-pb-paywalls#fetch-paywall-designed-with-paywall-builder) セクションをご覧ください。 :::warning `getPaywall` を推奨する理由 `getPaywallForDefaultAudience` メソッドにはいくつかの重大な欠点があります: - **後方互換性の問題**: 異なるアプリバージョン(現行バージョンと将来のバージョン)に対して異なるペイウォールを表示する必要がある場合、課題が生じる可能性があります。現行(レガシー)バージョンに対応したペイウォールを設計するか、現行(レガシー)バージョンのユーザーがレンダリングされないペイウォールに遭遇するリスクを許容するかのどちらかを選択しなければなりません。 - **ターゲティングの喪失**: すべてのユーザーが **All Users** オーディエンス向けに設計された同じペイウォールを見ることになるため、パーソナライズされたターゲティング(国、マーケティングアトリビューション、独自のカスタム属性に基づくものを含む)が失われます。 これらのデメリットを受け入れてでもペイウォールの取得を高速化したい場合は、以下のように `getPaywallForDefaultAudience` メソッドを使用してください。そうでない場合は、[上記](get-pb-paywalls#fetch-paywall-designed-with-paywall-builder)で説明した `getPaywall` を使用してください。 ::: ```swift showLineNumbers Adapty.getPaywallForDefaultAudience(placementId: "YOUR_PLACEMENT_ID", locale: "en") { result in switch result { case let .success(paywall): // the requested paywall case let .failure(error): // handle the error } } ``` :::note `getPaywallForDefaultAudience` メソッドは iOS SDK バージョン 2.11.2 以降で利用可能です。 ::: | パラメーター | 必須/任意 | 説明 | |---------|--------|-----------| | **placementId** | 必須 | [プレースメント](placements)の識別子です。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** | <p>任意</p><p>デフォルト: `en`</p> | <p>[ペイウォールのローカライズ](add-remote-config-locale)の識別子です。このパラメーターは、マイナス(**-**)文字で区切られた1つ以上のサブタグで構成される言語コードである必要があります。最初のサブタグは言語、2番目は地域を表します。</p><p></p><p>例: `en` は英語、`pt-br` はブラジルポルトガル語を表します。</p><p></p><p>ロケールコードおよび推奨される使用方法については、[ローカライズとロケールコード](localizations-and-locale-codes)を参照してください。</p> | | **fetchPolicy** | デフォルト: `.reloadRevalidatingCacheData` | <p>デフォルトでは、SDK はサーバーからデータを読み込もうとし、失敗した場合はキャッシュされたデータを返します。ユーザーが常に最新のデータを受け取れるため、この設定を推奨します。</p><p></p><p>ただし、ユーザーが不安定なインターネット環境にある場合は、`.returnCacheDataElseLoad` の使用を検討してください。キャッシュが存在する場合はキャッシュデータを返すため、最新データが得られない場合もありますが、接続状況に関わらず読み込みが速くなります。キャッシュは定期的に更新されるため、セッション中にネットワークリクエストを減らす目的で安全に利用できます。</p><p></p><p>キャッシュはアプリを再起動しても保持され、アプリの再インストールまたは手動でのクリーンアップ時にのみ削除されます。</p> | ## アセットのカスタマイズ \{#customize-assets\} ペイウォールの画像や動画をカスタマイズするには、カスタムアセットを実装します。 ヒーロー画像と動画には、`hero_image` と `hero_video` という定義済みIDがあります。カスタムアセットバンドルでは、これらのIDを使って各要素を指定し、動作をカスタマイズできます。 その他の画像や動画については、Adapty ダッシュボードで[カスタムIDを設定](custom-media)する必要があります。 たとえば、次のようなことができます。 - 一部のユーザーに別の画像や動画を表示する。 - リモートのメイン画像の読み込み中に、ローカルのプレビュー画像を表示する。 - 動画を再生する前にプレビュー画像を表示する。 :::important この機能を使用するには、Adapty iOS SDK をバージョン 3.7.0 以上にアップデートしてください。 ::: カスタムアセットをシンプルな辞書形式で提供する方法の例を示します: ```swift showLineNumbers let customAssets: [String: AdaptyCustomAsset] = [ // Show a local image using a custom ID "custom_image": .image( .uiImage(value: UIImage(named: "image_name")!) ), // Show a local preview image while a remote main image is loading "hero_image": .image( .remote( url: URL(string: "https://example.com/image.jpg")!, preview: UIImage(named: "preview_image") ) ), // Show a local video with a preview image "hero_video": .video( .file( url: Bundle.main.url(forResource: "custom_video", withExtension: "mp4")!, preview: .uiImage(value: UIImage(named: "video_preview")!) ) ), ] let paywallConfig = try await AdaptyUI.getPaywallConfiguration( forPaywall: paywall, assetsResolver: customAssets ) ``` :::note アセットが見つからない場合、ペイウォールはデフォルトの外観にフォールバックします。 ::: ## デベロッパー定義タイマーの設定 \{#set-up-developer-defined-timers\} モバイルアプリでカスタムタイマーを使用するには、`AdaptyTimerResolver` プロトコルに準拠したオブジェクトを作成します。このオブジェクトは、各カスタムタイマーのレンダリング方法を定義します。`[String: Date]` ディクショナリはすでにこのプロトコルに準拠しているため、直接使用することもできます。以下に例を示します。 ```swift showLineNumbers @MainActor struct AdaptyTimerResolverImpl: AdaptyTimerResolver { func timerEndAtDate(for timerId: String) -> Date { switch timerId { case "CUSTOM_TIMER_6H": Date(timeIntervalSinceNow: 3600.0 * 6.0) // 6 hours case "CUSTOM_TIMER_NY": Calendar.current.date(from: DateComponents(year: 2025, month: 1, day: 1)) ?? Date(timeIntervalSinceNow: 3600.0) default: Date(timeIntervalSinceNow: 3600.0) // 1 hour } } } ``` この例では、`CUSTOM_TIMER_NY` と `CUSTOM_TIMER_6H` は、Adapty ダッシュボードで設定した開発者定義タイマーの **Timer ID** です。`timerResolver` により、アプリは各タイマーを正しい値で動的に更新できます。例えば: - `CUSTOM_TIMER_NY`: 元日など、タイマー終了までの残り時間。 - `CUSTOM_TIMER_6H`: ユーザーがペイウォールを開いてから始まった6時間のうち、残り時間。 </SDKv3> --- # File: ios-present-paywalls --- --- title: "フローとペイウォールの表示 - iOS" description: "iOSアプリでユーザーにフローとペイウォールを表示します。" --- <SDKv4> <MethodPromo method="getFlow" label="フローとペイウォールの表示" /> フローまたはペイウォールを作成した場合、ユーザーに表示するためにモバイルアプリのコードでレンダリングを気にする必要はありません。フローやペイウォールには、表示する内容とその表示方法の両方が含まれています。 以下で使用する `AdaptyUI.FlowConfiguration` オブジェクトの取得方法については、[フローとペイウォールの取得](get-pb-paywalls)を参照してください。 ## SwiftUI でフローとペイウォールを表示する \{#present-flows-and-paywalls-in-swiftui\} ### モーダルビューとして表示する \{#present-as-a-modal-view\} フローまたはペイウォールをモーダルビューとしてデバイス画面に表示するには、SwiftUI の `.flow` モディファイアを使用します。最小限の呼び出しには `isPresented`、`flowConfiguration`、および4つの必須コールバックが必要です。 ```swift showLineNumbers title="SwiftUI" .flow( isPresented: $flowPresented, flowConfiguration: <AdaptyUI.FlowConfiguration>, didFailPurchase: { _, _ in /* handle the error */ }, didFinishRestore: { _ in /* check access level and dismiss */ }, didFailRestore: { _ in /* handle the error */ }, didReceiveError: { _ in flowPresented = false } ) ``` ボタンタップを処理する `didPerformAction` や購入成功に反応する `didFinishPurchase` などのオプションコールバックを追加することで、より細かく制御できます。 ```swift showLineNumbers title="SwiftUI" @State var flowPresented = false // この変数の状態を管理し、フローまたはペイウォールを表示したいタイミングで `true` に設定してください var body: some View { Text("Hello, AdaptyUI!") .flow( isPresented: $flowPresented, flowConfiguration: <AdaptyUI.FlowConfiguration>, didPerformAction: { action in switch action { case .close: flowPresented = false default: // Handle other actions break } }, didFailPurchase: { product, error in /* handle the error */ }, didFinishRestore: { profile in /* check access level and dismiss */ }, didFailRestore: { error in /* handle the error */ }, didReceiveError: { error in flowPresented = false } ) } ``` パラメータ: | パラメータ | 必須 | 説明 | |:-----------------------|:---------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **isPresented** | 必須 | フローまたはペイウォール画面の表示状態を管理するバインディング。 | | **flowConfiguration** | 必須 | フローまたはペイウォールの視覚的な詳細を含む `AdaptyUI.FlowConfiguration` オブジェクト。`AdaptyUI.getFlowConfiguration(forFlow:)` メソッドを使用します。詳細は[フローとペイウォールの取得](get-pb-paywalls)を参照してください。 | | **didFailPurchase** | 必須 | `Adapty.makePurchase()` が失敗した際に呼び出されます。 | | **didFinishRestore** | 必須 | `Adapty.restorePurchases()` が正常に完了した際に呼び出されます。 | | **didFailRestore** | 必須 | `Adapty.restorePurchases()` が失敗した際に呼び出されます。 | | **didReceiveError** | 必須 | レンダリングエラーまたはフロースクリプトからのランタイムエラー(例:JavaScript例外、`AdaptyUIError` コード `4105`)が発生した際に呼び出されます。レンダリングエラーが発生した場合は、[Adapty サポート](mailto:support@adapty.io)にお問い合わせください。 | | **fullScreen** | 任意 | フローまたはペイウォールをフルスクリーンモードで表示するか、シートとして表示するかを決定します。デフォルトは `true` です。 | | **didAppear** | 任意 | フローまたはペイウォールのビューが表示された際に呼び出されます。 | | **didDisappear** | 任意 | フローまたはペイウォールのビューが閉じられた際に呼び出されます。 | | **didPerformAction** | 任意 | ユーザーがボタンをタップした際に呼び出されます。`close` と `openURL` の2つのアクションIDが事前定義されており、その他はカスタムでビルダーで設定できます。 | | **didSelectProduct** | 任意 | ユーザーまたはシステムによって購入するプロダクトが選択された際に呼び出されます。 | | **didStartPurchase** | 任意 | ユーザーが購入プロセスを開始した際に呼び出されます。 | | **didFinishPurchase** | 任意 | `Adapty.makePurchase()` が正常に完了した際に呼び出されます。 | | **didFinishWebPaymentNavigation** | 任意 | Web決済のナビゲーションが完了した際に呼び出されます。 | | **didStartRestore** | 任意 | ユーザーが復元プロセスを開始した際に呼び出されます。 | | **didFailLoadingProducts** | 任意 | プロダクトの読み込み中にエラーが発生した際に呼び出されます。再試行するには `true` を返します。 | | **didPartiallyLoadProducts** | 任意 | プロダクトが部分的に読み込まれた際に呼び出されます。 | | **showAlertItem** | 任意 | フローまたはペイウォールの上にアラートアイテムの表示を管理するバインディング。 | | **showAlertBuilder** | 任意 | アラートビューをレンダリングするための関数。 | | **placeholderBuilder** | 任意 | フローまたはペイウォールの読み込み中にプレースホルダービューをレンダリングするための関数。デフォルトは `ProgressView` です。 | パラメータの詳細については、[iOS - イベントの処理](ios-handling-events)を参照してください。 ### 非モーダルビューとして表示する \{#present-as-a-non-modal-view\} フローやペイウォールを、アプリのナビゲーションフロー内のナビゲーション先またはインラインビューとして表示することもできます。SwiftUI ビューで `AdaptyFlowView` を直接使用してください。 ```swift showLineNumbers title="SwiftUI" AdaptyFlowView( flowConfiguration: <AdaptyUI.FlowConfiguration>, didFailPurchase: { product, error in // Handle purchase failure }, didFinishRestore: { profile in // Handle successful restore }, didFailRestore: { error in // Handle restore failure }, didReceiveError: { error in // Handle the error (rendering or JS exception from the flow script). } ) ``` ## UIKit でフローとペイウォールを表示する \{#present-flows-and-paywalls-in-uikit\} デバイス画面にフローまたはペイウォールを表示するには、次の手順を行います。 1. `AdaptyUI.flowController(with:delegate:)` メソッドを使用して、表示したいビジュアルフローを初期化します。 ```swift showLineNumbers title="Swift" import AdaptyUI let visualFlow = try AdaptyUI.flowController( with: <AdaptyUI.FlowConfiguration>, delegate: <AdaptyFlowControllerDelegate> ) ``` リクエストパラメータ: | パラメータ | 必須 | 説明 | | :----------------------- | :------- | :---------- | | **flowConfiguration** | 必須 | フローまたはペイウォールの視覚的な詳細を含む `AdaptyUI.FlowConfiguration` オブジェクト。`AdaptyUI.getFlowConfiguration(forFlow:)` メソッドを使用します。詳細は[フローとペイウォールの取得](get-pb-paywalls)を参照してください。 | | **delegate** | 必須 | フローおよびペイウォールイベントをリッスンする `AdaptyFlowControllerDelegate`。詳細は[フロー&ペイウォールイベントの処理](ios-handling-events)を参照してください。 | 返り値: | オブジェクト | 説明 | | :---------------------- | :------------------------------------------------------- | | **AdaptyFlowController** | リクエストされたフローまたはペイウォール画面を表すオブジェクト。 | 2. オブジェクトが正常に作成されたら、デバイスの画面に表示できます。 ```swift showLineNumbers title="Swift" present(visualFlow, animated: true) ``` :::tip Adapty SDK がモバイルアプリに統合された実際の例を見てみましょう。ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを示す[サンプルアプリ](sample-apps)をご確認ください。 ::: </SDKv4> <SDKv3> ペイウォールビルダーを使用してペイウォールをカスタマイズした場合、ユーザーに表示するためにモバイルアプリのコードでレンダリングを気にする必要はありません。そのようなペイウォールには、ペイウォール内に表示する内容とその表示方法の両方が含まれています。 以下で使用する `AdaptyUI.PaywallConfiguration` オブジェクトの取得方法については、[ペイウォールビルダーのペイウォールとその設定の取得](get-pb-paywalls)を参照してください。 ## SwiftUI でペイウォールを表示する \{#present-paywalls-in-swiftui\} ### モーダルビューとして表示する \{#present-as-a-modal-view\} ビジュアルペイウォールをモーダルビューとしてデバイス画面に表示するには、SwiftUI の `.paywall` モディファイアを使用します。 ```swift showLineNumbers title="SwiftUI" @State var paywallPresented = false // この変数の状態を管理し、ペイウォールを表示したいタイミングで `true` に設定してください var body: some View { Text("Hello, AdaptyUI!") .paywall( isPresented: $paywallPresented, paywallConfiguration: <AdaptyUI.PaywallConfiguration>, didPerformAction: { action in switch action { case .close: paywallPresented = false default: // Handle other actions break } }, didFinishPurchase: { product, profile in paywallPresented = false }, didFailPurchase: { product, error in /* handle the error */ }, didFinishRestore: { profile in /* check access level and dismiss */ }, didFailRestore: { error in /* handle the error */ }, didFailRendering: { error in paywallPresented = false } ) } ``` パラメータ: | パラメータ | 必須 | 説明 | |:----------------------------------|:---------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **isPresented** | 必須 | ペイウォール画面の表示状態を管理するバインディング。 | | **paywallConfiguration** | 必須 | ペイウォールの視覚的な詳細を含む `AdaptyUI.PaywallConfiguration` オブジェクト。`AdaptyUI.paywallConfiguration(for:products:viewConfiguration:observerModeResolver:tagResolver:timerResolver:)` メソッドを使用します。詳細は[ペイウォールビルダーのペイウォールとその設定の取得](get-pb-paywalls)を参照してください。 | | **didFailPurchase** | 必須 | `Adapty.makePurchase()` が失敗した際に呼び出されます。 | | **didFinishRestore** | 必須 | `Adapty.restorePurchases()` が正常に完了した際に呼び出されます。 | | **didFailRestore** | 必須 | `Adapty.restorePurchases()` が失敗した際に呼び出されます。 | | **didFailRendering** | 必須 | インターフェースのレンダリング中にエラーが発生した際に呼び出されます。この場合は、[Adapty サポート](mailto:support@adapty.io)にお問い合わせください。 | | **fullScreen** | 任意 | ペイウォールをフルスクリーンモードで表示するか、モーダルとして表示するかを決定します。デフォルトは `true` です。 | | **didAppear** | 任意 | ペイウォールのビューが表示された際に呼び出されます。 | | **didDisappear** | 任意 | ペイウォールのビューが閉じられた際に呼び出されます。 | | **didPerformAction** | 任意 | ユーザーがボタンをタップした際に呼び出されます。ボタンごとに異なるアクションIDがあります。`close` と `openURL` の2つのアクションIDが事前定義されており、その他はカスタムでビルダーで設定できます。 | | **didSelectProduct** | 任意 | ユーザーまたはシステムによって購入するプロダクトが選択された場合に呼び出されます。 | | **didStartPurchase** | 任意 | ユーザーが購入プロセスを開始した際に呼び出されます。 | | **didFinishPurchase** | 任意 | `Adapty.makePurchase()` が正常に完了した際に呼び出されます。 | | **didFinishWebPaymentNavigation** | 任意 | Web決済のナビゲーションが完了した際に呼び出されます。 | | **didStartRestore** | 任意 | ユーザーが復元プロセスを開始した際に呼び出されます。 | | **didFailLoadingProducts** | 任意 | プロダクトの読み込み中にエラーが発生した際に呼び出されます。再試行するには `true` を返します。 | | **didPartiallyLoadProducts** | 任意 | プロダクトが部分的に読み込まれた際に呼び出されます。 | | **showAlertItem** | 任意 | ペイウォールの上にアラートアイテムの表示を管理するバインディング。 | | **showAlertBuilder** | 任意 | アラートビューをレンダリングするための関数。 | | **placeholderBuilder** | 任意 | ペイウォールの読み込み中にプレースホルダービューをレンダリングするための関数。 | パラメータの詳細については、[iOS - イベントの処理](ios-handling-events)を参照してください。 ### 非モーダルビューとして表示する \{#present-as-a-non-modal-view\} ペイウォールを、アプリのナビゲーションフロー内のナビゲーション先またはインラインビューとして表示することもできます。SwiftUI ビューで `AdaptyPaywallView` を直接使用してください。 ```swift showLineNumbers title="SwiftUI" AdaptyPaywallView( paywallConfiguration: <AdaptyUI.PaywallConfiguration>, didFailPurchase: { product, error in // Handle purchase failure }, didFinishRestore: { profile in // Handle successful restore }, didFailRestore: { error in // Handle restore failure }, didFailRendering: { error in // Handle rendering error } ) ``` ## UIKit でペイウォールを表示する \{#present-paywalls-in-uikit\} デバイス画面にビジュアルペイウォールを表示するには、次の手順を行います。 1. `.paywallController(for:products:viewConfiguration:delegate:)` メソッドを使用して、表示したいビジュアルペイウォールを初期化します。 ```swift showLineNumbers title="Swift" import AdaptyUI let visualPaywall = AdaptyUI.paywallController( with: <paywall configuration object>, delegate: <AdaptyPaywallControllerDelegate> ) ``` リクエストパラメータ: | パラメータ | 必須 | 説明 | | :----------------------- | :------- | :---------- | | **paywall configuration** | 必須 | ペイウォールの視覚的な詳細を含む `AdaptyUI.PaywallConfiguration` オブジェクト。`AdaptyUI.getPaywallConfiguration(forPaywall:locale:)` メソッドを使用します。詳細は[ペイウォールビルダーのペイウォールとその設定の取得](get-pb-paywalls)を参照してください。 | | **delegate** | 必須 | ペイウォールイベントをリッスンする `AdaptyPaywallControllerDelegate`。詳細は[ペイウォールイベントの処理](ios-handling-events)を参照してください。 | 返り値: | オブジェクト | 説明 | | :---------------------- | :--------------------------------------------------- | | **AdaptyPaywallController** | リクエストされたペイウォール画面を表すオブジェクト。 | 2. オブジェクトが正常に作成されたら、デバイスの画面に表示できます。 ```swift showLineNumbers title="Swift" present(visualPaywall, animated: true) ``` :::tip Adapty SDK がモバイルアプリに統合された実際の例を見てみましょう。ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを示す[サンプルアプリ](sample-apps)をご確認ください。 ::: </SDKv3> --- # File: handle-paywall-actions --- --- title: "フローアクションへの応答 - iOS" description: "iOS アプリでペイウォールやオンボーディングフローのボタンアクションを処理し、ユーザー入力を扱う方法。" --- <SDKv4> Adapty のフロービルダーまたはペイウォールビルダーを使用してフローやペイウォールを構築する場合、ボタンを適切に設定することが重要です。 1. [ペイウォールビルダーでボタンを追加](paywall-buttons)し、既存のアクションを割り当てるか、カスタムアクション ID を作成します。 2. 割り当てた各アクションを処理するコードをアプリに記述します。 このガイドでは、カスタムアクションおよび既存アクションをコードで処理する方法を説明します。 :::warning **フロー/ペイウォールのクローズと URL オープンのみ自動処理されます。** その他のボタンアクションはすべて、アプリコード側で適切な処理を実装する必要があります。 ::: :::note iOS SDKは、`AdaptySystemRequestsHandler`を通じて、プッシュ通知やカメラアクセスなどのシステム権限リクエストに応答できます。フローはまだこれらのリクエストをトリガーしないため、現時点では対応不要です。 ::: ## フローとペイウォールを閉じる \{#close-flows-and-paywalls\} フローまたはペイウォールを閉じるボタンを追加するには: 1. ビルダーでボタンを追加し、**Close** アクションを割り当てます。 2. アプリのコードで `close` アクションのハンドラーを実装します。 :::info iOS SDK では、`close` アクションはデフォルトでフローまたはペイウォールを閉じる動作をトリガーします。ただし、必要に応じてコード内でこの動作をオーバーライドできます。たとえば、あるフローを閉じると別のフローが開くようにすることもできます。 ::: ```swift .flow( isPresented: $flowPresented, flowConfiguration: flowConfiguration, didPerformAction: { action in switch action { case .close: flowPresented = false // dismiss the flow or paywall default: break } }, didFailPurchase: { product, error in /* handle the error */ }, didFinishRestore: { profile in /* check access level and dismiss */ }, didFailRestore: { error in /* handle the error */ }, didFailRendering: { error in flowPresented = false } ) ``` ## フローとペイウォールからURLを開く \{#open-urls-from-flows-and-paywalls\} :::tip リンクのグループ(利用規約や購入の復元など)を追加したい場合は、ビルダーで **Link** 要素を追加し、**Open URL** アクションを持つボタンと同じ方法で処理してください。 ::: フローまたはペイウォールにリンクを開くボタン(例:**Terms of use** や **Privacy policy**)を追加するには: 1. ビルダーでボタンを追加し、**Open URL** アクションを割り当て、開きたいURLを入力します。 2. アプリのコードに、受け取ったURLをブラウザで開く `openURL` アクションのハンドラーを実装します。 :::info iOS SDK では、`openURL` アクションはデフォルトでURLを開く動作をします。ただし、必要に応じてコード内でこの動作を上書きすることができます。 ::: ```swift .flow( isPresented: $flowPresented, flowConfiguration: flowConfiguration, didPerformAction: { action in switch action { case let .openURL(url): UIApplication.shared.open(url, options: [:]) // default behavior default: break } }, didFailPurchase: { product, error in /* handle the error */ }, didFinishRestore: { profile in /* check access level and dismiss */ }, didFailRestore: { error in /* handle the error */ }, didFailRendering: { error in flowPresented = false } ) ``` ## カスタムアクションを処理する \{#handle-custom-actions\} その他のアクションを処理するボタンを追加するには: 1. ビルダーでボタンを追加し、**Custom** アクションを割り当て、ID を設定します。 2. アプリのコードに、作成したアクション ID に対応するハンドラーを実装します。 たとえば、別のサブスクリプションオファーや買い切り購入がある場合、別のフローやペイウォールを表示するボタンを追加できます。 ```swift .flow( isPresented: $flowPresented, flowConfiguration: flowConfiguration, didPerformAction: { action in switch action { case let .custom(id): if id == "openNewPaywall" { // Display another flow or paywall } default: break } }, didFailPurchase: { product, error in /* handle the error */ }, didFinishRestore: { profile in /* check access level and dismiss */ }, didFailRestore: { error in /* handle the error */ }, didFailRendering: { error in flowPresented = false } ) ``` </SDKv4> <SDKv3> Adapty ペイウォールビルダーを使ってペイウォールを構築する場合、ボタンを適切に設定することが重要です: 1. [ペイウォールビルダーにボタンを追加](paywall-buttons)し、既存のアクションを割り当てるか、カスタムアクション ID を作成します。 2. 割り当てた各アクションを処理するコードをアプリに記述します。 このガイドでは、コード内でカスタムアクションおよび既存アクションを処理する方法を説明します。 :::warning **購入、復元、ペイウォールのクローズ、URL のオープンのみ自動的に処理されます。** その他のボタンアクションは、アプリのコードで適切に対応を実装する必要があります。 ::: ## ペイウォールを閉じる \{#close-paywalls\} ペイウォールを閉じるボタンを追加するには: 1. ペイウォールビルダーでボタンを追加し、**Close** アクションを割り当てます。 2. アプリのコードで、ペイウォールを閉じる `close` アクションのハンドラーを実装します。 :::info iOS SDK では、`close` アクションはデフォルトでペイウォールを閉じる動作をトリガーします。ただし、必要に応じてコードでこの動作をオーバーライドできます。たとえば、あるペイウォールを閉じることで別のペイウォールを開くようにすることも可能です。 ::: ```swift func paywallController(_ controller: AdaptyPaywallController, didPerform action: AdaptyUI.Action) { switch action { case .close: controller.dismiss(animated: true) // default behavior break } } ``` ## ペイウォールからURLを開く \{#open-urls-from-paywalls\} :::tip リンクのグループ(利用規約や購入の復元など)を追加したい場合は、ペイウォールビルダーで **Link** 要素を追加し、**Open URL** アクションを持つボタンと同じ方法で処理してください。 ::: ペイウォールにリンクを開くボタン(**Terms of use** や **Privacy policy** など)を追加するには: 1. ペイウォールビルダーでボタンを追加し、**Open URL** アクションを割り当てて、開きたいURLを入力します。 2. アプリのコードで、受け取ったURLをブラウザで開く `openUrl` アクションのハンドラーを実装します。 :::info iOS SDKでは、`openUrl`アクションはデフォルトでURLを開く動作をします。ただし、必要に応じてコード内でこの動作をオーバーライドできます。 ::: ```swift func paywallController(_ controller: AdaptyPaywallController, didPerform action: AdaptyUI.Action) { switch action { case let .openURL(url): UIApplication.shared.open(url, options: [:]) // default behavior break } } ``` ## アプリへのログイン \{#log-into-the-app\} ユーザーをアプリにログインさせるボタンを追加するには: 1. ペイウォールビルダーでボタンを追加し、**Login** アクションを割り当てます。 2. アプリのコードで、ユーザーを識別する `login` アクションのハンドラーを実装します。 ```swift func paywallController(_ controller: AdaptyPaywallController, didPerform action: AdaptyUI.Action) { switch action { case .login: // Show a login screen let loginVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "LoginViewController") controller.present(loginVC, animated: true) } } ``` ## カスタムアクションの処理 \{#handle-custom-actions\} その他のアクションを処理するボタンを追加するには: 1. ペイウォールビルダーでボタンを追加し、**Custom** アクションを割り当てて、IDを設定します。 2. アプリのコードで、作成したアクションIDのハンドラーを実装します。 たとえば、別のサブスクリプションオファーや買い切り購入がある場合、別のペイウォールを表示するボタンを追加できます: ```swift func paywallController(_ controller: AdaptyPaywallController, didPerform action: AdaptyUI.Action) { switch action { case let .custom(id): if id == "openNewPaywall" { // Display another paywall } } break } } ``` </SDKv3> --- # File: ios-handling-events --- --- title: "フローとペイウォールのイベントを処理する - iOS" description: "iOSアプリでフローおよびペイウォールのイベントを処理する方法。" --- <SDKv4> :::important このガイドでは、購入・復元・プロダクト選択・ペイウォール表示に関するイベント処理について説明します。また、ボタン操作(ペイウォールを閉じる、リンクを開くなど)の実装も必要です。詳しくは[ボタン操作の処理に関するガイド](handle-paywall-actions)をご覧ください。 ::: フローとペイウォールは、購入や購入の復元に追加のコードは不要です。ただし、アプリが反応できるイベントをいくつか生成します。これらのイベントには、ボタン操作(閉じるボタン、URL、プロダクト選択など)や購入関連アクションの通知が含まれます。以下で、これらのイベントへの対応方法を説明します。 :::tip Adapty SDK をモバイルアプリに組み込む実際の例を見たいですか?ペイウォールの表示、購入、その他の基本的な機能を含む完全なセットアップを示す[サンプルアプリ](sample-apps)をぜひご確認ください。 ::: ## SwiftUI でのイベント処理 \{#handling-events-in-swiftui\} モバイルアプリ内のフローまたはペイウォール画面で発生するプロセスを制御・監視するには、SwiftUI の `.flow` モディファイアを使用します。 ```swift showLineNumbers title="Swift" @State var flowPresented = false var body: some View { Text("Hello, AdaptyUI!") .flow( isPresented: $flowPresented, flowConfiguration: flowConfiguration, didPerformAction: { action in switch action { case .close: flowPresented = false case let .openURL(url): // handle opening the URL (incl. for terms and privacy) default: // handle other actions } }, didSelectProduct: { product in /* Handle the event */ }, didStartPurchase: { product in /* Handle the event */ }, didFailPurchase: { product, error in /* handle the error */ }, didStartRestore: { /* Handle the event */ }, didFinishRestore: { profile in /* check access level and dismiss */ }, didFailRestore: { error in /* handle the error */ }, didReceiveError: { error in flowPresented = false }, didFailLoadingProducts: { error in // Return `true` to retry loading return false } ) } ``` クロージャのパラメーターは必要なものだけ登録すれば、不要なものは省略できます。 | パラメータ | 必須 | 説明 | |:-----------------------|:-----|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **isPresented** | 必須 | フローまたはペイウォール画面の表示を管理するバインディング。 | | **flowConfiguration** | 必須 | フローまたはペイウォールの視覚的な詳細を含む `AdaptyUI.FlowConfiguration` オブジェクト。詳細は[フローとペイウォールの取得](get-pb-paywalls)を参照してください。 | | **didFailPurchase** | 必須 | `Adapty.makePurchase()` が失敗したときに呼び出されます。 | | **didFinishRestore** | 必須 | `Adapty.restorePurchases()` が正常に完了したときに呼び出されます。 | | **didFailRestore** | 必須 | `Adapty.restorePurchases()` が失敗したときに呼び出されます。 | | **didReceiveError** | 必須 | フローでレンダリングエラーまたはフロースクリプトの実行時エラー(例:JavaScript例外、`AdaptyUIError` コード `4105`)が発生したときに呼び出されます。レンダリングエラーの場合は[Adapty サポート](mailto:support@adapty.io)にお問い合わせください。 | | **placeholderBuilder** | 任意 | フローまたはペイウォールの読み込み中にプレースホルダービューをレンダリングする関数。デフォルトは `ProgressView`。 | | **fullScreen** | 任意 | フローまたはペイウォールをフルスクリーンモードで表示するか、シートとして表示するかを決定します。デフォルトは `true`。 | | **didAppear** | 任意 | フローまたはペイウォールのビューが画面に表示されたときに呼び出されます。 | | **didDisappear** | 任意 | フローまたはペイウォールのビューが閉じられたときに呼び出されます。 | | **didPerformAction** | 任意 | ユーザーがボタンをクリックしたときに呼び出されます。アクション ID として `close` と `openURL` が事前定義されており、その他はビルダーで設定できるカスタムIDです。 | | **didSelectProduct** | 任意 | ユーザーまたはシステムによってプロダクトが購入対象として選択されたときに呼び出されます。 | | **didStartPurchase** | 任意 | ユーザーが購入プロセスを開始したときに呼び出されます。 | | **didFinishPurchase** | 任意 | `Adapty.makePurchase()` が正常に完了したときに呼び出されます。 | | **didFinishWebPaymentNavigation** | 任意 | ウェブ決済のナビゲーションが完了したときに呼び出されます。 | | **didStartRestore** | 任意 | ユーザーが復元プロセスを開始したときに呼び出されます。 | | **didFailLoadingProducts** | 任意 | プロダクトの読み込み中にエラーが発生したときに呼び出されます。`true` を返すと再読み込みを試みます。 | | **didPartiallyLoadProducts** | 任意 | プロダクトが部分的に読み込まれたときに呼び出されます。 | | **showAlertItem** | 任意 | フローまたはペイウォールの上にアラートアイテムの表示を管理するバインディング。 | | **showAlertBuilder** | 任意 | アラートビューをレンダリングする関数。 | ## UIKitでのイベント処理 \{#handling-events-in-uikit\} UIKitアプリでは、`AdaptyFlowControllerDelegate`プロトコルを通じてイベントを処理します。`AdaptyFlowController`と`AdaptyFlowControllerDelegate`のセットアップ方法については、[フロー&ペイウォールの表示 - iOS](ios-present-paywalls)を参照してください。 このプロトコルには13のメソッドが定義されています。そのうち3つ(`didFailPurchase`、`didFinishRestoreWith`、`didFailRestoreWith`)はデフォルト実装がなく、プロトコルに準拠する際に必ず実装する必要があります。残りのメソッドはデフォルトで何も行わない実装が提供されており、カスタムの動作が必要な場合にオーバーライドできます。以下ではメソッドを目的別にグループ化して説明します。 ### ライフサイクル \{#lifecycle\} ```swift showLineNumbers title="Swift" func flowControllerDidAppear(_ controller: AdaptyFlowController) { } func flowControllerDidDisappear(_ controller: AdaptyFlowController) { } ``` これらはフローまたはペイウォールのビューが表示・非表示になったときに呼び出されます。 ### ユーザーアクション \{#user-actions\} ```swift showLineNumbers title="Swift" func flowController( _ controller: AdaptyFlowController, didPerform action: AdaptyUI.Action ) { } ``` `AdaptyUI.Action` のケース: - `.close` — デフォルトの動作はコントローラーを閉じます。コントローラーを画面に残したり、追加のクリーンアップ処理を行う場合はオーバーライドしてください。 - `.openURL(url:)` — デフォルトの動作は `UIApplication.shared.open(...)` でURLを開きます。 - `.custom(id:)` — ビルダーでカスタムアクションIDが設定されたボタンがタップされたときに発火します。 ### プロダクト選択 \{#product-selection\} ```swift showLineNumbers title="Swift" func flowController( _ controller: AdaptyFlowController, didSelectProduct product: AdaptyPaywallProduct ) { } ``` ユーザーまたはシステムによってプロダクトが購入対象として選択されたときに呼び出されます。プロダクトにはオファーの全情報が含まれており(v4 ではエリジビリティが自動で判定されるため、`AdaptyPaywallProductWithoutDeterminingOffer` という独立した型は存在しません)。 ### 購入イベント \{#purchase-events\} ```swift showLineNumbers title="Swift" func flowController( _ controller: AdaptyFlowController, didStartPurchase product: AdaptyPaywallProduct ) { } func flowController( _ controller: AdaptyFlowController, didFinishPurchase product: AdaptyPaywallProduct, purchaseResult: AdaptyPurchaseResult ) { // Default: dismiss the controller unless the purchase was cancelled. } func flowController( _ controller: AdaptyFlowController, didFailPurchase product: AdaptyPaywallProduct, error: AdaptyError ) { } ``` `didFailPurchase` はデフォルト実装のない唯一の購入イベントです。`didFinishPurchase` は成功時にコントローラーを閉じるデフォルト実装が用意されています。カスタムの購入後処理が必要な場合のみオーバーライドしてください。 ### リストアイベント \{#restore-events\} ```swift showLineNumbers title="Swift" func flowControllerDidStartRestore(_ controller: AdaptyFlowController) { } func flowController( _ controller: AdaptyFlowController, didFinishRestoreWith profile: AdaptyProfile ) { } func flowController( _ controller: AdaptyFlowController, didFailRestoreWith error: AdaptyError ) { } ``` `didFinishRestoreWith` と `didFailRestoreWith` にはデフォルト実装がありません。コントローラーを閉じる前に、返された `AdaptyProfile` に目的のアクセスレベルが含まれているかどうかを確認してください。 ### フローエラーとプロダクト読み込みエラー \{#flow-errors-and-product-loading-errors\} ```swift showLineNumbers title="Swift" func flowController( _ controller: AdaptyFlowController, didReceiveError error: AdaptyUIError ) { } func flowController( _ controller: AdaptyFlowController, didFailLoadingProductsWith error: AdaptyError ) -> Bool { // Return `true` to retry product loading; default returns `false`. return false } func flowController( _ controller: AdaptyFlowController, didPartiallyLoadProducts failedIds: [String] ) { } ``` `didReceiveError` は、レンダリングエラーおよびフロースクリプトのランタイムエラー(JavaScript例外、`AdaptyUIError` コード `4105`)で発生します。レンダリングエラーが発生した場合は、[Adapty サポートにお問い合わせください](mailto:support@adapty.io)。読み込みエラーの場合は、`didFailLoadingProductsWith` から `true` を返すことでリトライできます。一時的なネットワーク障害に有効です。 ### Web支払いナビゲーション \{#web-payment-navigation\} ```swift showLineNumbers title="Swift" func flowController( _ controller: AdaptyFlowController, didFinishWebPaymentNavigation product: AdaptyPaywallProduct?, error: AdaptyError? ) { } ``` Webの支払いナビゲーションが完了した際(成功・失敗を問わず)に呼び出されます。 </SDKv4> <SDKv3> :::important このガイドでは、購入・復元・プロダクト選択・ペイウォール表示のイベント処理について説明します。ボタン操作(ペイウォールを閉じる、リンクを開くなど)の処理も実装する必要があります。詳しくは[ボタン操作のハンドリングに関するガイド](handle-paywall-actions)をご覧ください。 ::: [ペイウォールビルダー](adapty-paywall-builder)で設定されたペイウォールは、購入や復元のために追加のコードは必要ありません。ただし、アプリが応答できるいくつかのイベントが生成されます。これらのイベントには、ボタン押下(閉じるボタン、URL、プロダクト選択など)や、ペイウォール上で行われた購入関連アクションの通知が含まれます。これらのイベントへの応答方法については、以下をご覧ください。 このガイドは、Adapty SDK v3.0 以降が必要な**新しいペイウォールビルダーのペイウォール**専用です。 :::tip Adapty SDK がモバイルアプリにどのように統合されるか、実際の例を見てみたいですか?[サンプルアプリ](sample-apps)では、ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを確認できます。 ::: ## SwiftUI でのイベント処理 \{#handling-events-in-swiftui\} モバイルアプリ内のペイウォール画面で発生するプロセスを制御・監視するには、SwiftUI の `.paywall` モディファイアを使用してください: ```swift showLineNumbers title="Swift" @State var paywallPresented = false var body: some View { Text("Hello, AdaptyUI!") .paywall( isPresented: $paywallPresented, paywall: paywall, viewConfiguration: viewConfig, didPerformAction: { action in switch action { case .close: paywallPresented = false case let .openURL(url): // handle opening the URL (incl. for terms and privacy) default: // handle other actions } }, didSelectProduct: { /* Handle the event */ }, didStartPurchase: { /* Handle the event */ }, didFinishPurchase: { product, info in /* Handle the event */ }, didFailPurchase: { product, error in /* Handle the event */ }, didStartRestore: { /* Handle the event */ }, didFinishRestore: { /* Handle the event */ }, didFailRestore: { /* Handle the event */ }, didFailRendering: { error in paywallPresented = false }, didFailLoadingProducts: { error in return false } ) } ``` 必要なクロージャパラメータだけを登録し、不要なものは省略できます。この場合、未使用のクロージャパラメータは作成されません。 | パラメータ | 必須 | 説明 | |:----------------------------------|:---------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **isPresented** | 必須 | ペイウォール画面の表示を管理するバインディング。 | | **paywallConfiguration** | 必須 | ペイウォールのビジュアル詳細を含む `AdaptyUI.PaywallConfiguration` オブジェクト。`AdaptyUI.paywallConfiguration(for:products:viewConfiguration:observerModeResolver:tagResolver:timerResolver:)` メソッドを使用してください。詳細は [ペイウォールビルダーのペイウォールと設定の取得](get-pb-paywalls) を参照してください。 | | **didFailPurchase** | 必須 | エラー(支払い不可、ネットワークエラー、無効なプロダクトなど)によって購入が失敗した場合に呼び出されます。ユーザーによるキャンセルや保留中の支払いでは呼び出されません。 | | **didFinishRestore** | 必須 | 購入が正常に完了したときに呼び出されます。 | | **didFailRestore** | 必須 | 購入の復元に失敗したときに呼び出されます。 | | **didFailRendering** | 必須 | インターフェースのレンダリング中にエラーが発生した場合に呼び出されます。この場合は [Adapty サポートにお問い合わせください](mailto:support@adapty.io)。 | | **fullScreen** | 任意 | ペイウォールをフルスクリーンモードで表示するか、モーダルとして表示するかを指定します。デフォルトは `true` です。 | | **didAppear** | 任意 | ペイウォールビューが画面に表示されたときに呼び出されます。また、ユーザーがペイウォール内の [ウェブペイウォールボタン](web-paywall#step-2a-add-a-web-purchase-button) をタップしてインアプリブラウザでウェブペイウォールが開いたときにも呼び出されます。 | | **didDisappear** | 任意 | ペイウォールビューが閉じられたときに呼び出されます。また、ペイウォールからインアプリブラウザで開いた [ウェブペイウォール](web-paywall#step-2a-add-a-web-purchase-button) が画面から消えたときにも呼び出されます。 | | **didPerformAction** | 任意 | ユーザーがボタンをクリックしたときに呼び出されます。ボタンごとにアクション ID が異なります。`close` と `openURL` の 2 つのアクション ID は事前定義されており、その他はビルダーで設定できるカスタムのものです。 | | **didSelectProduct** | 任意 | プロダクトが(ユーザーまたはシステムによって)購入のために選択された場合に呼び出されます。 | | **didStartPurchase** | 任意 | ユーザーが購入プロセスを開始したときに呼び出されます。 | | **didFinishPurchase** | 任意 | 購入が正常に完了したときに呼び出されます。 | | **didFinishWebPaymentNavigation** | 任意 | 購入のために [ウェブペイウォール](web-paywall) を開こうとした後(成功・失敗を問わず)に呼び出されます。 | | **didStartRestore** | 任意 | ユーザーが復元プロセスを開始したときに呼び出されます。 | | **didFailLoadingProducts** | 任意 | プロダクトの読み込み中にエラーが発生したときに呼び出されます。読み込みを再試行する場合は `true` を返してください。 | | **didPartiallyLoadProducts** | 任意 | プロダクトが部分的に読み込まれたときに呼び出されます。 | | **showAlertItem** | 任意 | ペイウォールの上部にアラートアイテムの表示を管理するバインディング。 | | **showAlertBuilder** | 任意 | アラートビューをレンダリングするための関数。 | | **placeholderBuilder** | 任意 | ペイウォールの読み込み中にプレースホルダービューをレンダリングするための関数。 | ## UIKit でのイベント処理 \{#handling-events-in-uikit\} モバイルアプリのペイウォール画面で発生するプロセスを制御・監視するには、`AdaptyPaywallControllerDelegate` のメソッドを実装してください。 ### ユーザー生成イベント \{#user-generated-events\} #### プロダクトの選択 \{#product-selection\} ユーザーが購入するプロダクトを選択すると、このメソッドが呼び出されます: ```swift showLineNumbers title="Swift" func paywallController( _ controller: AdaptyPaywallController, didSelectProduct product: AdaptyPaywallProductWithoutDeterminingOffer ) { } ``` <Details> <summary>イベントの例(クリックして展開)</summary> ```javascript { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" } } ``` </Details> #### 購入開始 \{#started-purchase\} ユーザーが購入プロセスを開始すると、このメソッドが呼び出されます: ```swift showLineNumbers title="Swift" func paywallController(_ controller: AdaptyPaywallController, didStartPurchase product: AdaptyPaywallProduct) { } ``` <Details> <summary>イベントの例(クリックして展開)</summary> ```javascript { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" } } ``` </Details> オブザーバーモードでは呼び出されません。詳細については、[iOS - オブザーバーモードでペイウォールビルダーのペイウォールを表示する](ios-present-paywall-builder-paywalls-in-observer-mode)を参照してください。 #### ウェブペイウォールを使用して購入を開始した \{#started-purchase-using-a-web-paywall\} ユーザーが[ウェブペイウォール](web-paywall)を使って購入プロセスを開始すると、このメソッドが呼び出されます: ```swift showLineNumbers title="Swift" func paywallController( _ controller: AdaptyPaywallController, shouldContinueWebPaymentNavigation product: AdaptyPaywallProduct ) { } ``` <Details> <summary>イベントの例(クリックして展開)</summary> ```javascript { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" } } ``` </Details> #### 購入成功またはキャンセル \{#successful-or-canceled-purchase\} 購入が成功した場合、このメソッドが呼び出されます: ```swift showLineNumbers title="Swift" func paywallController( _ controller: AdaptyPaywallController, didFinishPurchase product: AdaptyPaywallProductWithoutDeterminingOffer, purchaseResult: AdaptyPurchaseResult ) { } } ``` <Details> <summary>イベントの例(クリックして展開)</summary> ```javascript // Successful purchase { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "purchaseResult": { "type": "success", "profile": { "accessLevels": { "premium": { "id": "premium", "isActive": true, "expiresAt": "2024-02-15T10:30:00Z" } } } } } // Cancelled purchase { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "purchaseResult": { "type": "cancelled" } } ``` </Details> この場合は、ペイウォール画面を閉じることをお勧めします。 オブザーバーモードでは呼び出されません。詳細については、[iOS - オブザーバーモードでペイウォールビルダーのペイウォールを表示する](ios-present-paywall-builder-paywalls-in-observer-mode) を参照してください。 #### 購入失敗 \{#failed-purchase\} 購入がエラーにより失敗した場合、このメソッドが呼び出されます。対象となるのは、StoreKit のエラー(支払い制限、無効なプロダクト、ネットワーク障害)、トランザクション検証の失敗、システムエラーです。なお、ユーザーによるキャンセルは `didFinishPurchase` がキャンセル結果として呼び出され、このメソッドはトリガーされません。保留中の支払いについても同様です。 ```swift showLineNumbers title="Swift" func paywallController( _ controller: AdaptyPaywallController, didFailPurchase product: AdaptyPaywallProduct, error: AdaptyError ) { } ``` <Details> <summary>イベント例(クリックして展開)</summary> ```javascript { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "error": { "code": "purchase_failed", "message": "Purchase failed due to insufficient funds", "details": { "underlyingError": "Insufficient funds in account" } } } ``` </Details> オブザーバーモードでは呼び出されません。詳細は [iOS - オブザーバーモードでペイウォールビルダーのペイウォールを表示する](ios-present-paywall-builder-paywalls-in-observer-mode) をご覧ください。 #### Webペイウォールによる購入の失敗 \{#failed-purchase-using-a-web-paywall\} `Adapty.openWebPaywall()` が失敗した場合、このメソッドが呼び出されます: ```swift showLineNumbers title="Swift" func paywallController( _ controller: AdaptyPaywallController, didFailWebPaymentNavigation product: AdaptyPaywallProduct, error: AdaptyError ) { } ``` <Details> <summary>イベント例(クリックして展開)</summary> ```javascript { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "error": { "code": "web_payment_failed", "message": "Web payment navigation failed", "details": { "underlyingError": "Network connection error" } } } ``` </Details> #### 購入の復元に成功した場合 \{#successful-restore\} 購入の復元が成功した場合、このメソッドが呼び出されます: ```swift showLineNumbers title="Swift" func paywallController( _ controller: AdaptyPaywallController, didFinishRestoreWith profile: AdaptyProfile ) { } ``` <Details> <summary>イベントの例(クリックして展開)</summary> ```javascript { "profile": { "accessLevels": { "premium": { "id": "premium", "isActive": true, "expiresAt": "2024-02-15T10:30:00Z" } }, "subscriptions": [ { "vendorProductId": "premium_monthly", "isActive": true, "expiresAt": "2024-02-15T10:30:00Z" } ] } } ``` </Details> 推奨する方法は、必要な `accessLevel` がある場合にスクリーンを閉じることです。確認方法については、[サブスクリプションのステータス](subscription-status)をご参照ください。 #### 復元の失敗 \{#failed-restore\} 購入の復元に失敗した場合、このメソッドが呼び出されます: ```swift showLineNumbers title="Swift" public func paywallController( _ controller: AdaptyPaywallController, didFailRestoreWith error: AdaptyError ) { } ``` <Details> <summary>イベント例(クリックして展開)</summary> ```javascript { "error": { "code": "restore_failed", "message": "Purchase restoration failed", "details": { "underlyingError": "No previous purchases found" } } } ``` </Details> ### データの取得とレンダリング \{#data-fetching-and-rendering\} #### プロダクト読み込みエラー \{#product-loading-errors\} 初期化時にプロダクトの配列を渡さなかった場合、AdaptyUI はサーバーから必要なオブジェクトを自動的に取得します。この操作が失敗した場合、AdaptyUI は以下のメソッドを呼び出してエラーを通知します: ```swift showLineNumbers title="Swift" public func paywallController( _ controller: AdaptyPaywallController, didFailLoadingProductsWith error: AdaptyError ) -> Bool { return true } ``` <Details> <summary>イベント例(クリックして展開)</summary> ```javascript { "error": { "code": "products_loading_failed", "message": "Failed to load products from the server", "details": { "underlyingError": "Network timeout" } } } ``` </Details> `true` を返すと、AdaptyUI は 2 秒後にリクエストを再試行します。 #### レンダリングエラー \{#rendering-errors\} インターフェースのレンダリング中にエラーが発生した場合、このメソッドで通知されます: ```swift showLineNumbers title="Swift" public func paywallController( _ controller: AdaptyPaywallController, didFailRenderingWith error: AdaptyError ) { } ``` <Details> <summary>イベント例(クリックして展開)</summary> ```javascript { "error": { "code": "rendering_failed", "message": "Failed to render paywall interface", "details": { "underlyingError": "Invalid paywall configuration" } } } ``` </Details> 通常、このようなエラーは発生しないはずですので、もし見かけた場合はお知らせください。 </SDKv3> --- # File: ios-use-fallback-paywalls --- --- title: "iOS - フォールバックを使用する" description: "ユーザーがオフラインの場合や Adapty サーバーが利用できない場合の処理方法" --- スムーズなユーザー体験を維持するために、フロー、[ペイウォール](paywalls)、[オンボーディング](onboardings)に[フォールバック](/fallback-paywalls)を設定することが重要です。この対策により、インターネット接続が部分的または完全に失われた場合でも、アプリケーションの機能を維持できます。 * **アプリケーションが Adapty サーバーにアクセスできない場合:** フォールバックのフローまたはペイウォールを表示し、ローカルのオンボーディング設定にアクセスできます。 * **アプリケーションがインターネットにアクセスできない場合:** フォールバックのフローまたはペイウォールを表示できます。オンボーディングはリモートコンテンツを含むため、動作にはインターネット接続が必要です。 :::important このガイドの手順を進める前に、Adapty からフォールバック設定ファイルを[ダウンロード](/local-fallback-paywalls)してください。 ::: ## 設定 \{#configuration\} 1. フォールバック JSON ファイルをプロジェクトバンドルに追加します。XCode で **File** メニューを開き、**Add Files to "YourProjectName"** を選択してください。 2. 対象のフロー、ペイウォール、またはオンボーディングを取得する**前に** `.setFallback` メソッドを呼び出してください。 <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift showLineNumbers do { if let urlPath = Bundle.main.url(forResource: fileName, withExtension: "json") { try await Adapty.setFallback(fileURL: urlPath) } } catch { // handle the error } ``` </TabItem> <TabItem value="swift-callback" label="Swift-Callback" default> ```swift showLineNumbers if let url = Bundle.main.url(forResource: "ios_fallback", withExtension: "json") { Adapty.setFallback(fileURL: url) } ``` </TabItem> </Tabs> パラメーター: | パラメーター | 説明 | | :---------- |:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **fileURL** | フォールバック設定ファイルへのパス。 | --- # File: localizations-and-locale-codes --- --- title: "iOS SDKでローカライゼーションとロケールコードを使用する" description: "iOSアプリでグローバルなユーザーにリーチするために、アプリのローカライゼーションとロケールコードを管理します。" --- ## これが重要な理由 \{#why-this-is-important\} ロケールコードが関係するシナリオはいくつかあります。たとえば、アプリの現在のローカライゼーションに対応する正しいペイウォールを取得しようとする場合などです。 ロケールコードは複雑で、プラットフォームによって異なることがあります。そのため、Adaptyがサポートするすべてのプラットフォームに対して独自の内部標準を設けています。ただし、コードが複雑であるため、サーバーに何を送信しているのか、そして次に何が起こるのかを正確に把握することが重要です。これにより、期待通りの結果を常に受け取ることができます。 ## Adaptyのロケールコード標準 \{#locale-code-standard-at-adapty\} ロケールコードについて、Adaptyはわずかに変更した [BCP 47標準](https://en.wikipedia.org/wiki/IETF_language_tag) を使用しています。各コードはハイフンで区切られた小文字のサブタグで構成されています。例:`en`(英語)、`pt-br`(ポルトガル語(ブラジル))、`zh`(簡体字中国語)、`zh-hant`(繁体字中国語)。 ## ロケールコードのマッチング \{#locale-code-matching\} Adaptyがクライアント側SDKからロケールコード付きの呼び出しを受け取り、ペイウォールの対応するローカライゼーションを検索する際、以下の処理が行われます: 1. 受信したロケール文字列が小文字に変換され、すべてのアンダースコア(`_`)がハイフン(`-`)に置き換えられます 2. 完全に一致するロケールコードのローカライゼーションを検索します 3. 一致するものが見つからない場合、最初のハイフンの前の部分文字列(`pt-br`の場合は`pt`)を取り出し、一致するローカライゼーションを検索します 4. それでも一致するものが見つからない場合、デフォルトの`en`ローカライゼーションを返します これにより、`'pt_BR'`を送信したiOSデバイス、`pt-BR`を送信したAndroidデバイス、`pt-br`を送信した別のデバイスは、すべて同じ結果を受け取ります。 ## ローカライゼーションの実装:推奨方法 \{#implementing-localizations-recommended-way\} ローカライゼーションについて検討しているなら、すでにプロジェクト内のローカライズされた文字列ファイルを扱っているでしょう。その場合、各ローカライゼーションに対応するファイルに、意図したAdaptyロケールコードをキーと値のペアとして配置することをお勧めします。そして、次のようにSDKを呼び出す際にそのキーの値を取得します: ```swift showLineNumbers // 1. Modify your Localizable.strings files /* Localizable.strings - Spanish */ adapty_paywalls_locale = "es"; /* Localizable.strings - Portuguese (Brazil) */ adapty_paywalls_locale = "pt-br"; // 2. Extract and use the locale code let locale = NSLocalizedString("adapty_paywalls_locale", comment: "") // pass locale code to AdaptyUI.getViewConfiguration or Adapty.getPaywall method ``` これにより、アプリのすべてのユーザーに対してどのローカライゼーションが取得されるかを完全にコントロールできます。 ## ローカライゼーションの実装:別の方法 \{#implementing-localizations-the-other-way\} ロケールコードをすべてのローカライゼーションに明示的に定義しなくても、類似した(ただし同一ではない)結果を得ることができます。その場合、プラットフォームが提供する他のオブジェクトからロケールコードを抽出することになります。例: ```swift showLineNumbers let locale = Locale.current.identifier // pass locale code to AdaptyUI.getViewConfiguration or Adapty.getPaywall method ``` いくつかの理由から、このアプローチは推奨しません: 1. iOSでは、優先言語と現在のロケールは同一ではありません。ローカライゼーションを正しく選択したい場合、Appleのロジックに依存するか(ローカライズされた文字列ファイルを使用する推奨アプローチでは自動的に機能します)、それを再現する必要があります。 2. Adaptyのサーバーが何を受け取るかを予測するのが難しいです。たとえばiOSでは、デバイスから`ar_OM@numbers='latn'`のようなロケールを取得してサーバーに送信することがあります。この場合、期待していた`ar-om`ローカライゼーションではなく、`ar`が返ってくる可能性があり、意図しない結果になることがあります。 このアプローチを使用する場合は、関連するすべてのユースケースを網羅していることを確認してください。 --- # File: ios-troubleshoot-paywall-builder --- --- title: "Troubleshoot Paywall Builder in iOS SDK" description: "Troubleshoot Paywall Builder in iOS SDK" --- このガイドでは、iOS SDK でAdapty ペイウォールビルダーを使用して作成したペイウォールに関する一般的な問題の解決方法を説明します。 ## ペイウォール設定の取得に失敗する \{#getting-a-paywall-configuration-fails\} **問題**: `getPaywallConfiguration` メソッドがペイウォール設定を取得できない。 **原因**: ペイウォールビルダーでデバイス表示が有効になっていない。 **解決策**: ペイウォールビルダーの **Show on device** トグルを有効にしてください。 <img src="/assets/shared/img/show-on-device.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## ペイウォールの表示回数が多すぎる \{#the-paywall-view-number-is-too-big\} **問題**: ペイウォールの表示回数が想定の2倍になっている。 **原因**: コード内で `logShowFlow`(iOS SDK v4+)/ `logShowPaywall` を呼び出している可能性があります。ペイウォールビルダーやフロービルダーで作成したペイウォール・フローを使用している場合、アナリティクスは自動的に記録されるため、このメソッドを呼び出すと表示回数が重複します。 **解決策**: ペイウォールビルダーまたはフロービルダーを使用している場合は、コード内で `logShowFlow`(iOS SDK v4+)/ `logShowPaywall` を呼び出していないことを確認してください。 ## その他の問題 \{#other-issues\} **問題**: 上記に該当しないペイウォールビルダー関連の問題が発生している。 **解決策**: 必要に応じて[マイグレーションガイド](ios-sdk-migration-guides)を参照し、SDKを最新バージョンに移行してください。多くの問題は新しいSDKバージョンで修正されています。 --- # File: ios-present-paywall-builder-paywalls-in-observer-mode --- --- title: "iOS SDK のオブザーバーモードでペイウォールビルダーのペイウォールを表示する" description: "オブザーバーモードで PB ペイウォールを表示して詳細なインサイトを得る方法を学びましょう。" --- ペイウォールビルダーを使ってペイウォールをカスタマイズした場合、モバイルアプリのコードでユーザーへの表示処理を別途実装する必要はありません。このようなペイウォールには、表示内容と表示方法の両方が含まれています。 :::warning このセクションは[オブザーバーモード](observer-vs-full-mode)専用です。オブザーバーモードを使用していない場合は、[iOS - ペイウォールビルダーのペイウォールを表示する](ios-present-paywalls)を参照してください。 ::: <SDKv4> <details> <summary>フローの表示を始める前に(クリックして展開)</summary> 1. Adapty と [App Store](initial_ios) の初期連携を設定します。 2. Adapty SDK をインストールして設定します。`observerMode` パラメータを `true` に設定してください。[iOS SDK インストールガイド](sdk-installation-ios#activate-adapty-module-of-adapty-sdk)を参照してください。 3. Adapty ダッシュボードで[プロダクトを作成](create-product)します。 4. [ビルダーでフローまたはペイウォールを設定](create-paywall)し、プロダクトを割り当てます。 5. [プレースメントを作成し、フローまたはペイウォールを割り当て](create-placement)ます。 6. モバイルアプリのコードで[フローとその設定を取得](get-pb-paywalls)します。 </details> <p> </p> <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> 1. `AdaptyObserverModeResolver` オブジェクトを実装します。プロトコルは SDK v3 と同じです。オブザーバーモード自体はフローとペイウォールのレンダリング間で変わりません。 ```swift showLineNumbers title="Swift" func observerMode(didInitiatePurchase product: AdaptyPaywallProduct, onStartPurchase: @escaping () -> Void, onFinishPurchase: @escaping () -> Void) { // use the product object to handle the purchase // call onStartPurchase / onFinishPurchase to notify AdaptyUI about the purchase progress } func observerModeDidInitiateRestorePurchases(onStartRestore: @escaping () -> Void, onFinishRestore: @escaping () -> Void) { // call onStartRestore / onFinishRestore to notify AdaptyUI about the restore progress } ``` 2. `observerModeResolver:` パラメータにリゾルバを渡して、フロー設定オブジェクトを作成します。 ```swift showLineNumbers title="Swift" do { let flowConfiguration = try await AdaptyUI.getFlowConfiguration( forFlow: flow, observerModeResolver: <AdaptyObserverModeResolver> ) } catch { // handle the error } ``` リクエストパラメータ: | パラメータ | 必須/任意 | 説明 | | :----------------------- | :------- | :----------------------------------------------------------------------------------------------------------------------- | | **forFlow** | 必須 | `Adapty.getFlow(placementId:)` で取得した `AdaptyFlow` オブジェクト。[フローとペイウォールの取得](get-pb-paywalls)を参照してください。 | | **observerModeResolver** | 必須 | 上記で実装した `AdaptyObserverModeResolver`。 | 3. `AdaptyUI.flowController(with:delegate:)` を使ってフローコントローラーを初期化します。 ```swift showLineNumbers title="Swift" import AdaptyUI let visualFlow = try AdaptyUI.flowController( with: flowConfiguration, delegate: <AdaptyFlowControllerDelegate> ) ``` リクエストパラメータ: | パラメータ | 必須/任意 | 説明 | | :------------------------- | :------- | :----------------------------------------------------------------------------------------------------------------------------------------------- | | **flowConfiguration** | 必須 | フローのビジュアル詳細を含む `AdaptyUI.FlowConfiguration` オブジェクト。[フローとペイウォールの取得](get-pb-paywalls)を参照してください。 | | **delegate** | 必須 | フローイベントを受け取るための `AdaptyFlowControllerDelegate`。[フロー&ペイウォールイベントの処理](ios-handling-events)を参照してください。 | 返り値: | オブジェクト | 説明 | | :------------------- | :----------------------------------------------------- | | AdaptyFlowController | リクエストされたフロー画面を表すオブジェクト。 | 4. コントローラーを表示します。 ```swift showLineNumbers title="Swift" present(visualFlow, animated: true) ``` :::warning [ペイウォールを購入トランザクションに紐付ける](report-transactions-observer-mode)のを忘れないようにしてください。紐付けを行わないと、Adapty は購入元のペイウォールを特定できません。 ::: </TabItem> <TabItem value="swiftui" label="SwiftUI" default> SwiftUI では、リゾルバを指定してフロー設定を取得し、`.flow` モディファイアに渡します。 ```swift showLineNumbers title="SwiftUI" @State var flowPresented = false @State var flowConfiguration: AdaptyUI.FlowConfiguration? var body: some View { Text("Hello, AdaptyUI!") .flow( isPresented: $flowPresented, flowConfiguration: flowConfiguration, didPerformAction: { action in switch action { case .close: flowPresented = false default: break } }, didFailPurchase: { product, error in /* handle the error */ }, didFinishRestore: { profile in /* check access level and dismiss */ }, didFailRestore: { error in /* handle the error */ }, didReceiveError: { error in flowPresented = false } ) .task { flowConfiguration = try? await AdaptyUI.getFlowConfiguration( forFlow: flow, observerModeResolver: <AdaptyObserverModeResolver> ) } } ``` `getFlowConfiguration` の `observerModeResolver:` パラメータにより、レンダリングされたフローがカスタム購入ロジックに従って動作します。モディファイア自体はフルモードと同じコールバックを使用します。 :::warning [ペイウォールを購入トランザクションに紐付ける](report-transactions-observer-mode)のを忘れないようにしてください。紐付けを行わないと、Adapty は購入元のペイウォールを特定できません。 ::: </TabItem> </Tabs> </SDKv4> <SDKv3> <Tabs groupId="current-os" queryString> <TabItem value="sdk3" label="Paywall Builder (SDK 3.x)" default> <details> <summary>ペイウォールの表示を始める前に(クリックして展開)</summary> 1. Adapty と [Google Play](initial-android) および [App Store](initial_ios) の初期連携を設定します。 2. Adapty SDK をインストールして設定します。`observerMode` パラメータを `true` に設定してください。[iOS](sdk-installation-ios#activate-adapty-module-of-adapty-sdk) のフレームワーク別手順を参照してください。 3. Adapty ダッシュボードで[プロダクトを作成](create-product)します。 4. [ペイウォールを設定してプロダクトを割り当て](create-paywall)、Adapty ダッシュボードのペイウォールビルダーでカスタマイズします。 5. Adapty ダッシュボードで[プレースメントを作成し、ペイウォールを割り当て](create-placement)ます。 6. モバイルアプリのコードで[ペイウォールビルダーのペイウォールとその設定を取得](get-pb-paywalls)します。 </details> <p> </p> <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> 1. `AdaptyObserverModeResolver` オブジェクトを実装します。 ```swift showLineNumbers title="Swift" func observerMode(didInitiatePurchase product: AdaptyPaywallProduct, onStartPurchase: @escaping () -> Void, onFinishPurchase: @escaping () -> Void) { // use the product object to handle the purchase // use the onStartPurchase and onFinishPurchase callbacks to notify AdaptyUI about the process of the purchase } func observerModeDidInitiateRestorePurchases(onStartRestore: @escaping () -> Void, onFinishRestore: @escaping () -> Void) { // use the onStartRestore and onFinishRestore callbacks to notify AdaptyUI about the process of the restore } ``` `observerMode(didInitiatePurchase:onStartPurchase:onFinishPurchase:)` イベントは、ユーザーが購入を開始したことを通知します。このコールバックに応じて、カスタム購入フローをトリガーできます。 `observerModeDidInitiateRestorePurchases(onStartRestore:onFinishRestore:)` イベントは、ユーザーが復元を開始したことを通知します。このコールバックに応じて、カスタム復元フローをトリガーできます。 また、購入または復元の進行状況を AdaptyUI に通知するために、以下のコールバックを呼び出すのを忘れないようにしてください。これはローダーの表示など、ペイウォールの正常な動作に必要です。 | コールバック | 説明 | | :----------------- | :------------------------------------------------------------------------------- | | onStartPurchase() | 購入が開始されたことを AdaptyUI に通知するために呼び出します。 | | onFinishPurchase() | 購入が完了したことを AdaptyUI に通知するために呼び出します。 | | onStartRestore() | 復元が開始されたことを AdaptyUI に通知するために呼び出します。 | | onFinishRestore() | 復元が完了したことを AdaptyUI に通知するために呼び出します。 | 2. ペイウォール設定オブジェクトを作成します。 ```swift showLineNumbers title="Swift" do { let paywallConfiguration = try AdaptyUI.getPaywallConfiguration( forPaywall: <paywall object>, observerModeResolver: <AdaptyObserverModeResolver> ) } catch { // handle the error } ``` リクエストパラメータ: | パラメータ | 必須/任意 | 説明 | | :----------------------- | :------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Paywall** | 必須 | 対象ペイウォールのコントローラーを取得するための `AdaptyPaywall` オブジェクト。 | | **ObserverModeResolver** | 必須 | 前の手順で実装した `AdaptyObserverModeResolver` オブジェクト。 | 3. `.paywallController(for:products:viewConfiguration:delegate:)` メソッドを使って、表示したいビジュアルペイウォールを初期化します。 ```swift showLineNumbers title="Swift" import AdaptyUI let visualPaywall = AdaptyUI.paywallController( with: <paywall configuration object>, delegate: <AdaptyPaywallControllerDelegate> ) ``` リクエストパラメータ: | パラメータ | 必須/任意 | 説明 | | :----------------------- | :------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Paywall Configuration** | 必須 | ペイウォールのビジュアル詳細を含む `AdaptyUI.PaywallConfiguration` オブジェクト。`AdaptyUI.getPaywallConfiguration(forPaywall:locale:)` メソッドを使用してください。詳細は[ペイウォールビルダーのペイウォールと設定の取得](get-pb-paywalls)を参照してください。 | | **Delegate** | 必須 | ペイウォールイベントを受け取るための `AdaptyPaywallControllerDelegate`。詳細は[ペイウォールイベントの処理](ios-handling-events)を参照してください。 | 返り値: | オブジェクト | 説明 | | :---------------------- | :--------------------------------------------------- | | AdaptyPaywallController | リクエストされたペイウォール画面を表すオブジェクト。 | オブジェクトの作成に成功したら、次のように表示できます。 ```swift showLineNumbers title="Swift" present(visualPaywall, animated: true) ``` :::warning [ペイウォールを購入トランザクションに紐付ける](report-transactions-observer-mode)のを忘れないようにしてください。紐付けを行わないと、Adapty は購入元のペイウォールを特定できません。 ::: </TabItem> <TabItem value="swiftui" label="SwiftUI" default> デバイス画面にビジュアルペイウォールを表示するには、SwiftUI で `.paywall` モディファイアを使用します。 ```swift showLineNumbers title="SwiftUI" @State var paywallPresented = false var body: some View { Text("Hello, AdaptyUI!") .paywall( isPresented: $paywallPresented, paywallConfiguration: <paywall configuration object>, didPerformAction: { action in switch action { case .close: paywallPresented = false default: // Handle other actions break } }, didFinishRestore: { profile in /* check access level and dismiss */ }, didFailRestore: { error in /* handle the error */ }, didFailRendering: { error in paywallPresented = false } ) } ``` リクエストパラメータ: | パラメータ | 必須/任意 | 説明 | | :----------------------- | :------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Paywall Configuration** | 必須 | ペイウォールのビジュアル詳細を含む `AdaptyUI.PaywallConfiguration` オブジェクト。`AdaptyUI.getPaywallConfiguration(forPaywall:locale:)` メソッドを使用してください。詳細は[ペイウォールビルダーのペイウォールと設定の取得](get-pb-paywalls)を参照してください。 | | **Products** | 任意 | 画面上のプロダクト表示タイミングを最適化するために `AdaptyPaywallProduct` オブジェクトの配列を指定します。`nil` を渡すと、AdaptyUI が必要なプロダクトを自動的に取得します。 | | **TagResolver** | 任意 | カスタムタグとその解決値の辞書を定義します。カスタムタグはペイウォールコンテンツ内のプレースホルダーとして機能し、ペイウォール内のパーソナライズされたコンテンツ用の特定の文字列に動的に置き換えられます。詳細はペイウォールビルダーのカスタムタグのトピックを参照してください。 | | **ObserverModeResolver** | 任意 | 前の手順で実装した `AdaptyObserverModeResolver` オブジェクト。 | クロージャパラメータ: | クロージャパラメータ | 説明 | | :------------------- | :-------------------------------------------------------------------------------- | | **didFinishRestore** | `Adapty.restorePurchases()` が成功した場合に呼び出されます。 | | **didFailRestore** | `Adapty.restorePurchases()` が失敗した場合に呼び出されます。 | | **didFailRendering** | インターフェースのレンダリング中にエラーが発生した場合に呼び出されます。 | その他のクロージャパラメータについては、[iOS - イベントの処理](ios-handling-events)を参照してください。 :::warning [ペイウォールを購入トランザクションに紐付ける](report-transactions-observer-mode)のを忘れないようにしてください。紐付けを行わないと、Adapty は購入元のペイウォールを特定できません。 ::: </TabItem> </Tabs> </TabItem> <TabItem value="sdk2" label="Legacy Paywall Builder (SDK up to 2.x)" default> <details> <summary>ペイウォールの表示を始める前に(クリックして展開)</summary> 1. Adapty と [Google Play](initial-android) および [App Store](initial_ios) の初期連携を設定します。 1. Adapty SDK をインストールして設定します。`observerMode` パラメータを `true` に設定してください。[iOS](sdk-installation-ios#activate-adapty-module-of-adapty-sdk)、[React Native](sdk-installation-reactnative)、[Flutter](sdk-installation-flutter#activate-adapty-module-of-adapty-sdk)、[Unity](sdk-installation-unity#activate-adapty-module-of-adapty-sdk) のフレームワーク別手順を参照してください。 2. Adapty ダッシュボードで[プロダクトを作成](create-product)します。 3. [ペイウォールを設定してプロダクトを割り当て](create-paywall)、Adapty ダッシュボードのペイウォールビルダーでカスタマイズします。 4. Adapty ダッシュボードで[プレースメントを作成し、ペイウォールを割り当て](create-placement)ます。 5. モバイルアプリのコードで[ペイウォールビルダーのペイウォールとその設定を取得](get-pb-paywalls)します。 </details> <p> </p> <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> 1. `AdaptyObserverModeDelegate` オブジェクトを実装します。 ```swift showLineNumbers title="Swift" func paywallController(_ controller: AdaptyPaywallController, didInitiatePurchase product: AdaptyPaywallProduct, onStartPurchase: @escaping () -> Void, onFinishPurchase: @escaping () -> Void) { // use the product object to handle the purchase // use the onStartPurchase and onFinishPurchase callbacks to notify AdaptyUI about the process of the purchase } ``` `paywallController(_:didInitiatePurchase:onStartPurchase:onFinishPurchase:)` イベントは、ユーザーが購入を開始したことを通知します。このイベントに応じて、カスタム購入フローをトリガーできます。 また、購入の進行状況を AdaptyUI に通知するために、以下のコールバックを呼び出すのを忘れないようにしてください。これはローダーの表示など、ペイウォールの正常な動作に必要です。 | コールバック | 説明 | | :--------------- | :------------------------------------------------------------------------------- | | onStartPurchase | 購入が開始されたことを AdaptyUI に通知するために呼び出します。 | | onFinishPurchase | 購入が完了したことを AdaptyUI に通知するために呼び出します。 | 2. `.paywallController(for:products:viewConfiguration:delegate:observerModeDelegate:)` メソッドを使って、表示したいビジュアルペイウォールを初期化します。 ```swift showLineNumbers title="Swift" import AdaptyUI let visualPaywall = AdaptyUI.paywallController( for: <paywall object>, products: <paywall products array>, viewConfiguration: <LocalizedViewConfiguration>, delegate: <AdaptyPaywallControllerDelegate> observerModeDelegate: <AdaptyObserverModeDelegate> ) ``` リクエストパラメータ: | パラメータ | 必須/任意 | 説明 | | :----------------------- | :------- | :----------------------------------------------------------- | | **Paywall** | 必須 | 対象ペイウォールのコントローラーを取得するための `AdaptyPaywall` オブジェクト。 | | **Products** | 任意 | 画面上のプロダクト表示タイミングを最適化するために `AdaptyPaywallProduct` オブジェクトの配列を指定します。`nil` を渡すと、AdaptyUI が必要なプロダクトを自動的に取得します。 | | **ViewConfiguration** | 必須 | ペイウォールのビジュアル詳細を含む `AdaptyUI.LocalizedViewConfiguration` オブジェクト。`AdaptyUI.getViewConfiguration(paywall:locale:)` メソッドを使用してください。詳細は[ペイウォールビルダーのペイウォールと設定の取得](get-pb-paywalls)を参照してください。 | | **Delegate** | 必須 | ペイウォールイベントを受け取るための `AdaptyPaywallControllerDelegate`。詳細は[ペイウォールイベントの処理](ios-handling-events)を参照してください。 | | **ObserverModeDelegate** | 必須 | 前の手順で実装した `AdaptyObserverModeDelegate` オブジェクト。 | | **TagResolver** | 任意 | カスタムタグとその解決値の辞書を定義します。カスタムタグはペイウォールコンテンツ内のプレースホルダーとして機能し、ペイウォール内のパーソナライズされたコンテンツ用の特定の文字列に動的に置き換えられます。詳細はペイウォールビルダーのカスタムタグのトピックを参照してください。 | 返り値: | オブジェクト | 説明 | | :---------------------- | :--------------------------------------------------- | | AdaptyPaywallController | リクエストされたペイウォール画面を表すオブジェクト。 | オブジェクトの作成に成功したら、次のように表示できます。 ```swift showLineNumbers title="Swift" present(visualPaywall, animated: true) ``` :::warning [ペイウォールを購入トランザクションに紐付ける](report-transactions-observer-mode)のを忘れないようにしてください。紐付けを行わないと、Adapty は購入元のペイウォールを特定できません。 ::: </TabItem> <TabItem value="swiftui" label="SwiftUI" default> デバイス画面にビジュアルペイウォールを表示するには、SwiftUI で `.paywall` モディファイアを使用します。 ```swift showLineNumbers title="SwiftUI" @State var paywallPresented = false var body: some View { Text("Hello, AdaptyUI!") .paywall( isPresented: $paywallPresented, paywall: <paywall object>, configuration: <LocalizedViewConfiguration>, didPerformAction: { action in switch action { case .close: paywallPresented = false default: // Handle other actions break } }, didFinishRestore: { profile in /* check access level and dismiss */ }, didFailRestore: { error in /* handle the error */ }, didFailRendering: { error in paywallPresented = false }, observerModeDidInitiatePurchase: { product, onStartPurchase, onFinishPurchase in // use the product object to handle the purchase // use the onStartPurchase and onFinishPurchase callbacks to notify AdaptyUI about the process of the purchase }, ) } ``` リクエストパラメータ: | パラメータ | 必須/任意 | 説明 | | :---------------- | :------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Paywall** | 必須 | 対象ペイウォールのコントローラーを取得するための `AdaptyPaywall` オブジェクト。 | | **Product** | 任意 | 画面上のプロダクト表示タイミングを最適化するために `AdaptyPaywallProduct` オブジェクトの配列を指定します。`nil` を渡すと、AdaptyUI が必要なプロダクトを自動的に取得します。 | | **Configuration** | 必須 | ペイウォールのビジュアル詳細を含む `AdaptyUI.LocalizedViewConfiguration` オブジェクト。`AdaptyUI.getViewConfiguration(paywall:locale:)` メソッドを使用してください。詳細は[ペイウォールビルダーのペイウォールと設定の取得](get-pb-paywalls)を参照してください。 | | **TagResolver** | 任意 | カスタムタグとその解決値の辞書を定義します。カスタムタグはペイウォールコンテンツ内のプレースホルダーとして機能し、ペイウォール内のパーソナライズされたコンテンツ用の特定の文字列に動的に置き換えられます。詳細はペイウォールビルダーのカスタムタグのトピックを参照してください。 | クロージャパラメータ: | クロージャパラメータ | 説明 | | :---------------------------------- | :-------------------------------------------------------------------------------- | | **didFinishRestore** | `Adapty.restorePurchases()` が成功した場合に呼び出されます。 | | **didFailRestore** | `Adapty.restorePurchases()` が失敗した場合に呼び出されます。 | | **didFailRendering** | インターフェースのレンダリング中にエラーが発生した場合に呼び出されます。 | | **observerModeDidInitiatePurchase** | ユーザーが購入を開始したときに呼び出されます。 | その他のクロージャパラメータについては、[iOS - イベントの処理](ios-handling-events)を参照してください。 :::warning [ペイウォールを購入トランザクションに紐付ける](report-transactions-observer-mode)のを忘れないようにしてください。紐付けを行わないと、Adapty は購入元のペイウォールを特定できません。 ::: </TabItem> </Tabs> </TabItem> </Tabs> </SDKv3> --- # File: ios-quickstart-manual --- --- title: "iOS SDKのカスタムペイウォールで購入を有効にする" description: "Adapty SDKをカスタムiOSペイウォールに統合してアプリ内課金を有効にします。" --- このガイドでは、Adaptyをカスタムペイウォールに統合する方法を説明します。ペイウォールの実装を完全にコントロールしながら、Adapty SDKがプロダクトの取得、新規購入の処理、過去の購入の復元を行います。 :::important **このガイドはカスタムペイウォールを実装する開発者向けです。** 購入を最も簡単に有効にしたい場合は、[Adapty フローBuilder](ios-quickstart-paywalls)を使用してください。フローBuilderを使えば、ノーコードのビジュアルエディターでフローを作成でき、Adaptyが購入ロジックをすべて自動的に処理します。アプリを再公開せずにさまざまなデザインをテストできます。 ::: ## 始める前に \{#before-you-start\} ### プロダクトのセットアップ \{#set-up-products\} アプリ内課金を有効にするには、3つの重要な概念を理解する必要があります: - [**プロダクト**](product) – ユーザーが購入できるもの(サブスクリプション、消耗型アイテム、永続アクセス) - [**ペイウォール**](paywalls) – どのプロダクトを提供するかを定義する設定。Adaptyでは、プロダクトを取得する唯一の方法がペイウォールですが、この設計によりアプリコードを変更せずにプロダクト、価格、オファーを変更できます。 - [**プレースメント**](placements) – アプリ内でペイウォールを表示する場所とタイミング(`main`、`onboarding`、`settings`など)。ダッシュボードでプレースメントにペイウォールを設定し、コード内でプレースメントIDを使ってリクエストします。これにより、A/B テストの実施やユーザーごとに異なるペイウォールの表示が簡単になります。 カスタムペイウォールを使用する場合でも、これらの概念を理解しておくことが重要です。基本的に、アプリで販売するプロダクトを管理するための仕組みです。 カスタムペイウォールを実装するには、**ペイウォール**を作成して**プレースメント**に追加する必要があります。この設定によりプロダクトを取得できるようになります。ダッシュボードで何をする必要があるかを理解するには、[こちら](quickstart)のクイックスタートガイドに従ってください。 ### ユーザーの管理 \{#manage-users\} バックエンド認証の有無にかかわらず作業できます。 ただし、Adapty SDKは匿名ユーザーと識別済みユーザーを異なる方法で処理します。[識別クイックスタートガイド](ios-quickstart-identify)を読んで、その詳細を理解し、ユーザーを適切に処理していることを確認してください。 ## ステップ1. プロダクトを取得する \{#step-1-get-products\} カスタムペイウォール用のプロダクトを取得するには、次の手順が必要です: 1. `getFlow`メソッドに[プレースメント](placements)IDを渡して`flow`オブジェクトを取得します。 2. `getPaywallProducts`メソッドを使ってこのフローのプロダクト配列を取得します。 <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift func loadPaywall() async { do { let flow = try await Adapty.getFlow(placementId: "YOUR_PLACEMENT_ID") let products = try await Adapty.getPaywallProducts(flow: flow) // Use products to build your custom paywall UI } catch { // Handle the error } } ``` </TabItem> <TabItem value="swift-callback" label="Swift-Callback" default> ```swift func loadPaywall() { Adapty.getFlow(placementId: "YOUR_PLACEMENT_ID") { result in switch result { case let .success(flow): Adapty.getPaywallProducts(flow: flow) { result in switch result { case let .success(products): // Use products to build your custom paywall UI case let .failure(error): // Handle the error } } case let .failure(error): // Handle the error } } } ``` </TabItem> </Tabs> ## ステップ2. 購入を受け付ける \{#step-2-accept-purchases\} ユーザーがカスタムペイウォールのプロダクトをタップしたら、選択したプロダクトを引数に`makePurchase`メソッドを呼び出します。これにより購入フローが処理され、更新されたプロファイルが返されます。 <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift func purchaseProduct(_ product: AdaptyPaywallProduct) async { do { let purchaseResult = try await Adapty.makePurchase(product: product) switch purchaseResult { case .userCancelled: // User canceled the purchase break case .pending: // Purchase is pending (e.g., awaiting parental approval) break case let .success(profile, transaction): // Purchase successful, profile updated break } } catch { // Handle the error } } ``` </TabItem> <TabItem value="swift-callback" label="Swift-Callback" default> ```swift func purchaseProduct(_ product: AdaptyPaywallProduct) { Adapty.makePurchase(product: product) { result in switch result { case let .success(purchaseResult): switch purchaseResult { case .userCancelled: // User canceled the purchase break case .pending: // Purchase is pending (e.g., awaiting parental approval) break case let .success(profile, transaction): // Purchase successful, profile updated break } case let .failure(error): // Handle the error } } } ``` </TabItem> </Tabs> ## ステップ3. 購入を復元する \{#step-3-restore-purchases\} Appleは、サブスクリプションのあるすべてのアプリに対して、ユーザーが購入を復元できる手段を提供することを求めています。Apple IDでログインした際に購入は自動的に復元されますが、それでもアプリに復元ボタンを実装する必要があります。 ユーザーが復元ボタンをタップしたら`restorePurchases`メソッドを呼び出します。これにより購入履歴がAdaptyと同期され、更新されたプロファイルが返されます。 <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift func restorePurchases() async { do { let profile = try await Adapty.restorePurchases() // Restore successful, profile updated } catch { // Handle the error } } ``` </TabItem> <TabItem value="swift-callback" label="Swift-Callback" default> ```swift func restorePurchases() { Adapty.restorePurchases { result in switch result { case let .success(profile): // Restore successful, profile updated case let .failure(error): // Handle the error } } } ``` </TabItem> </Tabs> ## 次のステップ \{#next-steps\} --- no_index: true --- import Callout from '../../../components/Callout.astro'; <Callout type="tip"> ご質問やお困りのことがあれば、[サポートフォーラム](https://adapty.featurebase.app/)をご覧ください。よくある質問への回答を見つけたり、ご自身の質問を投稿することができます。チームとコミュニティがサポートいたします! </Callout> ペイウォールはアプリに表示する準備ができました。[サンドボックスモードで購入をテスト](test-purchases-in-sandbox)して、ペイウォールからテスト購入を完了できることを確認してください。 次に、[ユーザーが購入を完了したかどうかを確認](ios-check-subscription-status)して、ペイウォールを表示するか有料機能へのアクセスを許可するかを判断してください。 --- # File: fetch-paywalls-and-products --- --- title: "iOS SDKでリモートコンフィグペイウォールのペイウォールとプロダクトを取得する" description: "AdaptyのiOS SDKでペイウォールとプロダクトを取得し、ユーザーの収益化を向上させます。" --- <SDKv4> リモートコンフィグやカスタムペイウォールを表示する前に、それらの情報を取得する必要があります。このトピックはリモートコンフィグとカスタムペイウォールに関するものです。**Flow Builder** または **Paywall Builder** でカスタマイズされたフローやペイウォールの取得方法については、<InlineTooltip tooltip="フローとペイウォールのアプリ内での取得方法に関するガイド">[iOS](get-pb-paywalls)、[Android](android-get-pb-paywalls)、[React Native](react-native-get-pb-paywalls)、[Flutter](flutter-get-pb-paywalls)、および [Unity](unity-get-pb-paywalls)</InlineTooltip>をご覧ください。 :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: <details> <summary>モバイルアプリでフローとプロダクトの取得を開始する前に(クリックして展開)</summary> 1. Adapty ダッシュボードで[プロダクトを作成](create-product)する。 2. Adapty ダッシュボードで[フローまたはペイウォールを作成し、プロダクトを組み込む](create-paywall)。 3. Adapty ダッシュボードで[プレースメントを作成し、フローまたはペイウォールをプレースメントに組み込む](create-placement)。 4. モバイルアプリに[Adapty SDK をインストール](sdk-installation-ios)する。 </details> ## フローの情報を取得する \{#fetch-flow-information\} Adapty では、[プロダクト](product)は App Store と Google Play 両方のプロダクトを組み合わせたものです。これらのクロスプラットフォームプロダクトはフローやペイウォールに統合され、モバイルアプリの特定のプレースメントに表示できます。 プロダクトを表示するには、`getFlow` メソッドを使って[プレースメント](placements)のいずれかから `AdaptyFlow` を取得する必要があります。 :::important **プロダクトIDをハードコードしないでください。** ハードコードすべきIDはプレースメントIDのみです。フローはリモートで設定されるため、プロダクトの数や利用可能なオファーはいつでも変更される可能性があります。アプリはこれらの変更を動的に処理する必要があります。つまり、今日フローが2つのプロダクトを返し、明日3つを返す場合でも、コードを変更せずにすべてを表示できなければなりません。 ::: <Tabs group="current-os"> <TabItem value="swift" label="Swift"> ```swift showLineNumbers do { let flow = try await Adapty.getFlow(placementId: "YOUR_PLACEMENT_ID") // the requested flow } catch { // handle the error } ``` </TabItem> <TabItem value="callback" label="Swift-Callback"> ```swift showLineNumbers Adapty.getFlow(placementId: "YOUR_PLACEMENT_ID") { result in switch result { case let .success(flow): // the requested flow case let .failure(error): // handle the error } } ``` </TabItem> </Tabs> | パラメーター | 必須/任意 | 説明 | |---------|--------|-----------| | **placementId** | 必須 | [プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **fetchPolicy** | デフォルト: `.reloadRevalidatingCacheData` | <p>デフォルトでは、SDK はサーバーからデータの読み込みを試み、失敗した場合はキャッシュされたデータを返します。この設定を推奨します。ユーザーが常に最新のデータを取得できるためです。</p><p></p><p>ただし、ユーザーのインターネット接続が不安定な場合は、`.returnCacheDataElseLoad` を使用することを検討してください。キャッシュが存在する場合はキャッシュデータを返します。この場合、最新データが得られないことがありますが、接続状況にかかわらず読み込みが速くなります。キャッシュは定期的に更新されるため、セッション中にネットワークリクエストを避けるために活用しても安全です。</p><p></p><p>キャッシュはアプリの再起動後も保持され、アプリの再インストール時または手動でクリアした場合にのみ削除されます。</p><p></p><p>Adapty SDK はフローとペイウォールを 2 つのレイヤーで保存しています。上記の定期更新されるキャッシュと[フォールバックペイウォール](fallback-paywalls)です。また、フローとペイウォールをより速く取得するために CDN を使用し、CDN が利用できない場合に備えてスタンドアロンのフォールバックサーバーも用意しています。</p> | | **loadTimeout** | デフォルト: 5 秒 | <p>このメソッドのタイムアウト上限を設定します。タイムアウトに達した場合、キャッシュデータまたはローカルフォールバックが返されます。</p><p></p><p>まれに、内部で複数のリクエストが行われるため、`loadTimeout` で指定した時間よりわずかに遅れてタイムアウトする場合があります。</p> | :::note v4 では、`locale` パラメータは `getFlow` から移動し、`getFlowConfiguration`(AdaptyUI でレンダリングする場合のみ使用)に設定するようになりました。カスタムペイウォールの場合、利用可能なすべてのロケールは `flow.remoteConfigs` にまとめて返されるため、ユーザーのデバイスまたはアプリの設定に合ったロケールを選んでください。 ::: プロダクトIDをハードコードしないでください!フローはリモートで設定されるため、利用可能なプロダクト、プロダクトの数、特典(無料トライアルなど)は随時変更される可能性があります。こうしたシナリオに対応できるようコードを作成してください。 たとえば、最初に2つのプロダクトを取得した場合、アプリはそれら2つを表示します。しかし後に3つのプロダクトを取得した場合は、コードを変更することなく3つすべてを表示できる必要があります。ハードコードが必要なのはプレースメントIDだけです。 レスポンスパラメーター: | パラメーター | 説明 | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- | | Flow | `AdaptyFlow` オブジェクト。プレースメント、識別子(`id`、`variationId`)、名前、設定済みロケールごとのエントリを含む `remoteConfigs` 配列、および `hasViewConfiguration` フラグを保持します。フローのプロダクトを取得するには `getPaywallProducts(flow:)` を呼び出してください。 | ## プロダクトを取得する \{#fetch-products\} フローを取得したら、そのフローに対応するプロダクトの配列を取得できます: <Tabs group="current-os"> <TabItem value="swift" label="Swift"> ```swift showLineNumbers do { let products = try await Adapty.getPaywallProducts(flow: flow) // the requested products array } catch { // handle the error } ``` </TabItem> <TabItem value="callback" label="Swift-Callback"> ```swift showLineNumbers Adapty.getPaywallProducts(flow: flow) { result in switch result { case let .success(products): // the requested products array case let .failure(error): // handle the error } } ``` </TabItem> </Tabs> レスポンスパラメーター: | パラメータ | 説明 | | :-------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Products | [`AdaptyPaywallProduct`](https://swift.adapty.io/documentation/adapty/adaptypaywallproduct) オブジェクトのリスト。プロダクト識別子、プロダクト名、価格、通貨、サブスクリプション期間、その他いくつかのプロパティを含みます。 | 独自のペイウォールデザインを実装する場合、[`AdaptyPaywallProduct`](https://swift.adapty.io/documentation/adapty/adaptypaywallproduct) オブジェクトから以下のプロパティにアクセスする必要があります。よく使われるプロパティを以下に示しますが、利用可能なすべてのプロパティの詳細については、リンク先のドキュメントを参照してください。 | プロパティ | 説明 | |---|---| | **Title** | プロダクトのタイトルを表示するには、`product.localizedTitle` を使用してください。ローカライズはデバイスのロケールではなく、ユーザーが選択したストアの国に基づきます。 | | **Price** | ローカライズされた価格を表示するには、`product.localizedPrice` を使用してください。このローカライズはデバイスのロケール情報に基づきます。また、`product.price` で価格を数値として取得することもできます。値はローカル通貨で提供されます。対応する通貨記号を取得するには、`product.currencySymbol` を使用してください。 | | **Subscription Period** | 期間(週、月、年など)を表示するには、`product.localizedSubscriptionPeriod` を使用してください。このローカライズはデバイスのロケールに基づきます。サブスクリプション期間をプログラムで取得するには、`product.subscriptionPeriod` を使用してください。そこから `unit` 列挙型にアクセスして期間の長さ(day、week、month、year、または unknown)を取得できます。`numberOfUnits` の値で期間単位の数を取得できます。たとえば、四半期ごとのサブスクリプションの場合、`unit` プロパティには `.month`、`numberOfUnits` プロパティには `3` が表示されます。 | | **Introductory Offer** | サブスクリプションに初回オファーが含まれていることを示すバッジやインジケーターを表示するには、`product.subscriptionOffer` プロパティを確認してください。このオブジェクトには以下の便利なプロパティがあります:<br/>• `offerType`:`introductory`、`promotional`、`winBack` の値を持つ列挙型。無料トライアルや初期割引サブスクリプションは `introductory` タイプになります。<br/>• `price`:割引価格を数値で表したもの。無料トライアルの場合は `0` を確認してください。<br/>• `localizedPrice`:ユーザーのロケールに合わせてフォーマットされた割引価格。<br/>• `localizedNumberOfPeriods`:オファーの期間をデバイスのロケールでローカライズした文字列。たとえば、3日間のトライアルオファーの場合、このフィールドには `3 days` と表示されます。<br/>• `subscriptionPeriod`:オファー期間の個別の詳細はこのプロパティで取得することもできます。オファーに対してもサブスクリプション期間と同様に機能します。<br/>• `localizedSubscriptionPeriod`:ユーザーのロケールに合わせてフォーマットされた割引のサブスクリプション期間。 | :::note v4では、`getPaywallProducts(flow:)` が返すすべてのプロダクトにオファーの適格性情報が含まれています。v3にあった `getPaywallProductsWithoutDeterminingOffer` の個別呼び出しは削除されました。 ::: ## デフォルトオーディエンスフローでフロー取得を高速化する \{#speed-up-flow-fetching-with-default-audience-flow\} 通常、フローはほぼ瞬時に取得されるため、この処理を高速化することを特に気にする必要はありません。ただし、オーディエンスやプレースメントが多数あり、ユーザーのインターネット接続が不安定な場合、フローの取得に想定以上の時間がかかることがあります。そのような状況では、何も表示しないよりもデフォルトフローを表示して、スムーズなユーザー体験を確保したい場合があるでしょう。 これに対処するには、`getFlowForDefaultAudience` メソッドを使用できます。このメソッドは、指定されたプレースメントの **All Users** オーディエンス向けのフローを取得します。ただし、推奨されるアプローチは `getFlow` メソッドを使用してフローを取得することである点を理解しておくことが重要です。詳細は上記の[フロー情報の取得](fetch-paywalls-and-products#fetch-flow-information)セクションを参照してください。 :::warning `getFlow` の使用を推奨する理由 `getFlowForDefaultAudience` メソッドにはいくつかの重大な欠点があります: - **後方互換性の問題**: 現在のバージョンと将来のバージョンで異なるフローを表示する必要がある場合、課題に直面する可能性があります。現在の(レガシー)バージョンに対応したフローを設計するか、現在の(レガシー)バージョンのユーザーがレンダリングされないフローで問題に遭遇することを許容するかのどちらかになります。 - **ターゲティングの喪失**: すべてのユーザーが **All Users** オーディエンス向けに設計された同じフローを見ることになるため、パーソナライズされたターゲティング(国、マーケティングアトリビューション、独自のカスタム属性に基づくターゲティングを含む)が失われます。 これらのデメリットを受け入れてでもフローの取得を高速化したい場合は、以下のように `getFlowForDefaultAudience` メソッドを使用してください。それ以外の場合は、[上記](fetch-paywalls-and-products#fetch-flow-information)の `getFlow` を使用してください。 ::: <Tabs group="current-os"> <TabItem value="swift" label="Swift"> ```swift showLineNumbers do { let flow = try await Adapty.getFlowForDefaultAudience(placementId: "YOUR_PLACEMENT_ID") // the requested flow } catch { // handle the error } ``` </TabItem> <TabItem value="callback" label="Swift-Callback"> ```swift showLineNumbers Adapty.getFlowForDefaultAudience(placementId: "YOUR_PLACEMENT_ID") { result in switch result { case let .success(flow): // the requested flow case let .failure(error): // handle the error } } ``` </TabItem> </Tabs> | パラメータ | 必須/任意 | 説明 | |---------|--------|-----------| | **placementId** | 必須 | [プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **fetchPolicy** | デフォルト: `.reloadRevalidatingCacheData` | <p>デフォルトでは、SDK はサーバーからデータを読み込もうとし、失敗した場合はキャッシュされたデータを返します。この方式はユーザーが常に最新のデータを取得できるため、推奨しています。</p><p></p><p>ただし、ユーザーがネットワークの不安定な環境にいると想定される場合は、`.returnCacheDataElseLoad` の使用を検討してください。キャッシュが存在する場合はキャッシュされたデータを返します。この場合、最新のデータが届かない可能性はありますが、ネットワーク状況に関わらず読み込みが速くなります。キャッシュは定期的に更新されるため、セッション中にネットワークリクエストを避けるために活用しても安全です。</p><p></p><p>なお、キャッシュはアプリを再起動しても保持され、アプリのアンインストール時または手動でクリアした場合にのみ削除されます。</p> | </SDKv4> <SDKv3> リモートコンフィグとカスタムペイウォールを表示する前に、それらに関する情報を取得する必要があります。このトピックはリモートコンフィグとカスタムペイウォールに関するものです。ペイウォールビルダーでカスタマイズされたペイウォールの取得方法については、<InlineTooltip tooltip="アプリでペイウォールビルダーのペイウォールを取得するガイド">[iOS](get-pb-paywalls)、[Android](android-get-pb-paywalls)、[React Native](react-native-get-pb-paywalls)、[Flutter](flutter-get-pb-paywalls)、[Unity](unity-get-pb-paywalls)</InlineTooltip>を参照してください。 :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: <details> <summary>モバイルアプリでペイウォールとプロダクトの取得を開始する前に(クリックして展開)</summary> 1. Adapty ダッシュボードで[プロダクトを作成](create-product)してください。 2. Adapty ダッシュボードで[ペイウォールを作成し、プロダクトをペイウォールに追加](create-paywall)してください。 3. Adapty ダッシュボードで[プレースメントを作成し、ペイウォールをプレースメントに追加](create-placement)してください。 4. モバイルアプリに [Adapty SDK をインストール](sdk-installation-ios)してください。 </details> ## ペイウォール情報の取得 \{#fetch-paywall-information\} Adapty では、[プロダクト](product)はApp StoreとGoogle Playの両方のプロダクトを組み合わせたものです。これらのクロスプラットフォームプロダクトはペイウォールに統合されており、モバイルアプリの特定のプレースメントで表示できます。 プロダクトを表示するには、`getPaywall` メソッドを使って[プレースメント](placements)のいずれかから[ペイウォール](paywalls)を取得する必要があります。 :::important **プロダクト ID をハードコードしないでください。** ハードコードするのはプレースメント ID のみにしてください。ペイウォールはリモートで設定されるため、プロダクトの数や利用可能なオファーはいつでも変わる可能性があります。アプリはこれらの変更に動的に対応する必要があります。今日は 2 つのプロダクトを返すペイウォールが明日は 3 つを返すことになっても、コードを変更せずにすべて表示できるようにしてください。 ::: <Tabs group="current-os"> <TabItem value="swift" label="Swift"> ```swift showLineNumbers do { let paywall = try await Adapty.getPaywall(placementId: "YOUR_PLACEMENT_ID") // the requested paywall } catch { // handle the error } ``` </TabItem> <TabItem value="callback" label="Swift-Callback"> ```swift showLineNumbers Adapty.getPaywall(placementId: "YOUR_PLACEMENT_ID", locale: "en") { result in switch result { case let .success(paywall): // the requested paywall case let .failure(error): // handle the error } } ``` </TabItem> </Tabs> | パラメーター | 必須/任意 | 説明 | |---------|--------|-----------| | **placementId** | 必須 | [プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** | <p>任意</p><p>デフォルト: `en`</p> | <p>[ペイウォールのローカライズ](add-remote-config-locale)の識別子。このパラメーターは、マイナス(**-**)文字で区切られた1つ以上のサブタグで構成される言語コードである必要があります。最初のサブタグは言語を表し、2番目のサブタグは地域を表します。</p><p></p><p>例: `en` は英語、`pt-br` はブラジルポルトガル語を表します。</p><p></p><p>ロケールコードの詳細とその推奨される使用方法については、[ローカライズとロケールコード](localizations-and-locale-codes)を参照してください。</p> | | **fetchPolicy** | デフォルト: `.reloadRevalidatingCacheData` | <p>デフォルトでは、SDK はサーバーからデータを読み込もうとし、失敗した場合はキャッシュされたデータを返します。この方法を推奨します。ユーザーが常に最新のデータを取得できるからです。</p><p></p><p>ただし、ユーザーが不安定なインターネット環境を使用していると思われる場合は、`.returnCacheDataElseLoad` を使用してキャッシュデータが存在すればそれを返すことを検討してください。この場合、ユーザーは最新のデータを取得できないことがありますが、インターネット接続が不安定な場合でも読み込み時間が短縮されます。キャッシュは定期的に更新されるため、ネットワークリクエストを避けるためにセッション中に使用しても安全です。</p><p></p><p>キャッシュはアプリを再起動しても保持され、アプリの再インストールまたは手動でのクリーンアップによってのみ消去されます。</p><p></p><p>Adapty SDK はペイウォールを2つの層に保存します:上記の定期的に更新されるキャッシュと[フォールバックペイウォール](fallback-paywalls)です。また、ペイウォールをより速く取得するために CDN を使用し、CDN が到達不能な場合に備えてスタンドアローンのフォールバックサーバーも使用しています。このシステムは、インターネット接続が限られている状況でも信頼性を確保しながら、常に最新バージョンのペイウォールを取得できるように設計されています。</p> | | **loadTimeout** | デフォルト: 5秒 | <p>このメソッドのタイムアウト上限を設定します。タイムアウトに達した場合、キャッシュされたデータまたはローカルのフォールバックが返されます。</p><p></p><p>まれに、このメソッドが `loadTimeout` で指定した時間よりもわずかに遅くタイムアウトすることがあります。これは、処理内部で複数のリクエストが実行される場合があるためです。</p> | プロダクトIDをハードコードしないでください!ペイウォールはリモートで設定されるため、利用可能なプロダクト、プロダクト数、特典(無料トライアルなど)は随時変更される可能性があります。これらのシナリオに対応できるよう、コードを実装してください。 たとえば、最初に2つのプロダクトを取得した場合、アプリはその2つのプロダクトを表示する必要があります。その後3つのプロダクトを取得した場合は、コードを変更することなく3つすべてを表示できなければなりません。ハードコードが必要なのはプレースメントIDのみです。 レスポンスのパラメーター: | パラメーター | 説明 | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- | | Paywall | プロダクトIDのリスト、ペイウォールの識別子、リモートコンフィグなどのプロパティを含む [`AdaptyPaywall`](https://swift.adapty.io/documentation/adapty/adaptypaywall) オブジェクト。 | ## プロダクトを取得する \{#fetch-products\} ペイウォールを取得したら、それに対応するプロダクトの配列をクエリできます: <Tabs group="current-os"> <TabItem value="swift" label="Swift"> ```swift showLineNumbers do { let products = try await Adapty.getPaywallProducts(paywall: paywall) // the requested products array } catch { // handle the error } ``` </TabItem> <TabItem value="callback" label="Swift-Callback"> ```swift showLineNumbers Adapty.getPaywallProducts(paywall: paywall) { result in switch result { case let .success(products): // 取得したプロダクトの配列 case let .failure(error): // エラーを処理する } } ``` </TabItem> </Tabs> レスポンスパラメーター: | パラメータ | 説明 | | :-------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Products | [`AdaptyPaywallProduct`](https://swift.adapty.io/documentation/adapty/adaptypaywallproduct) オブジェクトのリストで、プロダクト識別子、プロダクト名、価格、通貨、サブスクリプション期間、その他のプロパティを含みます。 | 独自のペイウォールデザインを実装する際、[`AdaptyPaywallProduct`](https://swift.adapty.io/documentation/adapty/adaptypaywallproduct) オブジェクトから以下のプロパティにアクセスする必要があります。以下によく使われるプロパティを示しますが、利用可能なすべてのプロパティの詳細はリンク先のドキュメントを参照してください。 | プロパティ | 説明 | |-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **タイトル** | プロダクトのタイトルを表示するには、`product.localizedTitle` を使用します。ローカライズはデバイスのロケールではなく、ユーザーが選択したストアの国に基づいて行われます。 | | **価格** | ローカライズされた価格を表示するには、`product.localizedPrice` を使用します。このローカライズはデバイスのロケール情報に基づいています。`product.price` を使用すると価格を数値として取得することもできます。値はローカル通貨で提供されます。対応する通貨記号を取得するには、`product.currencySymbol` を使用します。 | | **サブスクリプション期間** | 期間(週、月、年など)を表示するには、`product.localizedSubscriptionPeriod` を使用します。このローカライズはデバイスのロケールに基づいています。サブスクリプション期間をプログラムで取得するには、`product.subscriptionPeriod` を使用します。そこから `unit` 列挙型にアクセスして長さ(day、week、month、year、または unknown)を取得できます。`numberOfUnits` の値は期間単位の数を返します。たとえば四半期サブスクリプションの場合、unit プロパティには `.month`、numberOfUnits プロパティには `3` が表示されます。 | | **初回オファー** | サブスクリプションに初回オファーが含まれているかをバッジなどで表示するには、`product.subscriptionOffer` プロパティを確認します。このオブジェクト内には以下の便利なプロパティが含まれています。<br/>• `offerType`: `introductory`、`promotional`、`winBack` の値を持つ列挙型。無料トライアルや初期割引サブスクリプションは `introductory` タイプになります。<br/>• `price`: 割引後の価格(数値)。無料トライアルの場合は `0` になります。<br/>• `localizedPrice`: ユーザーのロケールに合わせてフォーマットされた割引価格。<br/>• `localizedNumberOfPeriods`: オファーの期間をデバイスのロケールでローカライズした文字列。たとえば3日間のトライアルオファーの場合、このフィールドには `3 days` と表示されます。<br/>• `subscriptionPeriod`: オファー期間の詳細を個別に取得する場合はこのプロパティを使用します。前のセクションで説明したのと同じ方法でオファーに対しても機能します。<br/>• `localizedSubscriptionPeriod`: ユーザーのロケールに合わせてフォーマットされた割引のサブスクリプション期間。 | ## iOS での初回オファー適格性の確認 \{#check-intro-offer-eligibility-on-ios\} デフォルトでは、`getPaywallProducts` メソッドが初回オファー、プロモーションオファー、ウィンバックオファーの適格性を確認します。SDK がオファーの適格性を判定する前にプロダクトを表示する必要がある場合は、代わりに `getPaywallProductsWithoutDeterminingOffer` メソッドを使用してください。 :::note 初期プロダクトを表示した後は、必ず通常の `getPaywallProducts` メソッドを呼び出して、正確なオファー適格性情報でプロダクトを更新してください。 ::: <Tabs group="current-os"> <TabItem value="swift" label="Swift"> ```swift showLineNumbers do { let products = try await Adapty.getPaywallProductsWithoutDeterminingOffer(paywall: paywall) // the requested products array without subscriptionOffer } catch { // handle the error } ``` </TabItem> <TabItem value="callback" label="Swift-Callback"> ```swift showLineNumbers Adapty.getPaywallProductsWithoutDeterminingOffer(paywall: paywall) { result in switch result { case let .success(products): // subscriptionOfferなしでリクエストしたプロダクト配列 case let .failure(error): // エラーを処理する } } ``` </TabItem> </Tabs> ## デフォルトオーディエンスのペイウォールでペイウォールの取得を高速化する \{#speed-up-paywall-fetching-with-default-audience-paywall\} 通常、ペイウォールはほぼ瞬時に取得されるため、このプロセスを高速化することを特に意識する必要はありません。しかし、オーディエンスやペイウォールの数が多く、ユーザーのインターネット接続が不安定な場合、ペイウォールの取得に想定以上の時間がかかることがあります。そのような状況では、ペイウォールをまったく表示しないよりも、デフォルトのペイウォールを表示してスムーズなユーザー体験を提供したい場合があるでしょう。 この問題を解決するために、`getPaywallForDefaultAudience` メソッドを使用できます。このメソッドは、指定されたプレースメントの **All Users** オーディエンス向けペイウォールを取得します。ただし、推奨されるアプローチは `getPaywall` メソッドでペイウォールを取得することであり、詳細は上記の[ペイウォール情報の取得](fetch-paywalls-and-products#fetch-paywall-information)セクションをご覧ください。 :::warning `getPaywall` を推奨する理由 `getPaywallForDefaultAudience` メソッドにはいくつかの重大な欠点があります: - **後方互換性の問題**: 異なるアプリバージョン(現行バージョンと将来のバージョン)で異なるペイウォールを表示する必要がある場合、課題が生じることがあります。現行(レガシー)バージョンに対応したペイウォールを設計するか、現行(レガシー)バージョンのユーザーがペイウォールを正しく表示できないリスクを受け入れるかのどちらかになります。 - **ターゲティングの喪失**: すべてのユーザーが **All Users** オーディエンス向けに設計された同じペイウォールを見ることになるため、パーソナライズされたターゲティング(国、マーケティングアトリビューション、カスタム属性に基づくものを含む)が失われます。 これらのデメリットを許容してでもペイウォールの取得を高速化したい場合は、以下のように `getPaywallForDefaultAudience` メソッドを使用してください。そうでない場合は、[上記](fetch-paywalls-and-products#fetch-paywall-information)で説明した `getPaywall` を使用してください。 ::: <Tabs group="current-os"> <TabItem value="swift" label="Swift"> ```swift showLineNumbers do { let paywall = try await Adapty.getPaywallForDefaultAudience("YOUR_PLACEMENT_ID") // the requested paywall } catch { // handle the error } ``` </TabItem> <TabItem value="callback" label="Swift-Callback"> ```swift showLineNumbers Adapty.getPaywallForDefaultAudience(placementId: "YOUR_PLACEMENT_ID", locale: "en") { result in switch result { case let .success(paywall): // the requested paywall case let .failure(error): // handle the error } } ``` </TabItem> </Tabs> :::note `getPaywallForDefaultAudience` メソッドは iOS SDK バージョン 2.11.2 以降で利用できます。 ::: | パラメータ | 必須/任意 | 説明 | |---------|--------|-----------| | **placementId** | 必須 | [プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** | <p>任意</p><p>デフォルト: `en`</p> | <p>[ペイウォールのローカライズ](add-remote-config-locale)の識別子。このパラメータは、マイナス(**-**)文字で区切られた1つ以上のサブタグで構成される言語コードです。最初のサブタグは言語、2番目は地域を表します。</p><p></p><p>例: `en` は英語、`pt-br` はブラジルポルトガル語を表します。</p><p></p><p>ロケールコードと推奨される使い方については、[ローカライズとロケールコード](localizations-and-locale-codes)を参照してください。</p> | | **fetchPolicy** | デフォルト: `.reloadRevalidatingCacheData` | <p>デフォルトでは、SDK はサーバーからデータの読み込みを試み、失敗した場合はキャッシュされたデータを返します。ユーザーが常に最新のデータを受け取れるため、この設定を推奨します。</p><p></p><p>ただし、ユーザーがネットワークの不安定な環境にいると想定される場合は、`.returnCacheDataElseLoad` を使用してキャッシュデータが存在すればそれを返すことも検討してください。この場合、最新データが取得できないことがありますが、接続状況に左右されず読み込みが速くなります。キャッシュはセッション中も定期的に更新されるため、ネットワークリクエストを減らす目的で安全に使用できます。</p><p></p><p>キャッシュはアプリの再起動後も保持され、アプリの再インストールまたは手動でのクリア時にのみ削除されます。</p> | </SDKv3> --- # File: present-remote-config-paywalls --- --- title: "iOS SDKでリモートコンフィグ設計のペイウォールをレンダリングする" description: "Adaptyでリモートコンフィグペイウォールを表示してユーザー体験をパーソナライズする方法を解説します。" --- <SDKv4> リモートコンフィグを使ってペイウォールをカスタマイズした場合、ユーザーに表示するためのレンダリング処理をアプリのコードに実装する必要があります。リモートコンフィグは柔軟にカスタマイズできるため、ペイウォールに何を含めるか、どのように表示するかはすべて開発者次第です。Adapty はリモートコンフィグを取得するメソッドを提供しており、カスタムペイウォールを自由に表示できます。 [iOS で初回オファーの対象ユーザーを確認する](fetch-paywalls-and-products#check-intro-offer-eligibility-on-ios)ことを忘れずに、対象ユーザーの場合の処理もペイウォールに組み込んでください。 ## フローのリモートコンフィグを取得して表示する \{#get-flow-remote-config-and-present-it\} v4 では、フローは設定済みロケールごとに 1 つの `AdaptyRemoteConfig` エントリを `remoteConfigs` 配列に持ちます。ユーザーの設定に合ったロケールを選択し、必要な値を読み取ってください。 <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift showLineNumbers do { let flow = try await Adapty.getFlow(placementId: "YOUR_PLACEMENT_ID") let config = flow.remoteConfigs.first(where: { $0.locale == "en" }) ?? flow.remoteConfigs.first let headerText = config?.dictionary?["header_text"] as? String } catch { // handle the error } ``` </TabItem> <TabItem value="swift-callback" label="Swift-Callback" default> ```swift showLineNumbers Adapty.getFlow(placementId: "YOUR_PLACEMENT_ID") { result in let flow = try? result.get() let config = flow?.remoteConfigs.first(where: { $0.locale == "en" }) ?? flow?.remoteConfigs.first let headerText = config?.dictionary?["header_text"] as? String } ``` </TabItem> </Tabs> 必要な値をすべて取得したら、それらを組み合わせて見栄えの良いページをレンダリングしましょう。さまざまなスマートフォンの画面サイズや向きに対応したデザインにして、どのデバイスでもシームレスで使いやすい体験を提供してください。 :::warning 以下で説明する[ペイウォール表示イベントの記録](present-remote-config-paywalls#track-paywall-view-events)を必ず行ってください。これにより、Adapty アナリティクスがファネルや A/B テストの情報を取得できるようになります。 ::: ペイウォールの表示が完了したら、次は購入フローの設定に進みます。ユーザーが購入する際は、フローのプロダクトを使って `.makePurchase()` を呼び出すだけです。`.makePurchase()` メソッドの詳細は[購入処理](making-purchases)を参照してください。 [フォールバックペイウォールというバックアップペイウォールを作成する](fallback-paywalls)ことをおすすめします。インターネット接続がない場合やキャッシュが利用できない場合でも、このバックアップが表示されるためスムーズな体験が維持されます。 ## ペイウォール表示イベントのトラッキング \{#track-paywall-view-events\} Adapty はペイウォールのパフォーマンス測定をサポートしています。購入データは自動的に収集されますが、ペイウォールの表示ログはユーザーがペイウォールを見たタイミングを把握しているのが開発者だけのため、手動での記録が必要です。 ペイウォール表示イベントを記録するには、`.logShowFlow(flow)` を呼び出すだけです。ファネルや A/B テストのペイウォール指標に反映されます。 :::important [フロービルダー](adapty-flow-builder)や[ペイウォールビルダー](adapty-paywall-builder)でレンダリングされたフローやペイウォールを表示している場合は、`.logShowFlow(flow)` を呼び出す必要はありません。それらの場合、Adapty が自動的に表示をトラッキングします。 ::: ```swift showLineNumbers try await Adapty.logShowFlow(flow) ``` リクエストパラメーター: | パラメーター | 必須 | 説明 | | :-------- | :------- |:-----------------------------------------------------------------------------------------| | **flow** | 必須 | `Adapty.getFlow(placementId:)` で取得した `AdaptyFlow` オブジェクト。 | </SDKv4> <SDKv3> リモートコンフィグを使ってペイウォールをカスタマイズした場合、ユーザーに表示するためのレンダリング処理をアプリのコードに実装する必要があります。リモートコンフィグは柔軟にカスタマイズできるため、ペイウォールに何を含めるか、どのように表示するかはすべて開発者次第です。Adapty はリモートコンフィグを取得するメソッドを提供しており、リモートコンフィグで設定したカスタムペイウォールを自由に表示できます。 [iOS で初回オファーの対象ユーザーを確認する](fetch-paywalls-and-products#check-intro-offer-eligibility-on-ios)ことを忘れずに、対象ユーザーの場合の処理もペイウォールに組み込んでください。 ## ペイウォールのリモートコンフィグを取得して表示する \{#get-paywall-remote-config-and-present-it\} ペイウォールのリモートコンフィグを取得するには、`remoteConfig` プロパティにアクセスして必要な値を取り出します。 <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift showLineNumbers do { let paywall = try await Adapty.getPaywall(placementId: "YOUR_PLACEMENT_ID") let headerText = paywall.remoteConfig?.dictionary?["header_text"] as? String } catch { // handle the error } ``` </TabItem> <TabItem value="swift-callback" label="Swift-Callback" default> ```swift showLineNumbers Adapty.getPaywall(placementId: "YOUR_PLACEMENT_ID") { result in let paywall = try? result.get() let headerText = paywall?.remoteConfig?.dictionary?["header_text"] as? String } ``` </TabItem> </Tabs> 必要な値をすべて取得したら、それらを組み合わせて見栄えの良いページをレンダリングしましょう。さまざまなスマートフォンの画面サイズや向きに対応したデザインにして、どのデバイスでもシームレスで使いやすい体験を提供してください。 :::warning 以下で説明する[ペイウォール表示イベントの記録](present-remote-config-paywalls#track-paywall-view-events)を必ず行ってください。これにより、Adapty アナリティクスがファネルや A/B テストの情報を取得できるようになります。 ::: ペイウォールの表示が完了したら、次は購入フローの設定に進みます。ユーザーが購入する際は、ペイウォールのプロダクトを使って `.makePurchase()` を呼び出すだけです。`.makePurchase()` メソッドの詳細は[購入処理](making-purchases)を参照してください。 [フォールバックペイウォールというバックアップペイウォールを作成する](fallback-paywalls)ことをおすすめします。インターネット接続がない場合やキャッシュが利用できない場合でも、このバックアップが表示されるためスムーズな体験が維持されます。 ## ペイウォール表示イベントのトラッキング \{#track-paywall-view-events\} Adapty はペイウォールのパフォーマンス測定をサポートしています。購入データは自動的に収集されますが、ペイウォールの表示ログはユーザーがペイウォールを見たタイミングを把握しているのが開発者だけのため、手動での記録が必要です。 ペイウォール表示イベントを記録するには、`.logShowPaywall(paywall)` を呼び出すだけです。ファネルや A/B テストのペイウォール指標に反映されます。 :::important [ペイウォールビルダー](adapty-paywall-builder)で作成したペイウォールを表示している場合は、`.logShowPaywall(paywall)` を呼び出す必要はありません。 ::: ```swift showLineNumbers Adapty.logShowPaywall(paywall) ``` リクエストパラメーター: | パラメーター | 必須 | 説明 | | :---------- | :------- |:-----------------------------------------------------------------------------------------| | **paywall** | 必須 | [`AdaptyPaywall`](https://swift.adapty.io/documentation/adapty/adaptypaywall) オブジェクト。 | </SDKv3> --- # File: making-purchases --- --- title: "iOS SDKでモバイルアプリの購入を行う" description: "Adaptyを使用したアプリ内課金とサブスクリプションの処理に関するガイド。" --- モバイルアプリ内でペイウォールを表示することは、ユーザーにプレミアムコンテンツやサービスへのアクセスを提供するための重要なステップです。ただし、[ペイウォールビルダー](adapty-paywall-builder)を使用してペイウォールをカスタマイズしている場合に限り、ペイウォールを表示するだけで購入処理が完結します。 ペイウォールビルダーを使用しない場合は、購入を完了してコンテンツをアンロックするために `.makePurchase()` という別のメソッドを使用する必要があります。このメソッドは、ユーザーがペイウォールで操作を行い、目的のトランザクションを進めるための窓口となります。 ペイウォールにユーザーが購入しようとしているプロダクトに対して有効なプロモーションオファーがある場合、Adaptyは購入時に自動的にそれを適用します。 :::warning 初回オファーが自動的に適用されるのは、ペイウォールビルダーで設定されたペイウォールを使用している場合のみです。 それ以外の場合は、[iOS での初回オファーの利用資格を確認](fetch-paywalls-and-products#check-intro-offer-eligibility-on-ios)する必要があります。この手順を省略すると、リリース時にアプリが審査で却下される可能性があります。また、初回オファーの対象ユーザーに通常価格が請求される可能性もあります。 ::: 一つのステップも省略せずに[初期設定](quickstart)を完了していることを確認してください。設定が完了していないと、購入の検証ができません。 ## 購入を行う \{#make-purchase\} :::note **[ペイウォールビルダー](adapty-paywall-builder)を使用していますか?** 購入は自動的に処理されます。このステップはスキップできます。 **ステップバイステップのガイドが必要ですか?** 完全なコンテキストとエンドツーエンドの実装手順については、[クイックスタートガイド](ios-implement-paywalls-manually)をご覧ください。 ::: <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift showLineNumbers do { let purchaseResult = try await Adapty.makePurchase(product: product) switch purchaseResult { case .userCancelled: // Handle the case where the user canceled the purchase case .pending: // Handle deferred purchases (e.g., the user will pay offline with cash) case let .success(profile, transaction): if profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false { // Grant access to the paid features } } } catch { // Handle the error } ``` </TabItem> <TabItem value="swift-callback" label="Swift-Callback" default> ```swift showLineNumbers Adapty.makePurchase(product: product) { result in switch result { case let .success(purchaseResult): switch purchaseResult { case .userCancelled: // Handle the case where the user canceled the purchase case .pending: // Handle deferred purchases (e.g., the user will pay offline with cash) case let .success(profile, transaction): if profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false { // Grant access to the paid features } } case let .failure(error): // Handle the error } } ``` </TabItem> </Tabs> リクエストパラメーター: | パラメーター | 必須 | 説明 | | :---------- | :------- | :-------------------------------------------------------------------------------------------------- | | **Product** | 必須 | ペイウォールから取得した [`AdaptyPaywallProduct`](https://swift.adapty.io/documentation/adapty/adaptypaywallproduct) オブジェクト。 | レスポンスパラメーター: | パラメーター | 説明 | |---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Profile** | <p>リクエストが成功した場合、レスポンスにはこのオブジェクトが含まれます。[AdaptyProfile](https://swift.adapty.io/documentation/adapty/adaptyprofile) オブジェクトは、アプリ内でのユーザーのアクセスレベル、サブスクリプション、非サブスクリプション購入に関する包括的な情報を提供します。</p><p>ユーザーがアプリへの必要なアクセス権を持っているかどうかを確認するために、アクセスレベルのステータスをチェックしてください。</p> | :::warning **注意:** Apple の StoreKit バージョンが v2.0 未満、かつ Adapty SDK バージョンが v2.9.0 未満の場合は、代わりに [Apple App Store 共有シークレット](app-store-connection-configuration#step-5-enter-app-store-shared-secret)を提供する必要があります。このメソッドは現在 Apple によって非推奨とされています。 ::: ## App Store からのアプリ内課金 \{#in-app-purchases-from-the-app-store\} ユーザーが App Store で購入を開始し、トランザクションがアプリに引き継がれる場合、2つの選択肢があります: - **トランザクションを即座に処理する:** `shouldAddStorePayment` で `true` を返します。これにより、Apple の購入システム画面がすぐに表示されます。 - **後処理のためにプロダクトオブジェクトを保存する:** `shouldAddStorePayment` で `false` を返し、後で保存したプロダクトを使って `makePurchase` を呼び出します。購入をトリガーする前にユーザーにカスタム画面を表示したい場合に便利です。 完全なコード例を以下に示します: ```swift showLineNumbers title="Swift" final class YourAdaptyDelegateImplementation: AdaptyDelegate { nonisolated func shouldAddStorePayment(for product: AdaptyDeferredProduct) -> Bool { // 1a. // Return `true` to continue the transaction in your app. The Apple purchase system screen will show automatically. // 1b. // Store the product object and return `false` to defer or cancel the transaction. false } // 2. Continue the deferred purchase later on by passing the product to `makePurchase` when the timing is appropriate func continueDeferredPurchase() async { let storedProduct: AdaptyDeferredProduct = // get the product object from 1b. do { try await Adapty.makePurchase(product: storedProduct) } catch { // handle the error } } } ``` ## iOS でオファーコードを利用する \{#redeem-offer-codes-in-ios\} --- no_index: true --- import Callout from '../../../components/Callout.astro'; <Details> <summary>オファーコードについて</summary> オファーコードを使うと、特定のユーザーに割引や無料トライアルを提供できます。自動的に適用される通常のオファーとは異なり、オファーコードはメールキャンペーン、SNS、印刷物など、アプリの外で配布します。ユーザーはApp Storeでコードを入力するか、引き換えURLを使うか、アプリ内ダイアログから利用できます。 オファーコードを設定するには、App Store Connectでサブスクリプションを開き、**Offer Codes** セクションに移動してください。オファーコードは[3種類](https://developer.apple.com/help/app-store-connect/manage-subscriptions/set-up-subscription-offer-codes)作成できます。 - **Free** — 指定した期間はサブスクリプションが無料になり、次の更新から通常価格になります。 - **Pay as you go** — 指定した期間、各請求サイクルに割引価格が適用され、その後は通常価格で更新されます。 - **Pay up front** — オファー期間全体に対して一括で割引価格を支払い、その後は通常価格で更新されます。 オファーコードをAdaptyに追加する必要はありません。Appleはオファー期間中のすべてのトランザクションにオファーコードカテゴリのタグを付与します。これには最初の引き換えとその後の割引更新がすべて含まれます。Adaptyはこのタグを検出し、各トランザクションをオファーカテゴリ `offer_code` として記録します。オファー期間が終了してサブスクリプションが通常価格で更新されると、タグは付与されなくなります。[Adapty ダッシュボード](controls-filters-grouping-compare-proceeds)のアナリティクスで **Offer Code** オファータイプによるフィルタリングが可能です。 #### 収益の差異が生じた場合のトラブルシューティング \{#revenue-discrepancy-troubleshooting\} オファーコードのトランザクションが、割引価格ではなく通常価格でAdaptyに記録されている場合は、App Store Connectで以下を確認してください。 - オファーコードに、ユーザーが引き換え可能なすべての地域に対して正しい価格が設定されているか。 - ユーザーの特定の国や地域に対してオファー価格が設定されているか。Appleはトランザクションに地域価格を含めて送信します。その地域のオファー価格が設定されていない場合、Appleは通常価格を送信することがあります。 [Adapty ダッシュボード](controls-filters-grouping-compare-proceeds)で、**Offer Code** オファータイプと **Offer Discount Type** フィルターを使ってオファーコードのトランザクションをフィルタリング・確認できます。 #### レガシープロモコード(非推奨) \{#legacy-promo-codes-deprecated\} <Callout type="warning"> Appleは2026年3月にアプリ内課金向けのプロモコードを廃止しました。オファーコードはより多くの機能(適格性の設定、有効期限、四半期あたり最大100万コード)を備えた後継機能です。アプリ内課金にプロモコードを使用していた場合は、App Store Connectでオファーコードに移行してください。 </Callout> レガシープロモコード(アプリのバージョンごとに最大100件)は、サブスクリプションへの無料アクセスを付与していました。オファーコードとは異なり、Appleはプロモコードのトランザクションに割引情報を含めず、レシートには通常価格が記載されていました。そのため、Adaptyはこれらのトランザクションを通常価格で記録し、Adaptyアナリティクスとレポートの間に収益の差異が生じていました。 本来は無料であるべきトランザクションが通常価格で記録されている履歴がある場合、それはレガシープロモコードによるものと考えられます。これらのコードは現在廃止されているため、正確な収益追跡のためにオファーコードに移行してください。 </Details> アプリ内でコード引き換えシートを表示するには: ```swift showLineNumbers Adapty.presentCodeRedemptionSheet() ``` :::danger 確認された問題として、一部のアプリでオファーコード引き換えシートが正常に動作しない場合があります。ユーザーを直接 App Store にリダイレクトすることをお勧めします。 そのためには、以下の形式の URL を開く必要があります: `https://apps.apple.com/redeem?ctx=offercodes&id={apple_app_id}&code={code}` ::: --- # File: restore-purchase --- --- title: "iOS SDKでのアプリ内購入の復元" description: "シームレスなユーザー体験を確保するために、Adaptyで購入を復元する方法を学びましょう。" --- 購入の復元とは、ユーザーが以前に購入したコンテンツ(サブスクリプションやアプリ内課金など)に、再度課金されることなくアクセスを取り戻せる機能です。アプリをアンインストール・再インストールした場合や、新しいデバイスに移行した場合でも、以前の購入内容に改めて支払うことなくアクセスできるため、特に便利な機能です。 :::note [ペイウォールビルダー](adapty-paywall-builder)で構築されたペイウォールでは、追加のコードなしに購入が自動的に復元されます。その場合は、この手順をスキップできます。 ::: [ペイウォールビルダー](adapty-paywall-builder)を使用してペイウォールをカスタマイズしていない場合に購入を復元するには、`.restorePurchases()` メソッドを呼び出してください。 <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift showLineNumbers do { let profile = try await Adapty.restorePurchases() if profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false { // successful access restore } } catch { // handle the error } ``` </TabItem> <TabItem value="swift-callback" label="Swift-Callback" default> ```swift showLineNumbers Adapty.restorePurchases { [weak self] result in switch result { case let .success(profile): if profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false { // successful access restore } case let .failure(error): // handle the error } } ``` </TabItem> </Tabs> レスポンスパラメーター: | パラメーター | 説明 | |---------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Profile** | <p>[`AdaptyProfile`](https://swift.adapty.io/documentation/adapty/adaptyprofile) オブジェクト。このモデルには、アクセスレベル、サブスクリプション、および非サブスクリプション購入に関する情報が含まれます。</p><p>ユーザーがアプリへのアクセス権を持っているかどうかを確認するには、**アクセスレベルのステータス**を確認してください。</p> | :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: --- # File: ios-transaction-management --- --- title: "iOS SDKにおける高度なトランザクション管理" description: "Adapty SDKを使用してiOSアプリでトランザクションを手動で完了する方法を説明します。" --- :::note 高度なトランザクション管理は、Adapty iOS SDK バージョン3.12以降でサポートされています。 ::: Adaptyの高度なトランザクション管理を使用すると、トランザクションの処理、検証、完了をより細かく制御できます。 高度なトランザクション管理には、連携して動作する3つのオプション機能が含まれています。 | 機能 | 目的 | |-------------------------------------------------------------|----------| | [`appAccountToken`](#assign-appaccounttoken) | Appleのトランザクションを内部ユーザーIDに紐付ける | | [`jwsTransaction`](#access-the-jws-representation) | バリデーション用にAppleの署名済みトランザクションペイロードを提供する | | [手動完了](#control-transaction-finishing-behavior) | バックエンドが成功を確認した後にのみトランザクションを完了できる | これらのツールを組み合わせることで、AdaptyがバックエンドとのトランザクションSync機能を維持しながら、堅牢なカスタムバリデーションフローを構築できます。 :::important ほとんどのアプリにはこの機能は不要です。 デフォルトでは、AdaptyはStoreKitトランザクションを自動的に検証・完了します。 このガイドは、独自のバックエンドバリデーションを実行する場合や、購入ライフサイクルを完全に制御したい場合にのみ使用してください。 ::: ## `appAccountToken`を設定する \{#assign-appaccounttoken\} [`appAccountToken`](https://developer.apple.com/documentation/storekit/product/purchaseoption/appaccounttoken(_:))は、App Storeのトランザクションを内部ユーザーIDに紐付けるための**UUID**です。 StoreKitはこのトークンをすべてのトランザクションに関連付けるため、バックエンドでApp Storeのデータとユーザーを照合できます。 ユーザーごとに生成した安定したUUIDを使用し、デバイスをまたいで同じアカウントに対して再利用してください。 これにより、購入とApp Storeの通知が正しく紐付けられます。 トークンは2つの方法で設定できます。SDK初期化時またはユーザーを識別するときです。 :::important `appAccountToken`は必ず`customerUserId`と一緒に渡す必要があります。 トークンのみを渡した場合、トランザクションに含まれません。 ::: <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift showLineNumbers // During configuration: let configurationBuilder = AdaptyConfiguration .builder(withAPIKey: "PUBLIC_SDK_KEY") .with(customerUserId: "YOUR_USER_ID", withAppAccountToken: UUID()) do { try await Adapty.activate(with: configurationBuilder.build()) } catch { // handle the error } // Or when identifying a user: do { try await Adapty.identify("YOUR_USER_ID", withAppAccountToken: UUID()) } catch { // handle the error } ``` </TabItem> <TabItem value="swift-callback" label="Swift-Callback" default> ```swift showLineNumbers // During configuration: let configurationBuilder = AdaptyConfiguration .builder(withAPIKey: "PUBLIC_SDK_KEY") .with(customerUserId: "YOUR_USER_ID", withAppAccountToken: <APP_ACCOUNT_TOKEN>) Adapty.activate(with: configurationBuilder.build()) { error in // handle the error } // Or when identifying a user: Adapty.identify("YOUR_USER_ID", withAppAccountToken: <APP_ACCOUNT_TOKEN>) { error in if let error { // handle the error } } ``` </TabItem> </Tabs> ## JWS表現にアクセスする \{#access-the-jws-representation\} 購入を行うと、結果にはAppleのトランザクションが[JWSコンパクトシリアライゼーション形式](https://developer.apple.com/documentation/storekit/verificationresult/jwsrepresentation-21vgo)で含まれます。 この値をバックエンドに転送して、独自のバリデーションやログ記録に活用できます。 ```swift let result = try await Adapty.makePurchase(product: paywallProduct) let jwsRepresentation = result.jwsTransaction ``` ## トランザクション完了の動作を制御する \{#control-transaction-finishing-behavior\} デフォルトでは、AdaptyはバリデーションAfterにStoreKitトランザクションを自動的に完了します。 バックエンドが成功を確認するまで完了を遅らせたい場合は、完了動作を手動に設定してください。 このモードでは: - Adaptyは引き続き購入を検証し、バックエンドとSyncします。 - `finish()`を明示的に呼び出すまで、トランザクションは未完了のままです。 ```swift var configBuilder = AdaptyConfiguration .builder(withAPIKey: "YOUR_API_KEY") .with(transactionFinishBehavior: .manual) try await Adapty.activate(with: configBuilder.build()) ``` 手動トランザクション完了を使用する場合、未完了のトランザクションを処理するために`onUnfinishedTransaction`デリゲートメソッドを実装する必要があります。 ```swift showLineNumbers title="Swift" extension YourApp: AdaptyDelegate { func onUnfinishedTransaction(_ transaction: AdaptyUnfinishedTransaction) async { // Perform your custom validation logic here // When ready, finish the transaction await transaction.finish() } } ``` 現在の未完了トランザクションをすべて取得するには、`getUnfinishedTransactions()`メソッドを使用してください。 ```swift let unfinishedTransactions = try await Adapty.getUnfinishedTransactions() ``` --- # File: implement-observer-mode --- --- title: "iOS SDK でオブザーバーモードを実装する" description: "iOS SDK で Adapty のオブザーバーモードを実装し、ユーザーのサブスクリプションイベントを追跡する方法を説明します。" --- 独自の購入インフラを持っており、まだ Adapty への完全な移行を検討していない場合は、[オブザーバーモード](observer-vs-full-mode)を活用できます。基本的な使い方では、オブザーバーモードによって高度なアナリティクスや、アトリビューション・分析システムとのシームレスな連携が可能になります。 これで十分な場合は、以下の 2 つだけ対応すれば OK です: 1. Adapty SDK を設定する際に `observerMode` パラメータを `true` にしてオブザーバーモードを有効化する。 2. 既存の購入インフラから Adapty へ[トランザクションを報告する](report-transactions-observer-mode)。 ペイウォールや A/B テストも利用したい場合は、以下に説明する追加のセットアップが必要です。 ## オブザーバーモードのセットアップ \{#observer-mode-setup\} 購入やサブスクリプションのステータス管理を自分で行い、サブスクリプションイベントの送信やアナリティクスのために Adapty を使用する場合は、オブザーバーモードを有効にしてください。 :::important オブザーバーモードで動作している場合、Adapty SDK はトランザクションをクローズしません。そのため、トランザクションの処理はご自身で行ってください。 ::: <Tabs groupId="current-os" queryString> <TabItem value="swiftui" label="SwiftUI"> ```swift showLineNumbers @main struct YourApp: App { init() { // Configure Adapty SDK let configurationBuilder = AdaptyConfiguration .builder(withAPIKey: "YOUR_PUBLIC_SDK_KEY") // Get from Adapty dashboard .with(observerMode: true) let config = configurationBuilder.build() // Activate Adapty SDK asynchronously Task { do { try await Adapty.activate(with: configurationBuilder) } catch { // Handle error appropriately for your app print("Adapty activation failed: ", error) } } var body: some Scene { WindowGroup { // Your content view } } } } ``` </TabItem> <TabItem value="swift" label="UIKit" default> ```swift showLineNumbers Task { do { let configurationBuilder = AdaptyConfiguration .builder(withAPIKey: "YOUR_PUBLIC_SDK_KEY") // Get from Adapty dashboard .with(observerMode: true) let config = configurationBuilder.build() try await Adapty.activate(with: config) } catch { // Handle error appropriately for your app print("Adapty activation failed: ", error) } } ``` </TabItem> </Tabs> パラメータ: | パラメータ | 説明 | | --------------------------- | ------------------------------------------------------------ | | observerMode | [オブザーバーモード](observer-vs-full-mode)を制御する真偽値です。デフォルト値は `false` です。 | ## オブザーバーモードで Adapty のペイウォールを使用する \{#using-adapty-paywalls-in-observer-mode\} Adapty のペイウォールや A/B テスト機能も使用したい場合は可能ですが、オブザーバーモードでは追加のセットアップが必要です。上記の手順に加えて、以下を行ってください: 1. [リモートコンフィグペイウォール](present-remote-config-paywalls)は通常どおり表示する。ペイウォールビルダーのペイウォールについては、[iOS](ios-present-paywall-builder-paywalls-in-observer-mode) 向けの専用セットアップガイドに従う。 3. 購入トランザクションに[ペイウォールを紐付ける](report-transactions-observer-mode)。 --- # File: report-transactions-observer-mode --- --- title: "iOS SDKのObserverモードでトランザクションをレポートする" description: "iOS SDKのAdapty Observerモードで購入トランザクションをレポートし、ユーザーインサイトと収益追跡を行います。" --- <Tabs groupId="sdk-version" queryString> <TabItem value="current" label="Adapty SDK v3.4+(現行版)" default> Observerモードでは、Adapty SDKは既存の購入システムで行われた購入を自動的に追跡できません。アプリストアからトランザクションを手動でレポートする必要があります。アナリティクスのエラーを防ぐため、アプリをリリースする**前に**この設定を行うことが重要です。 `reportTransaction`を使用して、Adaptyが認識できるよう各トランザクションを明示的にレポートしてください。 :::warning **トランザクションのレポートをスキップしないでください!** `reportTransaction`を呼び出さないと、Adaptyはトランザクションを認識できず、アナリティクスに表示されず、インテグレーションにも送信されません。 ::: Adaptyのペイウォールを使用している場合は、トランザクションをレポートする際に`variationId`を含めてください。これにより、購入がトリガーとなったペイウォールとリンクされ、正確なペイウォールアナリティクスが確保されます。 ```swift showLineNumbers do { // every time when calling transasction.finish() try await Adapty.reportTransaction(transaction, withVariationId: <YOUR_PAYWALL_VARIATION_ID>) } catch { // handle the error } ``` パラメーター: | パラメーター | 必須/任意 | 説明 | | --------------- | --------- | ------------------------------------------------------------ | | **transaction** | 必須 | <ul><li> StoreKit 1の場合:SKPaymentTransaction。</li><li> StoreKit 2の場合:Transaction。</li></ul> | | **variationId** | 任意 | ペイウォールバリアントの一意のID。[AdaptyPaywall](https://swift.adapty.io/documentation/adapty/adaptypaywall)オブジェクトの`variationId`プロパティから取得できます。 | </TabItem> <TabItem value="old" label="Adapty SDK 3.3.x(旧バージョン)" default> Observerモードでは、Adapty SDKは既存の購入システムで行われた購入を自動的に追跡できません。アプリストアからトランザクションをレポートするか、リストアする必要があります。アナリティクスのエラーを防ぐため、アプリをリリースする**前に**この設定を行うことが重要です。 `reportTransaction`を使用して、トランザクションデータをAdaptyに送信してください。 :::warning **トランザクションのレポートをスキップしないでください!** `reportTransaction`を呼び出さないと、Adaptyはトランザクションを認識できず、アナリティクスに表示されず、インテグレーションにも送信されません。 ::: Adaptyのペイウォールを使用している場合は、トランザクションをレポートする際に`withVariationId`を含めてください。これにより、購入がトリガーとなったペイウォールとリンクされ、正確なペイウォールアナリティクスが確保されます。 ```swift showLineNumbers do { // every time when calling transasction.finish() try await Adapty.reportTransaction(transaction, withVariationId: <YOUR_PAYWALL_VARIATION_ID>) } catch { // handle the error } ``` パラメーター: | パラメーター | 必須/任意 | 説明 | | --------------- | --------- | ------------------------------------------------------------ | | **transaction** | 必須 | <ul><li> StoreKit 1の場合:SKPaymentTransaction。</li><li> StoreKit 2の場合:Transaction。</li></ul> | | **variationId** | 任意 | ペイウォールバリアントの一意のID。[AdaptyPaywall](https://swift.adapty.io/documentation/adapty/adaptypaywall)オブジェクトの`variationId`プロパティから取得できます。 | </TabItem> <TabItem value="old2" label="Adapty SDK 3.2.x以前(旧バージョン)" default> **トランザクションのレポート** - 3.1.x以前のバージョンはApp Storeのトランザクションを自動的に監視するため、手動でのレポートは不要です。 - バージョン3.2はObserverモードをサポートしていません。 **トランザクションとペイウォールの関連付け** Adapty SDKは購入のソースを判断できません。購入の処理はお客様側で行うためです。そのため、Observerモードでペイウォールやおよび/またはA/Bテストを使用する場合は、アプリストアから受け取ったトランザクションをモバイルアプリのコード内で対応するペイウォールに関連付ける必要があります。アプリをリリースする前にこの設定を正しく行うことが重要です。そうしないと、アナリティクスにエラーが発生します。 ```swift let variationId = paywall.variationId // There are two overloads: for StoreKit 1 and StoreKit 2 Adapty.setVariationId(variationId, forPurchasedTransaction: transactionId) { error in if error == nil { // successful binding } } ``` リクエストパラメーター: | パラメーター | 必須/任意 | 説明 | | ------------- | --------- | ------------------------------------------------------------ | | variationId | 必須 | バリアントの文字列識別子。[AdaptyPaywall](https://swift.adapty.io/documentation/adapty/adaptypaywall)オブジェクトの`variationId`プロパティを使用して取得できます。 | | transactionId | 必須 | <p>StoreKit 1の場合:[SKPaymentTransaction](https://developer.apple.com/documentation/storekit/skpaymenttransaction)オブジェクト。</p><p>StoreKit 2の場合:[Transaction](https://developer.apple.com/documentation/storekit/transaction)オブジェクト。</p> | </TabItem> </Tabs> --- # File: ios-troubleshoot-purchases --- --- title: "iOSのSDKにおける購入のトラブルシューティング" description: "iOSのSDKにおける購入のトラブルシューティング" --- このガイドでは、iOS SDKで手動購入を実装する際によく発生する問題の解決方法を説明します。 ## オブザーバーモードでのAdaptyError.cantMakePayments \{#adaptyer-ror-cant-make-payments-in-observer-mode\} **問題**: オブザーバーモードで`makePurchase`を使用すると、`AdaptyError.cantMakePayments`が発生する。 **原因**: オブザーバーモードでは、Adaptyの`makePurchase`メソッドではなく、自分側で購入を処理する必要があります。 **解決策**: 購入に`makePurchase`を使用している場合は、オブザーバーモードをオフにしてください。`makePurchase`を使用するか、オブザーバーモードで自分側で購入を処理するか、どちらか一方を選択する必要があります。詳細は[オブザーバーモードの実装](implement-observer-mode)を参照してください。 ## makePurchasesCompletionHandlersが見つからない \{#not-found-makepurchasescompletionhandlers\} **問題**: `makePurchasesCompletionHandlers`が見つからないというエラーが発生している。 **原因**: これは通常、サンドボックステストに関連する問題です。 **解決策**: 新しいサンドボックスユーザーを作成して再試行してください。これにより、サンドボックス関連の購入完了ハンドラーの問題が解決されることがよくあります。 ## その他の問題 \{#other-issues\} **問題**: 上記で取り上げていない購入関連のその他の問題が発生している。 **解決策**: 必要に応じて[マイグレーションガイド](ios-sdk-migration-guides)を使用してSDKを最新バージョンに移行してください。多くの問題は新しいSDKバージョンで解決されています。 --- # File: ios-web-paywall --- --- title: "iOS SDKでウェブペイウォールを実装する" description: "App Storeの手数料や審査なしで決済を受け付けるウェブペイウォールを設定します。" --- :::important 始める前に、[ダッシュボードでウェブペイウォールを設定](web-paywall)済みであること、および Adapty SDK バージョン 3.6.1 以降がインストールされていることを確認してください。 ::: ## ウェブペイウォールを開く \{#open-web-paywalls\} 自分で開発したペイウォールを利用している場合は、SDK メソッドを使ってウェブペイウォールを処理する必要があります。`.openWebPaywall` メソッドは次の処理を行います。 1. 特定のユーザーに表示されたペイウォールとリダイレクト先のウェブページを Adapty が紐付けるための一意の URL を生成します。 2. ユーザーがアプリに戻ったタイミングを検知し、短い間隔で `.getProfile` を呼び出して、プロファイルのアクセス権が更新されたかどうかを確認します。 これにより、決済が成功してアクセス権が更新された場合、アプリ内でほぼ即座にサブスクリプションが有効化されます。 ```swift showLineNumbers title="Swift" do { try await Adapty.openWebPaywall(for: product) } catch { print("Failed to open web paywall: \(error)") } ``` :::note `openWebPaywall` メソッドには2つのバージョンがあります。 1. `openWebPaywall(product)` はペイウォールごとに URL を生成し、プロダクトのデータも URL に追加します。 2. `openWebPaywall(paywall)` はペイウォールごとに URL を生成しますが、プロダクトのデータは URL に追加しません。Adapty のペイウォールに設定されたプロダクトとウェブペイウォールのプロダクトが異なる場合に使用してください。 ::: ## エラーを処理する \{#handle-errors\} | エラー | 説明 | 推奨される対処法 | |-----------------------------------------|------------------------------------------------------|---------------------------------------------------------------------------| | AdaptyError.paywallWithoutPurchaseUrl | ペイウォールにウェブ購入 URL が設定されていない | Adapty ダッシュボードでペイウォールが正しく設定されているか確認してください | | AdaptyError.productWithoutPurchaseUrl | プロダクトにウェブ購入 URL が設定されていない | Adapty ダッシュボードでプロダクトの設定を確認してください | | AdaptyError.failedOpeningWebPaywallUrl | ブラウザで URL を開くことができなかった | デバイスの設定を確認するか、別の購入方法を提供してください | | AdaptyError.failedDecodingWebPaywallUrl | URL 内のパラメーターを正しくエンコードできなかった | URL パラメーターが有効かつ適切にフォーマットされているか確認してください | ## 実装例 \{#implementation-example\} ```swift showLineNumbers title="Swift" class SubscriptionViewController: UIViewController { var paywall: AdaptyPaywall? @IBAction func purchaseButtonTapped(_ sender: UIButton) { guard let paywall = paywall, let product = paywall.products.first else { return } Task { await offerWebPurchase(for: product) } } func offerWebPurchase(for paywallProduct: AdaptyPaywallProduct) async { do { // Attempt to open web paywall try await Adapty.openWebPaywall(for: paywallProduct) } catch let error as AdaptyError { switch error { case .paywallWithoutPurchaseUrl, .productWithoutPurchaseUrl: showAlert(message: "Web purchase is not available for this product.") case .failedOpeningWebPaywallUrl: showAlert(message: "Could not open web browser. Please try again.") default: showAlert(message: "An error occurred: \(error.localizedDescription)") } } catch { showAlert(message: "An unexpected error occurred.") } } // Helper methods private func showAlert(message: String) { /* ... */ } } ``` :::note ユーザーがアプリに戻った後は、プロファイルの更新を反映するために UI をリフレッシュしてください。`AdaptyDelegate` がプロファイル更新イベントを受信して処理します。 ::: ## アプリ内ブラウザでウェブペイウォールを開く \{#open-web-paywalls-in-an-in-app-browser\} :::important アプリ内ブラウザでのウェブペイウォール表示は、Adapty SDK v3.15 以降でサポートされています。 ::: デフォルトでは、ウェブペイウォールは外部ブラウザで開きます。 シームレスなユーザー体験を提供するために、アプリ内ブラウザでウェブペイウォールを開くことができます。これにより、アプリを切り替えることなく、アプリ内でウェブ購入ページを表示してトランザクションを完了できます。 この機能を有効にするには、`in` パラメーターを `.inAppBrowser` に設定します。 ```swift showLineNumbers title="Swift" do { try await Adapty.openWebPaywall(for: product, in: .inAppBrowser) // default – .externalBrowser } catch { print("Failed to open web paywall: \(error)") } ``` --- # File: identifying-users --- --- title: "iOS SDKでユーザーを識別する" description: "Adaptyでユーザーを識別し、パーソナライズされたサブスクリプション体験を向上させましょう。" --- Adaptyはすべてのユーザーに対して内部プロファイルIDを作成します。ただし、独自の認証システムがある場合は、独自のCustomer User IDを設定してください。[Profiles](profiles-crm)セクションでCustomer User IDによるユーザー検索が可能で、[サーバーサイドAPI](getting-started-with-server-side-api)でも使用できます。このIDはすべてのインテグレーションに送信されます。 ## 設定時にCustomer User IDを設定する \{#set-customer-user-id-on-configuration\} 設定時にユーザーIDが利用可能な場合は、`.activate()`メソッドの`customerUserId`パラメーターとして渡してください: <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift showLineNumbers // In your AppDelegate class: let configurationBuilder = AdaptyConfiguration .builder(withAPIKey: "PUBLIC_SDK_KEY") .with(customerUserId: "YOUR_USER_ID") do { try await Adapty.activate(with: configurationBuilder.build()) } catch { // handle the error } ``` </TabItem> <TabItem value="swift-callback" label="Swift-Callback" default> ```swift showLineNumbers // In your AppDelegate class: let configurationBuilder = AdaptyConfiguration .builder(withAPIKey: "PUBLIC_SDK_KEY") .with(customerUserId: "YOUR_USER_ID") Adapty.activate(with: configurationBuilder.build()) { error in // handle the error } ``` </TabItem> </Tabs> :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: ## 設定後にCustomer User IDを設定する \{#set-customer-user-id-after-configuration\} SDKの設定時にユーザーIDがない場合は、`.identify()`メソッドを使っていつでも後から設定できます。最も一般的なユースケースは、登録や認証の後、ユーザーが匿名ユーザーから認証済みユーザーに切り替わるタイミングです。 <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift showLineNumbers do { try await Adapty.identify("YOUR_USER_ID") } catch { // handle the error } ``` </TabItem> <TabItem value="swift-callback" label="Swift-Callback" default> ```swift showLineNumbers Adapty.identify("YOUR_USER_ID") { error in if let error { // handle the error } } ``` </TabItem> </Tabs> リクエストパラメーター: - **Customer User ID**(必須): 文字列のユーザー識別子。 :::warning 重要なユーザーデータの再送信 ユーザーが再度ログインするなど、Adaptyのサーバーにすでにそのユーザーの情報が存在する場合があります。このような場合、Adapty SDKは自動的に新しいユーザーへ切り替えます。匿名ユーザーにカスタム属性やサードパーティネットワークからのアトリビューションなどのデータを渡していた場合は、識別済みユーザーに対してそのデータを再送信してください。 また、新しいユーザーのデータが異なる可能性があるため、ユーザーを識別した後はすべてのペイウォールとプロダクトを再取得することが重要です。 ::: ## ログアウトとログイン \{#logging-out-and-logging-in\} `.logout()`メソッドを呼び出すことで、いつでもユーザーをログアウトできます: <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift showLineNumbers do { try await Adapty.logout() } catch { // handle the error } ``` </TabItem> <TabItem value="swift-callback" label="Swift-Callback" default> ```swift showLineNumbers Adapty.logout { error in if error == nil { // successful logout } } ``` </TabItem> </Tabs> その後、`.identify()`メソッドを使ってユーザーをログインできます。 ## appAccountTokenを設定する \{#set-appaccounttoken\} [`appAccountToken`](https://developer.apple.com/documentation/storekit/product/purchaseoption/appaccounttoken(_:))は、AppleのStoreKit 2がアプリのインストールやデバイスをまたいでユーザーを識別するためのUUIDです。 Adapty iOS SDK 3.10.2以降、SDKの設定時またはユーザーの識別時に`appAccountToken`を渡せるようになりました: <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift showLineNumbers // During configuration: let configurationBuilder = AdaptyConfiguration .builder(withAPIKey: "PUBLIC_SDK_KEY") .with(customerUserId: "YOUR_USER_ID", withAppAccountToken: UUID()) do { try await Adapty.activate(with: configurationBuilder.build()) } catch { // handle the error } // Or when identifying a user: do { try await Adapty.identify("YOUR_USER_ID", withAppAccountToken: UUID()) } catch { // handle the error } ``` </TabItem> <TabItem value="swift-callback" label="Swift-Callback" default> ```swift showLineNumbers // During configuration: let configurationBuilder = AdaptyConfiguration .builder(withAPIKey: "PUBLIC_SDK_KEY") .with(customerUserId: "YOUR_USER_ID", withAppAccountToken: UUID()) Adapty.activate(with: configurationBuilder.build()) { error in // handle the error } // Or when identifying a user: Adapty.identify("YOUR_USER_ID", withAppAccountToken: UUID()) { error in if let error { // handle the error } } ``` </TabItem> </Tabs> その後、`.identify()`メソッドを使ってユーザーをログインできます。 ## デバイスをまたいでユーザーを検出する \{#detect-users-across-devices\} --- no_index: true --- SDKが有効化されると、StoreKit(iOS)またはGoogle Play Billing(Android)からユーザーの既存のエンタイトルメントを自動的に読み取り、Adaptyバックエンドと同期します。有効なサブスクリプションは、アプリが`restorePurchases`を呼び出すことなく、Adaptyプロファイルに表示されます。 **自動では行われない**のは、新しいデバイスのプロファイルが元のデバイスと同じユーザーのものであることの認識です。AdaptyはCustomer User IDでプロファイルを照合するため、同一性の継続性はCUIDとして何を使用するかによって異なります。 **デバイス間でAdaptyが検出できること** | あなたの設定 | Adaptyが検出すること | 必要な対応 | | --- | --- | --- | | Customer User ID = `device_id`(アプリのログインなし) | 新しいデバイスは異なるCUIDを取得するため、異なるプロファイルが作成されます。サブスクリプションは**Access level updated**イベントを通じて新しいプロファイルに同期されますが、`subscription_started`は発火しません。新しいプロファイルは元の購入の継承者として扱われます。`subscription_started`に基づくアナリティクスは、リターニングユーザーをカウント不足します。 | リターニングユーザーが既存のプロファイルをデバイス間で照合できるよう、安定したアカウントIDをCustomer User IDとして使用してください。 | | Customer User ID = 安定したアカウントID(すべてのデバイスでログイン) | SDKは`activate()`でサブスクリプションを自動同期し、`identify()`がCUIDで既存のプロファイルを照合します。 | 追加の設定は不要です。IDとサブスクリプションの両方が自動的に解決されます。 | | Apple Family Sharing の継承者 | ファミリーメンバーは**Access level updated**イベントのみを通じてサブスクリプションを受け取ります。`subscription_started`は発火しません。 | **Access level updated**をリッスンしてください。完全なイベントマトリクスは[Apple Family Sharing](apple-family-sharing)を参照してください。 | | 同じApple/Googleアカウント、異なるアプリ内ユーザー | 最初に購入を記録したプロファイルが親になります。その後のプロファイルは継承者チェーンを通じてサブスクリプションを確認し、**Access level updated**イベントが1回発生します。 | ログインを必須にし、あなたのモデルに合った[共有モード](sharing-paid-access-between-user-accounts)を選択してください。 | **新しいデバイスでの購入の復元** ペイウォールにユーザーが操作できる「購入を復元」ボタンを設置してください。Apple App Review(ガイドライン3.1.1)で必須とされており、自動同期がエッジケースを見逃した場合のフォールバックとして機能します。このボタンはSDKの`restorePurchases`を呼び出す必要があります。 初回起動時にプログラムで`restorePurchases`を呼び出すことは、通常の使用では必要ありません。SDKはすでに`activate()`で同等の処理を実行しています。プログラムによる呼び出しは、`activate()`完了後にアクセスが欠落している場合のデバッグなど、強制的に新しいレシートチェックを行う場合にのみ使用してください。 --- # File: setting-user-attributes --- --- title: "iOS SDKでユーザー属性を設定する" description: "Adaptyでユーザー属性を設定し、より効果的なオーディエンスのセグメンテーションを実現する方法を学びましょう。" --- アプリのユーザーに対して、メールアドレスや電話番号などの任意の属性を設定できます。設定した属性は、ユーザーの[セグメント](segments)の作成や、CRMでの確認に利用できます。 ### ユーザー属性の設定 \{#setting-user-attributes\} ユーザー属性を設定するには、`.updateProfile()` メソッドを呼び出します。 <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift showLineNumbers let builder = AdaptyProfileParameters.Builder() .with(email: "email@email.com") .with(phoneNumber: "+18888888888") .with(firstName: "John") .with(lastName: "Appleseed") .with(gender: .other) .with(birthday: Date()) do { try await Adapty.updateProfile(params: builder.build()) } catch { // handle the error } ``` </TabItem> <TabItem value="swift-callback" label="Swift-Callback" default> ```swift showLineNumbers let builder = AdaptyProfileParameters.Builder() .with(email: "email@email.com") .with(phoneNumber: "+18888888888") .with(firstName: "John") .with(lastName: "Appleseed") .with(gender: .other) .with(birthday: Date()) Adapty.updateProfile(params: builder.build()) { error in if error != nil { // handle the error } } ``` </TabItem> </Tabs> `updateProfile` メソッドで以前に設定した属性はリセットされません。 :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: ### 使用できるキーの一覧 \{#the-allowed-keys-list\} `AdaptyProfileParameters.Builder` で使用できるキー `<Key>` と値 `<Value>` の一覧は以下のとおりです。 | キー | 値 | |---|-----| | <p>email</p><p>phoneNumber</p><p>firstName</p><p>lastName</p> | String | | gender | 列挙型。使用できる値: `female`、`male`、`other` | | birthday | Date | ### カスタムユーザー属性 \{#custom-user-attributes\} 独自のカスタム属性を設定できます。カスタム属性は通常、アプリの使用状況に関連したものです。たとえば、フィットネスアプリなら週あたりの運動回数、語学学習アプリならユーザーの習熟度などが考えられます。カスタム属性をセグメントで活用して、ターゲットを絞ったペイウォールやオファーを作成したり、どのプロダクト指標が収益に最も影響するかをアナリティクスで分析したりできます。 ```swift showLineNumbers do { builder = try builder.with(customAttribute: "value1", forKey: "key1") } catch { // handle key/value validation error } ``` 既存のキーを削除するには、`.withRemoved(customAttributeForKey:)` メソッドを使用します。 ```swift showLineNumbers do { builder = try builder.withRemoved(customAttributeForKey: "key2") } catch { // handle error } ``` 事前にどのカスタム属性が設定されているかを確認したい場合は、`AdaptyProfile` オブジェクトの `customAttributes` フィールドを使用してください。 :::warning `customAttributes` の値は最新でない場合があります。ユーザー属性は異なるデバイスからいつでも送信される可能性があるため、最後の同期後にサーバー上の属性が変更されている場合があります。 ::: ### 制限事項 \{#limits\} - ユーザーあたりのカスタム属性は最大30個まで - キー名は最大30文字。キー名に使用できる文字は英数字と以下の記号です: `_` `-` `.` - 値は文字列または浮動小数点数で、50文字以内 --- # File: subscription-status --- --- title: "iOS SDK でサブスクリプションのステータスを確認する" description: "Adapty でユーザーのサブスクリプションステータスを追跡・管理して、顧客維持率を向上させましょう。" --- Adapty を使えば、サブスクリプションのステータス管理が簡単になります。プロダクト ID をコードに手動で埋め込む必要はなく、アクティブな[アクセスレベル](access-level)を確認するだけで、ユーザーのサブスクリプションステータスをスムーズに把握できます。 サブスクリプションのステータス確認を始める前に、[App Store サーバー通知](enable-app-store-server-notifications)を設定してください。 ## アクセスレベルと AdaptyProfile オブジェクト \{#access-level-and-the-adaptyprofile-object\} アクセスレベルは [AdaptyProfile](https://swift.adapty.io/documentation/adapty/adaptyprofile) オブジェクトのプロパティです。アプリ起動時([ユーザーを識別する](identifying-users#set-customer-user-id-on-configuration)タイミングなど)にプロファイルを取得し、変更が発生したときに更新することをおすすめします。こうすることで、都度リクエストを送ることなくプロファイルオブジェクトを活用できます。 プロファイルの更新通知を受け取るには、以下の[サブスクリプションステータスの更新をリッスンする](subscription-status#listening-for-subscription-status-updates)セクションで説明している方法でプロファイルの変更を監視してください。 :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: ## サーバーからアクセスレベルを取得する \{#retrieving-the-access-level-from-the-server\} サーバーからアクセスレベルを取得するには、`.getProfile()` メソッドを使用します。 <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift showLineNumbers do { let profile = try await Adapty.getProfile() if profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false { // grant access to premium features } } catch { // handle the error } ``` </TabItem> <TabItem value="swift-callback" label="Swift-Callback" default> ```swift showLineNumbers Adapty.getProfile { result in if let profile = try? result.get() { // check the access profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive ?? false { // grant access to premium features } } } ``` </TabItem> </Tabs> レスポンスパラメーター: | パラメーター | 説明 | | ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Profile | <p>[AdaptyProfile](https://swift.adapty.io/documentation/adapty/adaptyprofile) オブジェクト。通常、ユーザーがプレミアムアクセスを持っているかどうかを判断するには、プロファイルのアクセスレベルのステータスだけを確認すれば十分です。</p><p></p><p>`.getProfile` メソッドは常に API へのクエリを試みるため、最新の結果を返します。何らかの理由(インターネット接続がないなど)で Adapty SDK がサーバーから情報を取得できない場合は、キャッシュのデータが返されます。また、Adapty SDK は `AdaptyProfile` キャッシュを定期的に更新し、情報をできる限り最新の状態に保ちます。</p> | `.getProfile()` メソッドはユーザープロファイルを返し、そこからアクセスレベルのステータスを取得できます。アプリごとに複数のアクセスレベルを設定することも可能です。たとえばニュースアプリで複数のトピックのサブスクリプションを独立して販売する場合、「sports」や「science」といったアクセスレベルを作成できます。ただし、ほとんどの場合はアクセスレベルは 1 つで十分なので、デフォルトの「premium」アクセスレベルをそのまま使用できます。 デフォルトの「premium」アクセスレベルを確認する例を示します。 <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift showLineNumbers do { let profile = try await Adapty.getProfile() let isPremium = profile.accessLevels["premium"]?.isActive ?? false // grant access to premium features } catch { // handle the error } ``` </TabItem> <TabItem value="swift-callback" label="Swift-Callback" default> ```swift showLineNumbers Adapty.getProfile { result in if let profile = try? result.get(), profile.accessLevels["premium"]?.isActive ?? false { // grant access to premium features } } ``` </TabItem> </Tabs> ### サブスクリプションステータスの更新をリッスンする \{#listening-for-subscription-status-updates\} ユーザーのサブスクリプションが変更されるたびに、Adapty はイベントを発火します。 Adapty からのメッセージを受け取るには、追加の設定が必要です。 ```swift showLineNumbers Adapty.delegate = self // To receive subscription updates, extend `AdaptyDelegate` with this method: nonisolated func didLoadLatestProfile(_ profile: AdaptyProfile) { // handle any changes to subscription state } ``` Adapty はアプリ起動時にもイベントを発火します。この場合、キャッシュされたサブスクリプションステータスが渡されます。 ### サブスクリプションステータスのキャッシュ \{#subscription-status-cache\} Adapty SDK に実装されたキャッシュはプロファイルのサブスクリプションステータスを保持します。これにより、サーバーが利用できない場合でも、キャッシュされたデータからプロファイルのサブスクリプションステータス情報を取得できます。 ただし、キャッシュから直接データをリクエストすることはできません。SDK は 1 分ごとにサーバーに問い合わせて、プロファイルに関する更新や変更を確認します。新しいトランザクションなどの変更があった場合は、サーバーとの同期を維持するためにキャッシュデータへ反映されます。 --- # File: ios-deal-with-att --- --- title: "iOSのATTについて" description: "iOSでAdaptyを使い始めて、サブスクリプションの設定と管理を効率化しましょう。" --- アプリでAppTrackingTransparencyフレームワークを使用しており、ユーザーにアプリトラッキングの許可リクエストを表示している場合は、[認証ステータス](https://developer.apple.com/documentation/apptrackingtransparency/attrackingmanager/authorizationstatus/)をAdaptyに送信する必要があります。 <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift showLineNumbers let builder = AdaptyProfileParameters.Builder() .with(appTrackingTransparencyStatus: .authorized) do { try await Adapty.updateProfile(params: builder.build()) } catch { // handle the error } ``` </TabItem> <TabItem value="swift-callback" label="Swift-Callback" default> ```swift showLineNumbers if #available(iOS 14, macOS 11.0, *) { let builder = AdaptyProfileParameters.Builder() .with(appTrackingTransparencyStatus: .authorized) Adapty.updateProfile(params: builder.build()) { [weak self] error in if error != nil { // handle the error } } } ``` </TabItem> </Tabs> :::warning この値は変更されたタイミングでできるだけ早く送信することを強くお勧めします。そうすることで、設定済みのインテグレーションにデータがタイムリーに送信されます。 ::: --- # File: kids-mode --- --- title: "iOS SDK のキッズモード" description: "キッズモードを簡単に有効化して Apple のポリシーに準拠できます。iOS SDK では IDFA や広告データは収集されません。" --- iOS アプリがお子様向けの場合は、[Apple](https://developer.apple.com/kids/) のポリシーに従う必要があります。Adapty SDK を使用している場合、いくつかの簡単な手順でポリシーに準拠した設定を行い、App Store の審査を通過できます。 ## 必要な対応 \{#whats-required\} 以下の情報の収集を無効化するよう、Adapty SDK を設定する必要があります。 - [IDFA(広告識別子)](https://en.wikipedia.org/wiki/Identifier_for_Advertisers) - [IP アドレス](https://www.ftc.gov/system/files/ftc_gov/pdf/p235402_coppa_application.pdf) また、カスタマーユーザー ID の扱いにも注意が必要です。`<名前.苗字>` 形式のユーザー ID やメールアドレスは、個人情報の収集とみなされます。キッズモードでは、ランダム化または匿名化された識別子(ハッシュ化された ID やデバイスが生成した UUID など)を使用することがベストプラクティスです。 ## キッズモードの有効化 \{#enabling-kids-mode\} ### Adapty ダッシュボードでの設定 \{#updates-in-the-adapty-dashboard\} Adapty ダッシュボードで IP アドレスの収集を無効化する必要があります。[App settings](https://app.adapty.io/settings/general) に移動し、**Collect users' IP address** の下にある **Disable IP address collection** をクリックしてください。 ### アプリコードの変更 \{#updates-in-your-mobile-app-code\} ポリシーに準拠するために、ユーザーの IDFA と IP アドレスの収集を無効化してください。 <Tabs> <TabItem value="spm" label="Swift Package Manager" default> Swift Package Manager を使用している場合、SDK インストール時に Xcode で **Adapty_KidsMode** モジュールを選択することでキッズモードを有効化できます。 Xcode で **File** -> **Add Package Dependency...** に進んでください。パッケージ依存関係の追加手順は Xcode のバージョンによって異なる場合があるため、必要に応じて Xcode のドキュメントを参照してください。 1. リポジトリ URL を入力します: ``` https://github.com/adaptyteam/AdaptySDK-iOS.git ``` 2. バージョンを選択し(最新の安定版を推奨)、**Add Package** をクリックします。 3. **Choose Package Products** ウィンドウで、必要なモジュールを選択します: - **Adapty_KidsMode**(コアモジュール) - **AdaptyUI_KidsMode**(オプション - ペイウォールビルダーを使用する場合のみ) 他のパッケージは不要です。 4. **Add Package** をクリックしてインストールを完了します。 5. コード内で `import Adapty` の代わりに `import Adapty_KidsMode`、`import AdaptyUI` の代わりに `import AdaptyUI_KidsMode` と記述します: ```swift ``` </TabItem> <TabItem value="cocoapods" label="CocoaPods"> 1. Podfile を更新します: - `post_install` セクションが**ない**場合は、以下のコードブロック全体を追加してください。 - `post_install` セクションが**ある**場合は、ハイライトされた行をそこにマージしてください。 ```ruby showLineNumbers title="Podfile" def adapty_enable_kids_mode(installer) installer.pods_project.targets.each do |target| next unless target.name == 'Adapty' target.build_configurations.each do |config| flags = config.build_settings['OTHER_SWIFT_FLAGS'] || '$(inherited)' flags = flags.join(' ') if flags.is_a?(Array) config.build_settings['OTHER_SWIFT_FLAGS'] = "#{flags} -DADAPTY_KIDS_MODE" end target.frameworks_build_phase.files.dup.each do |bf| target.frameworks_build_phase.remove_build_file(bf) if bf.display_name.to_s.include?('AdSupport') end end installer.pods_project.save Dir.glob(File.join(installer.sandbox.root, 'Target Support Files', '**', '*.xcconfig')).each do |xc| File.write(xc, File.read(xc).gsub(/\s*-framework\s+"?AdSupport"?/, '')) end end post_install do |installer| # ... keep your existing post_install body (Flutter adds one automatically) ... adapty_enable_kids_mode(installer) # <-- enable Adapty Kids Mode end ``` 2. 以下のコマンドを実行して変更を適用します: ```sh showLineNumbers title="Shell" pod install ``` </TabItem> </Tabs> --- # File: get-onboardings --- --- title: "オンボーディングとその設定を取得する" description: "Adapty でオンボーディングを取得する方法を学びましょう。" --- :::tip **SDK v4(ベータ版)以降**、オンボーディングのより強力な代替として[フロー](get-pb-paywalls)を構築できます。オンボーディングが WebView 内で動作するのに対し、フローはデバイス上でネイティブにレンダリングされるため、アニメーションがスムーズになり、iOS の一貫した外観と操作感が得られ、読み込みが速く、WebView ランタイムへの依存もありません。詳しくは [Get flows & paywalls](get-pb-paywalls) および [Display flows & paywalls](ios-present-paywalls) をご覧ください。 ::: Adapty ダッシュボードのビルダーで[オンボーディングのビジュアル部分をデザイン](design-onboarding)したら、モバイルアプリにそれを表示できます。最初のステップは、プレースメントに関連付けられたオンボーディングとそのビュー設定を以下の手順で取得することです。 始める前に、次の点を確認してください: 1. [Adapty iOS、Android、React Native、または Flutter SDK](installation-of-adapty-sdks) バージョン 3.8.0 以上をインストールしていること。 2. [オンボーディングを作成](create-onboarding)していること。 3. オンボーディングを[プレースメント](placements)に追加していること。 ## オンボーディングを取得する \{#fetch-onboarding\} ノーコードビルダーで[オンボーディング](onboardings)を作成すると、アプリが取得して表示する必要のある設定を含むコンテナとして保存されます。このコンテナは、表示されるコンテンツ、表示方法、ユーザーのインタラクション(クイズの回答やフォームの入力など)の処理方法といった全体的なエクスペリエンスを管理します。また、コンテナは自動的にアナリティクスイベントを追跡するため、個別にビュートラッキングを実装する必要はありません。 パフォーマンスを最大限に発揮するために、ユーザーに表示する前に画像をダウンロードする時間を確保できるよう、オンボーディングの設定を早めに取得することをお勧めします。 オンボーディングを取得するには、`getOnboarding` メソッドを使用します: ```swift showLineNumbers do { let onboarding = try await Adapty.getOnboarding(placementId: "YOUR_PLACEMENT_ID") // the requested onboarding } catch { // handle the error } ``` パラメーター: | パラメーター | 必須 / 任意 | 説明 | |---------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **placementId** | 必須 | 取得したい[プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** | <p>任意</p><p>デフォルト: `en`</p> | <p>オンボーディングのローカライズ識別子。このパラメーターは、マイナス(**-**)で区切られた 1 つまたは 2 つのサブタグで構成される言語コードです。最初のサブタグは言語、2 番目のサブタグは地域を表します。</p><p></p><p>例:`en` は英語、`pt-br` はブラジルポルトガル語を表します。</p><p>ロケールコードと推奨される使用方法については、[ローカライズとロケールコード](localizations-and-locale-codes)を参照してください。</p> | | **fetchPolicy** | デフォルト: `.reloadRevalidatingCacheData` | <p>デフォルトでは、SDK はサーバーからデータを読み込もうとし、失敗した場合はキャッシュされたデータを返します。この設定では常に最新のデータが取得できるため、推奨しています。</p><p></p><p>ただし、ユーザーのインターネット接続が不安定な場合は、`.returnCacheDataElseLoad` を使用してキャッシュデータがあればそちらを返すことを検討してください。この場合、最新データが取得できないことがありますが、通信状況に関わらず読み込みが速くなります。キャッシュは定期的に更新されるため、セッション中にネットワークリクエストを減らす目的で安全に使用できます。</p><p></p><p>キャッシュはアプリを再起動しても保持され、アプリの再インストールまたは手動でのクリーンアップ時にのみ消去されます。</p><p></p><p>Adapty SDK はオンボーディングをローカルに 2 層で保存しています:上記の定期更新キャッシュとフォールバックオンボーディングです。また、CDN を使用してオンボーディングをより速く取得し、CDN に接続できない場合に備えてスタンドアロンのフォールバックサーバーも用意しています。このシステムにより、インターネット接続が不安定な場合でも、常に最新バージョンのオンボーディングを確実に取得できます。</p> | | **loadTimeout** | デフォルト: 5 秒 | <p>このメソッドのタイムアウト上限を設定します。タイムアウトに達した場合、キャッシュデータまたはローカルフォールバックが返されます。</p><p>内部で複数のリクエストが実行される場合があるため、まれに `loadTimeout` で指定した時間より少し遅くタイムアウトすることがあります。</p> | レスポンスパラメーター: | パラメーター | 説明 | |:----------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------| | Onboarding | オンボーディング識別子と設定、リモートコンフィグ、その他のプロパティを含む [`AdaptyOnboarding`](https://swift.adapty.io/documentation/adapty/adaptyonboarding) オブジェクト。 | ## デフォルトオーディエンスのオンボーディングで取得を高速化する \{#speed-up-onboarding-fetching-with-default-audience-onboarding\} 通常、オンボーディングはほぼ即座に取得されるため、このプロセスの高速化を特に意識する必要はありません。ただし、オーディエンスやオンボーディングが多数あり、ユーザーのインターネット接続が不安定な場合は、取得に想定以上の時間がかかることがあります。そのような状況では、オンボーディングをまったく表示しないよりも、デフォルトのオンボーディングを表示してスムーズなユーザー体験を提供したい場合があるかもしれません。 これに対応するために、`getOnboardingForDefaultAudience` メソッドを使用できます。このメソッドは、指定したプレースメントの **All Users** オーディエンス向けオンボーディングを取得します。ただし、推奨されるアプローチは上記の[オンボーディングを取得する](#fetch-onboarding)セクションで説明した `getOnboarding` メソッドを使用することです。 :::warning `getOnboardingForDefaultAudience` の代わりに `getOnboarding` の使用を検討してください。前者には以下の重要な制限があります: - **互換性の問題**:複数のアプリバージョンをサポートする場合に問題が生じる可能性があります。後方互換性のあるデザインにするか、古いバージョンで正しく表示されないことを許容する必要があります。 - **パーソナライゼーションなし**:「All Users」オーディエンス向けのコンテンツのみが表示され、国・アトリビューション・カスタム属性に基づくターゲティングが機能しません。 ユースケースにおいて取得の高速化がこれらのデメリットを上回る場合は、以下に示す `getOnboardingForDefaultAudience` を使用してください。そうでない場合は、[上記](#fetch-onboarding)の `getOnboarding` を使用してください。 ::: ```swift showLineNumbers Adapty.getOnboardingForDefaultAudience(placementId: "YOUR_PLACEMENT_ID") { result in switch result { case let .success(onboarding): // the requested onboarding case let .failure(error): // handle the error } } ``` パラメーター: | パラメーター | 必須 / 任意 | 説明 | |---------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **placementId** | 必須 | 取得したい[プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** | <p>任意</p><p>デフォルト: `en`</p> | <p>オンボーディングのローカライズ識別子。このパラメーターは、マイナス(**-**)で区切られた 1 つまたは 2 つのサブタグで構成される言語コードです。最初のサブタグは言語、2 番目のサブタグは地域を表します。</p><p></p><p>例:`en` は英語、`pt-br` はブラジルポルトガル語を表します。</p><p>ロケールコードと推奨される使用方法については、[ローカライズとロケールコード](localizations-and-locale-codes)を参照してください。</p> | | **fetchPolicy** | デフォルト: `.reloadRevalidatingCacheData` | <p>デフォルトでは、SDK はサーバーからデータを読み込もうとし、失敗した場合はキャッシュされたデータを返します。この設定では常に最新のデータが取得できるため、推奨しています。</p><p></p><p>ただし、ユーザーのインターネット接続が不安定な場合は、`.returnCacheDataElseLoad` を使用してキャッシュデータがあればそちらを返すことを検討してください。この場合、最新データが取得できないことがありますが、通信状況に関わらず読み込みが速くなります。キャッシュは定期的に更新されるため、セッション中にネットワークリクエストを減らす目的で安全に使用できます。</p><p></p><p>キャッシュはアプリを再起動しても保持され、アプリの再インストールまたは手動でのクリーンアップ時にのみ消去されます。</p><p></p><p>Adapty SDK はオンボーディングをローカルに 2 層で保存しています:上記の定期更新キャッシュとフォールバックオンボーディングです。また、CDN を使用してオンボーディングをより速く取得し、CDN に接続できない場合に備えてスタンドアロンのフォールバックサーバーも用意しています。このシステムにより、インターネット接続が不安定な場合でも、常に最新バージョンのオンボーディングを確実に取得できます。</p> | --- # File: ios-present-onboardings --- --- title: "iOS SDKでオンボーディングを表示する" description: "iOSでオンボーディングを表示してコンバージョンと収益を高める方法を説明します。" --- :::tip **SDK v4(ベータ版)以降**、オンボーディングのより強力な代替手段として[フロー](get-pb-paywalls)を構築できます。オンボーディングはWebView内で動作しますが、フローはデバイス上でネイティブにレンダリングされるため、スムーズなアニメーション、iOSらしい一貫した外観、高速な読み込み、WebViewランタイムへの依存がなくなります。始めるには[フロー & ペイウォールの取得](get-pb-paywalls)と[フロー & ペイウォールの表示](ios-present-paywalls)をご覧ください。 ::: ビルダーを使ってオンボーディングをカスタマイズした場合、モバイルアプリのコードでレンダリング処理を実装する必要はありません。オンボーディングには、表示内容と表示方法がすべて含まれています。 開始する前に、以下を確認してください: 1. [Adapty iOS SDK](sdk-installation-ios) 3.8.0 以降をインストール済みであること。 2. [オンボーディングを作成](create-onboarding)済みであること。 3. オンボーディングを[プレースメント](placements)に追加済みであること。 ## SwiftでオンボーディングををPresent \{#present-onboardings-in-swift\} デバイス画面にビジュアルオンボーディングを表示するには、以下の手順を実行します: 1. `.getOnboardingConfiguration` メソッドを使ってオンボーディングのビュー設定を取得します。 2. `.onboardingController` メソッドを使って表示したいビジュアルオンボーディングを初期化します: リクエストパラメータ: | パラメータ | 必須/任意 | 説明 | |:-----------------------------|:---------|:----------------------------------------------------------------------------------------------------------------------------------------------------| | **onboarding configuration** | 必須 | オンボーディングのすべてのプロパティを含む `AdaptyUI.OnboardingConfiguration` オブジェクト。`AdaptyUI.getOnboardingConfiguration` メソッドで取得します。 | | **delegate** | 必須 | オンボーディングのイベントを受け取るための `AdaptyOnboardingControllerDelegate`。 | 戻り値: | オブジェクト | 説明 | |:-------------------------------|:--------------------------------------------------------| | **AdaptyOnboardingController** | リクエストされたオンボーディング画面を表すオブジェクト | 3. オブジェクトの作成に成功したら、デバイスの画面に表示できます: ```swift showLineNumbers title="Swift" import Adapty import AdaptyUI // 0. Get an onboarding if you haven't done it yet let onboarding = try await Adapty.getOnboarding(placementId: "YOUR_PLACEMENT_ID") // 1. Obtain the onboarding view configuration: let configuration = try AdaptyUI.getOnboardingConfiguration(forOnboarding: onboarding) // 2. Create Onboarding View Controller let onboardingController = try AdaptyUI.onboardingController( with: configuration, delegate: <AdaptyOnboardingControllerDelegate> ) // 3. Present it to the user present(onboardingController, animated: true) ``` ## SwiftUIでオンボーディングをPresent \{#present-onboardings-in-swiftui\} SwiftUIでデバイス画面にビジュアルオンボーディングを表示するには: ```swift showLineNumbers title="SwiftUI" // 1. Obtain the onboarding view configuration: let configuration = try AdaptyUI.getOnboardingConfiguration(forOnboarding: onboarding) // 2. Display the Onboarding View within your view hierarchy AdaptyOnboardingView( configuration: configuration, placeholder: { Text("Your Placeholder View") }, onCloseAction: { action in // hide the onboarding view }, onError: { error in // handle the error } ) ``` ## スプラッシュ画面とオンボーディング間のトランジションをスムーズにする \{#add-smooth-transitions-between-the-splash-screen-and-onboarding\} デフォルトでは、スプラッシュ画面とオンボーディングの間、オンボーディングが完全に読み込まれるまでローディング画面が表示されます。よりスムーズなトランジションにしたい場合は、スプラッシュ画面を延長したり、別のコンテンツを表示するようにカスタマイズできます。 そのためには、プレースホルダー(オンボーディングの読み込み中に表示するもの)を定義してください。プレースホルダーを定義すると、オンボーディングはバックグラウンドで読み込まれ、準備ができ次第自動的に表示されます。 <Tabs> <TabItem value="swift" label="UIKit"> ```swift showLineNumbers extension YourOnboardingManagerClass: AdaptyOnboardingControllerDelegate { func onboardingsControllerLoadingPlaceholder( _ controller: AdaptyOnboardingController ) -> UIView? { // instantiate and return the UIView which will be presented while onboarding is being loaded } } ``` </TabItem> <TabItem value="swiftui" label="SwiftUI"> ```swift showLineNumbers AdaptyOnboardingView( configuration: configuration, placeholder: { // define your placeholder view, which will be presented while onboarding is being loaded }, // the rest of the implementation ) ``` </TabItem> </Tabs> ## オンボーディング内のリンクの開き方をカスタマイズする \{#customize-how-links-open-in-onboardings\} :::important オンボーディング内のリンクの開き方のカスタマイズは、Adapty SDK v3.15.1 以降でサポートされています。 ::: デフォルトでは、オンボーディング内のリンクはアプリ内ブラウザで開きます。これにより、アプリを切り替えることなくウェブページをアプリ内で表示でき、シームレスなユーザー体験を提供します。 外部ブラウザでリンクを開きたい場合は、`externalUrlsPresentation` パラメータを `.externalBrowser` に設定することでこの動作をカスタマイズできます: ```swift showLineNumbers let configuration = try AdaptyUI.getOnboardingConfiguration( forOnboarding: onboarding, externalUrlsPresentation: .externalBrowser // default – .inAppBrowser ) ``` --- # File: ios-handling-onboarding-events --- --- title: "iOS SDKでオンボーディングイベントを処理する" description: "AdaptyのiOSを使用してオンボーディング関連のイベントを処理します。" --- :::tip **SDK v4(ベータ版)以降**、オンボーディングよりも強力な代替手段として[フロー](get-pb-paywalls)を構築できます。オンボーディングがWebView内で動作するのに対し、フローはデバイス上でネイティブにレンダリングされます。これにより、よりスムーズなアニメーション、一貫したiOSのルック&フィール、高速な読み込み、そしてWebViewランタイムへの依存がなくなります。はじめに[フロー&ペイウォールを取得する](get-pb-paywalls)と[フロー&ペイウォールを表示する](ios-present-paywalls)をご覧ください。 ::: 始める前に、以下を確認してください。 1. [Adapty iOS SDK](sdk-installation-ios) 3.8.0以降をインストール済みであること。 2. [オンボーディングを作成](create-onboarding)済みであること。 3. オンボーディングを[プレースメント](placements)に追加済みであること。 ビルダーで設定されたオンボーディングは、アプリが応答できるイベントを生成します。これらのイベントへの応答方法について以下で説明します。 モバイルアプリのオンボーディング画面で発生するプロセスを制御または監視するには、`AdaptyOnboardingControllerDelegate`のメソッドを実装します。 ## カスタムアクション \{#custom-actions\} ビルダーでは、ボタンに**カスタム**アクションを追加してIDを割り当てることができます。 <img src="/assets/shared/img/ios-events-1.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> このIDをコード内で使用し、カスタムアクションとして処理できます。たとえば、ユーザーが**ログイン**や**通知を許可**などのカスタムボタンをタップすると、デリゲートメソッド`onboardingController`が`.custom(id:)`ケースでトリガーされ、`actionId`パラメータはビルダーの**Action ID**になります。"allowNotifications"のような独自のIDを作成できます。 ```swift showLineNumbers func onboardingController(_ controller: AdaptyOnboardingController, onCustomAction action: AdaptyOnboardingsCustomAction) { if action.actionId == "allowNotifications" { // Request notification permissions } } func onboardingController(_ controller: AdaptyOnboardingController, didFailWithError error: AdaptyUIError) { // Handle errors } ``` <Details> <summary>イベントの例(クリックして展開)</summary> ```json { "actionId": "allowNotifications", "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 0, "screensTotal": 3 } } ``` </Details> ## オンボーディングを閉じる \{#closing-onboarding\} オンボーディングは、ユーザーが**閉じる**アクションが割り当てられたボタンをタップすると閉じられたと見なされます。 <img src="/assets/shared/img/ios-events-2.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> :::important ユーザーがオンボーディングを閉じたときの処理を自分で実装する必要があります。たとえば、オンボーディング自体の表示を停止する必要があります。 ::: 例: ```swift showLineNumbers func onboardingController(_ controller: AdaptyOnboardingController, onCloseAction action: AdaptyOnboardingsCloseAction) { controller.dismiss(animated: true) } ``` <Details> <summary>イベントの例(クリックして展開)</summary> ```json { "action_id": "close_button", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "final_screen", "screen_index": 3, "total_screens": 4 } } ``` </Details> ## ペイウォールを開く \{#opening-a-paywall\} :::tip オンボーディング内でペイウォールを開きたい場合はこのイベントを処理してください。オンボーディングが閉じた後にペイウォールを開きたい場合は、[`AdaptyOnboardingsCloseAction`](#closing-onboarding)を処理してイベントデータに依存せずにペイウォールを開く、よりシンプルな方法があります。 ::: オンボーディングでペイウォールをシームレスに扱う最善の方法は、アクションIDをペイウォールのプレースメントIDと同じにすることです。これにより、`AdaptyOnboardingsOpenPaywallAction`の後、プレースメントIDを使用してすぐにペイウォールを取得して開くことができます。 一度に表示できるビュー(ペイウォールまたはオンボーディング)は1つだけです。オンボーディングの上にペイウォールを表示すると、バックグラウンドのオンボーディングをプログラムで制御することができません。オンボーディングを閉じようとすると、代わりにペイウォールが閉じられ、オンボーディングが表示されたままになります。これを避けるために、ペイウォールを表示する前に必ずオンボーディングビューを閉じてください。 ```swift showLineNumbers func onboardingController(_ controller: AdaptyOnboardingController, onPaywallAction action: AdaptyOnboardingsOpenPaywallAction) { // Dismiss onboarding before presenting the flow controller.dismiss(animated: true) { Task { do { // Get the flow using the placement ID from the action let flow = try await Adapty.getFlow(placementId: action.actionId) // Get the flow configuration let flowConfiguration = try await AdaptyUI.getFlowConfiguration( forFlow: flow ) // Create and present the flow controller let flowController = try AdaptyUI.flowController( with: flowConfiguration, delegate: self ) // Present the flow from the root view controller if let rootVC = UIApplication.shared.windows.first?.rootViewController { rootVC.present(flowController, animated: true) } } catch { // Handle any errors that occur during flow loading print("Failed to present flow: \(error)") } } } } ``` <Details> <summary>イベントの例(クリックして展開)</summary> ```json { "action_id": "premium_offer_1", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "pricing_screen", "screen_index": 2, "total_screens": 4 } } ``` </Details> ## オンボーディングの読み込み完了 \{#finishing-loading-onboarding\} オンボーディングの読み込みが完了すると、このメソッドが呼び出されます。 ```swift showLineNumbers func onboardingController(_ controller: AdaptyOnboardingController, didFinishLoading action: OnboardingsDidFinishLoadingAction) { // Handle loading completion } ``` <Details> <summary>イベントの例(クリックして展開)</summary> ```json { "meta": { "onboarding_id": "onboarding_123", "screen_cid": "welcome_screen", "screen_index": 0, "total_screens": 4 } } ``` </Details> ## ナビゲーションの追跡 \{#tracking-navigation\} `onAnalyticsEvent`メソッドは、オンボーディングフロー中にさまざまなアナリティクスイベントが発生したときに呼び出されます。 `event`オブジェクトは以下のいずれかのタイプになります。 |タイプ | 説明 | |------------|-------------| | `onboardingStarted` | オンボーディングが読み込まれたとき | | `screenPresented` | 任意の画面が表示されたとき | | `screenCompleted` | 画面が完了したとき。オプションの`elementId`(完了した要素の識別子)とオプションの`reply`(ユーザーからの回答)が含まれます。ユーザーが画面を離れるためのアクションを実行したときにトリガーされます。 | | `secondScreenPresented` | 2番目の画面が表示されたとき | | `userEmailCollected` | 入力フィールドを通じてユーザーのメールアドレスが収集されたときにトリガーされます | | `onboardingCompleted` | ユーザーが`final` IDを持つ画面に到達したときにトリガーされます。このイベントが必要な場合は、[最後の画面に`final` IDを割り当ててください](design-onboarding)。 | | `unknown` | 認識できないイベントタイプの場合。`name`(不明なイベントの名前)と`meta`(追加のメタデータ)が含まれます | 各イベントには以下を含む`meta`情報が含まれます。 | フィールド | 説明 | |------------|-------------| | `onboardingId` | オンボーディングフローの一意の識別子 | | `screenClientId` | 現在の画面の識別子 | | `screenIndex` | フロー内の現在の画面の位置 | | `screensTotal` | フロー内の画面の総数 | 以下はアナリティクスイベントをトラッキングに使用する例です。 ```swift func onboardingController(_ controller: AdaptyOnboardingController, onAnalyticsEvent event: AdaptyOnboardingsAnalyticsEvent) { switch event { case .onboardingStarted(let meta): // Track onboarding start trackEvent("onboarding_started", meta: meta) case .screenPresented(let meta): // Track screen presentation trackEvent("screen_presented", meta: meta) case .screenCompleted(let meta, let elementId, let reply): // Track screen completion with user response trackEvent("screen_completed", meta: meta, elementId: elementId, reply: reply) case .onboardingCompleted(let meta): // Track successful onboarding completion trackEvent("onboarding_completed", meta: meta) case .unknown(let meta, let name): // Handle unknown events trackEvent(name, meta: meta) // Handle other cases as needed } } ``` <Details> <summary>イベントの例(クリックして展開)</summary> ```javascript // onboardingStarted { "name": "onboarding_started", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "welcome_screen", "screen_index": 0, "total_screens": 4 } } // screenPresented { "name": "screen_presented", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "interests_screen", "screen_index": 2, "total_screens": 4 } } // screenCompleted { "name": "screen_completed", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "profile_screen", "screen_index": 1, "total_screens": 4 }, "params": { "element_id": "profile_form", "reply": "success" } } // secondScreenPresented { "name": "second_screen_presented", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "profile_screen", "screen_index": 1, "total_screens": 4 } } // userEmailCollected { "name": "user_email_collected", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "profile_screen", "screen_index": 1, "total_screens": 4 } } // onboardingCompleted { "name": "onboarding_completed", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "final_screen", "screen_index": 3, "total_screens": 4 } } ``` </Details> --- # File: ios-onboarding-input --- --- title: "iOS SDKでオンボーディングのデータを処理する" description: "Adapty SDKを使用して、iOSアプリのオンボーディングからデータを保存・活用する方法を説明します。" --- :::tip **SDK v4(ベータ版)以降**、オンボーディングのより強力な代替手段として[フロー](get-pb-paywalls)を構築できます。オンボーディングがWebView内で動作するのに対し、フローはデバイス上でネイティブにレンダリングされるため、よりスムーズなアニメーション、一貫したiOSの外観、高速な読み込み、そしてWebViewランタイムへの依存がなくなります。詳細は[フローとペイウォールの取得](get-pb-paywalls)および[フローとペイウォールの表示](ios-present-paywalls)をご覧ください。 ::: ユーザーがクイズの質問に回答したり、入力フィールドにデータを入力したりすると、`onStateUpdatedAction` メソッドが呼び出されます。フィールドの種類をコード内で保存または処理することができます。 例: ```swift showLineNumbers func onboardingController(_ controller: AdaptyOnboardingController, onStateUpdatedAction action: AdaptyOnboardingsStateUpdatedAction) { // Store user preferences or responses switch action.params { case .select(let params): // Handle single selection case .multiSelect(let params): // Handle multiple selections case .input(let params): // Handle text input case .datePicker(let params): // Handle date selection } } ``` `action` オブジェクトに含まれる情報: | パラメーター | 説明 | |----------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `elementId` | 入力要素の一意の識別子です。回答を保存する際に、質問と回答を紐付けるために使用できます。 | | `params` | ユーザーの入力データオブジェクトで、typeとvalueのプロパティを含みます。 | | `params.type` | 入力要素のタイプです。以下のいずれかになります:<br/>• `"select"` - オプションからの単一選択<br/>• `"multiSelect"` - オプションからの複数選択<br/>• `"input"` - テキスト入力フィールド<br/>• `"datePicker"` - 日付選択 | | `params.value` | ユーザーが選択または入力した値です。構造はタイプによって異なります:<br/>• `select`:`id`、`value`、`label` を持つオブジェクト<br/>• `multiSelect`:`id`、`value`、`label` を持つオブジェクトの配列<br/>• `input`:`type`、`value` を持つオブジェクト<br/>• `datePicker`:`day`、`month`、`year` を持つオブジェクト | <Details> <summary>保存されたデータの例(実装によって異なる場合があります)</summary> ```javascript // Example of a saved select action { "elementId": "preference_selector", "meta": { "onboardingId": "onboarding_123", "screenClientId": "preferences_screen", "screenIndex": 1, "screensTotal": 3 }, "params": { "type": "select", "value": { "id": "option_1", "value": "premium", "label": "Premium Plan" } } } // Example of a saved multi-select action { "elementId": "interests_selector", "meta": { "onboardingId": "onboarding_123", "screenClientId": "interests_screen", "screenIndex": 2, "screensTotal": 3 }, "params": { "type": "multiSelect", "value": [ { "id": "interest_1", "value": "sports", "label": "Sports" }, { "id": "interest_2", "value": "music", "label": "Music" } ] } } // Example of a saved input action { "elementId": "name_input", "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 0, "screensTotal": 3 }, "params": { "type": "input", "value": { "type": "text", "value": "John Doe" } } } // Example of a saved date picker action { "elementId": "birthday_picker", "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 0, "screensTotal": 3 }, "params": { "type": "datePicker", "value": { "day": 15, "month": 6, "year": 1990 } } } ``` </Details> ## ユースケース \{#use-cases\} ### ユーザープロファイルをデータで充実させる \{#enrich-user-profiles-with-data\} 入力データをユーザープロファイルにすぐに紐付けて、同じ情報を二度聞かないようにするには、アクションを処理する際に入力データで[ユーザープロファイルを更新](setting-user-attributes)する必要があります。 例えば、`name` というIDを持つテキストフィールドにユーザーの名前を入力してもらい、そのフィールドの値をユーザーの名前として設定したいとします。また、`email` フィールドにメールアドレスを入力してもらう場合、アプリのコードは次のようになります: ```swift showLineNumbers func onboardingController(_ controller: AdaptyOnboardingController, onStateUpdatedAction action: AdaptyOnboardingsStateUpdatedAction) { // Store user preferences or responses switch action.params { case .input(let params): // Handle text input let builder = AdaptyProfileParameters.Builder() // Map elementId to appropriate profile field switch action.elementId { case "name": builder.with(firstName: params.value.value) case "email": builder.with(email: params.value.value) default: break } // Delegate methods are synchronous; kick off the async update in a Task. Task { do { try await Adapty.updateProfile(params: builder.build()) } catch { // handle the error } } default: break } } ``` ### 回答に基づいてペイウォールをカスタマイズする \{#customize-paywalls-based-on-answers\} オンボーディングのクイズを活用して、ユーザーがオンボーディングを完了した後に表示するペイウォールをカスタマイズすることもできます。 例えば、スポーツの経験について質問し、ユーザーグループごとに異なるCTAとプロダクトを表示することができます。 1. オンボーディングビルダーで[クイズを追加](onboarding-quizzes)し、各オプションにわかりやすいIDを割り当てます。 2. IDに基づいてクイズの回答を処理し、ユーザーに[カスタム属性を設定](setting-user-attributes)します。 ```swift showLineNumbers func onboardingController(_ controller: AdaptyOnboardingController, onStateUpdatedAction action: AdaptyOnboardingsStateUpdatedAction) { // Handle quiz responses and set custom attributes switch action.params { case .select(let params): // Handle quiz selection let builder = AdaptyProfileParameters.Builder() // Map quiz responses to custom attributes switch action.elementId { case "experience": // Set custom attribute 'experience' with the selected value (beginner, amateur, pro) try? builder.with(customAttribute: params.value.value, forKey: "experience") default: break } // Delegate methods are synchronous; kick off the async update in a Task. Task { do { try await Adapty.updateProfile(params: builder.build()) } catch { // handle the error } } default: break } } ``` 3. カスタム属性の値ごとに[セグメントを作成](segments)します。 4. [プレースメント](placements)を作成し、作成した各セグメントの[オーディエンス](audience)を追加します。 5. アプリのコードでそのプレースメントの[ペイウォールを表示](ios-paywalls)します。オンボーディングにペイウォールを開くボタンがある場合は、[そのボタンのアクションへの応答](ios-handling-onboarding-events#opening-a-paywall)としてペイウォールのコードを実装してください。 --- # File: ios-sdk-call-order --- --- title: "iOS SDKの呼び出し順序" description: "Adapty SDKのメソッドを正しい順序で呼び出すことで、プレミアムアクセスの喪失、アトリビューションの欠落、断続的な #2002 エラーを防ぎます。" --- `Adapty.activate()` が完了するまで、他のAdapty SDKメソッドを呼び出してはいけません。解決されるまで、SDKには状態がありません。`activate()` の前または並行して発行された呼び出しはすべて [`#2002 notActivated`](ios-sdk-error-handling#network-errors) で失敗します。 アプリがユーザー認証を行い、起動後にカスタマーユーザーIDを取得する場合は、そのタイミングで `Adapty.identify()` を呼び出してください。`identify` が解決するまでユーザーアクションメソッドを呼び出さないでください。`identify` と競合する呼び出しは [`#3006 profileWasChanged`](ios-sdk-error-handling#general-errors) で失敗するか、アクティベーション時に作成された匿名プロファイルに対して実行されます。これが起きると、アトリビューション、`appsflyer_id` などのMMP ID、インストールの帰属が識別済みプロファイルに転送されないことがあります。アプリがユーザー認証を行わない場合は、`identify` をスキップして匿名プロファイルのまま使用してください。 MMP・アナリティクスSDK(AppsFlyer、Adjust、Branch、PostHog)も同じルールに従います。それらを先に初期化し、UIDコールバックを待ってから `Adapty.activate` を呼び出してください。そうしないと、MMP IDが短命な匿名プロファイルに紐づき、識別済みプロファイルに常に転送されるとは限りません。AppsFlyerの詳細については、[AppsFlyer](appsflyer) を参照してください。 ## 正しい順序 \{#the-correct-order\} どのパスを取るかは、カスタマーユーザーIDをいつ知るか、そしてMMPまたはアナリティクスSDKを使用するかどうかの2点によって決まります。 - **ステップ2と5**:すべてのアプリで必須です。SDKをアクティベートし、その後SDKメソッドを呼び出します。 - **ステップ1と3**:MMPまたはアナリティクスSDK(AppsFlyer、Adjust、Branch、PostHog)を統合する場合のみ必要です。 - **ステップ4**:アプリがユーザー認証を行い、起動後にカスタマーユーザーIDを収集する場合のみ必要です。 アプリ起動時にカスタマーユーザーIDがある場合は、`activate()` に直接渡してください(ステップ2a)。このパスでは匿名プロファイルが作成されないため、ステップ4は不要です。 | ステップ | 呼び出し | タイミング | 備考 | |------|---------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------| | 1 | MMPまたはアナリティクスSDKの初期化(AppsFlyer、Adjust、PostHog、Branch) | アプリ起動時、最初に | MMPのUIDコールバック(例:`getAppsFlyerUID`)を待ってください。 | | 2a | `Adapty.activate(with: config)` に `customerUserId` をconfigに設定して呼び出す | アプリ起動時、ステップ1の後、カスタマーユーザーIDがある場合 | 推奨。匿名プロファイルは一切作成されません。 | | 2b | `Adapty.activate(with: config)` に `customerUserId` を設定せずに呼び出す | アプリ起動時、ステップ1の後、カスタマーユーザーIDがない場合(または収集しない場合) | Adaptyが匿名プロファイルを作成します。 | | 3 | 各MMPに対して `Adapty.setIntegrationIdentifier(...)` を呼び出す | ステップ2の後、ユーザーアクション呼び出しの前 | MMP IDが正しいプロファイルに紐づくために必要です。 | | 4 | `try await Adapty.identify("YOUR_USER_ID")` | ステップ3の後(またはMMPがない場合はステップ2の後)、ステップ5の前 — 認証ありのパス2bのみ | 必ず `await` してください。`identify` 中の並行呼び出しは `#3006 profileWasChanged` を発生させます。 | | 5 | `getPaywall`、`getPaywallProducts`、`restorePurchases`、`makePurchase`、`updateAttribution`、`updateProfile` | `identify` を呼び出す場合はステップ4の後、それ以外はステップ3の後(またはMMPがない場合はステップ2の後) | これらの呼び出しには安定したプロファイルが必要です。 | :::important これらのステップを省略すると、リターンユーザーのプレミアムアクセスの喪失、プロファイルへの `appsflyer_id` の欠落、間違ったオーディエンスに対してペイウォールが返される問題が発生します。 ::: ## Web2appとWebファネルのインストール \{#web2app-and-web-funnel-installs\} ユーザーがWebチェックアウト(Stripe、Paddle、FunnelFox)で購入し、その後ネイティブアプリをインストールする場合、デバイスで最初に `activate()` が呼ばれると新しい匿名プロファイルが作成されます。このプロファイルはWebプロファイルとリンクされていません。アプリ起動前にカスタマーユーザーIDを解決できる場合(認証フローやインストールリファラーから)、`activate()` に直接渡してください。そうしないと、`identify("YOUR_USER_ID")` を呼び出してから `restorePurchases` を実行するまで、Web購入はデバイスから見えません。 各Webチェックアウトで送信するメタデータについては、以下を参照してください: - [Stripe](stripe) - [Paddle](paddle) --- # File: ios-optimize-paywall-fetching --- --- title: "iOS SDKでペイウォールのフェッチを最適化する" description: "AdaptyのペイウォールをiOSで確実にフェッチする:タイミング、キャッシュ、フォールバックのパターン。" --- iOSで信頼性の高いペイウォールフェッチを実現するには、3つの要件を満たす必要があります。高速なレンダリング、オーディエンスターゲットに合ったペイウォールの返却、そしてネットワークが遅い場合のグレースフルなフォールバックです。以下のルールでは、それを実現するためのタイミング、キャッシュ、フォールバックのパターンを説明します。 :::tip 以下のルールは、`Adapty.activate()` と `Adapty.identify()` がすでに解決済みであることを前提としています。[iOS SDKのコール順序](ios-sdk-call-order)を参照してください。 ::: ## ルールと注意点 \{#rules-and-pitfalls\} | 推奨事項 | 避けるべき事項 | 理由 | |---|---|---| | 表示しようとしているプレースメントをフェッチする。 | 起動時にすべてのプレースメントを並列でプリフェッチする。 | 一括プリフェッチはメインスレッドをブロックし、バースト中に画面が真っ暗になる。 | | アトリビューションが解決される時間を確保してから `getPaywall` をフェッチする(例:`activate` から1〜2秒後、または `onProfileUpdate` が発火した後)。 | `App.init()` で `getPaywall` を呼び出す。 | アトリビューションがまだ取得されていない。ペイウォールはデフォルトのオーディエンスに対して解決され、セグメントやASAパーソナライゼーションが静かにバイパスされる。 | | `loadTimeout` を設定し、すべてのプレースメントに[フォールバックペイウォール](fallback-paywalls)を設定する。 | `getPaywall` を無期限に待機する。 | タイムアウトなしでは、接続が悪いユーザーはネットワークが解決するまで空白の画面を見続けるか、アプリを閉じてしまう。 | `fetchPolicy` と `loadTimeout` パラメーターのリファレンスについては[ペイウォールとプロダクトのフェッチ](fetch-paywalls-and-products)を、適切なプレースメントの選択については[プレースメント](placements)を参照してください。 ## 接続が悪い環境向けの調整 \{#tune-for-poor-connectivity\} 接続が安定しない市場(農村部、移動中、ルーティングの問題が多い地域)向けには: - 最初のフェッチを除くすべてのフェッチで `fetchPolicy: .returnCacheDataElseLoad` を設定する。 - Adapty ダッシュボードですべてのプレースメントに[フォールバックペイウォール](fallback-paywalls)を設定する。 - `loadTimeout` を3〜5秒に設定し、タイムアウトが発生した場合はフォールバックを受け入れる。 - ペイウォールの表示を `getProfile()` に依存させない。`getPaywall` は独立して呼び出すことで、プロファイルの取得が遅くてもUIをブロックしないようにする。 --- # File: ios-show-aa-targeted-paywall --- --- title: "iOS SDK の初回起動時に AA ターゲティングのペイウォールを表示する" description: "AdaptyProfile.appliedAttributionSources を使って、iOS で Apple Ads のアトリビューションを待ってからペイウォールをリクエストする方法。" --- Apple Ads(AA)のアトリビューションは、`Adapty.activate()` の後に非同期で届きます。`getPaywall` を早いタイミングで呼び出すと、アトリビューションがまだ反映されていないことが多く、Adapty はデフォルトのオーディエンスに対してプレースメントを解決してしまいます — つまり AA セグメントのペイウォールが適用されません。`AdaptyProfile.appliedAttributionSources` を使うと、AA アトリビューションがプロファイルに適用されたタイミングをアプリが検知できるため、AA セグメントが正しく解決されるまでペイウォールのリクエストを待機させられます。 ## はじめる前に \{#before-you-start\} 必要なもの: - Adapty iOS SDK **3.17.1** 以降。 - Adapty でアプリの Apple Ads を設定済みであること。詳しくは [Apple Ads](apple-search-ads) を参照してください。 ## 仕組み \{#how-it-works\} `Adapty.activate()` の後、SDK はバックグラウンドで Apple から Apple Ads のアトリビューションをリクエストし、その結果を Adapty のバックエンドに転送します。AA がプロファイルのアクティブなアトリビューションソースになると、SDK は更新された `AdaptyProfile` を配信します。この `appliedAttributionSources` 配列には `.appleAds` が含まれています。 配列が空の場合、以下のいずれかを意味します: - このプロファイルの Apple Ads アトリビューションがまだ処理されていない。 - アトリビューションが届いていない。 配列が空でも `getPaywall` の呼び出し自体は安全です — Adapty は現在のプロファイル状態に一致するオーディエンス(通常はデフォルトのオーディエンス)に対してリクエストを解決します。 :::important この待機処理は**初回起動時のみ**適用されます。Apple Ads のアトリビューションが一度記録されると、プロファイルに永続的に保存されます。2 回目以降の起動では、キャッシュされたプロファイルにすでに `.appleAds` が `appliedAttributionSources` に含まれているため、`didLoadLatestProfile` はその値ですぐに発火し、`getPaywall` は遅延なく Apple Ads セグメントのペイウォールを返します。 ::: ## 実装 \{#implementation\} 初回起動時は、プロファイル内の `.appleAds` を監視しながら、厳格なタイムアウトを設定してください — Apple Ads のアトリビューションが届かない場合でも、ユーザーにはペイウォールを表示する必要があります。 1. **SDK を有効化します。** [iOS SDK のインストールと設定](sdk-installation-ios) を参照してください。 2. **`AdaptyDelegate` に準拠して `didLoadLatestProfile` を実装することでプロファイルの更新を購読します。** デリゲートをまだ設定していない場合は、[サブスクリプションのアップデートを監視する](ios-check-subscription-status#listen-to-subscription-updates) を参照してください。 3. **`appliedAttributionSources` に `.appleAds` が含まれているか監視します。** 含まれている場合にペイウォールをリクエストすると、Adapty は AA セグメントのバリアントを返します: ```swift extension <YourAdaptyDelegateImpl>: AdaptyDelegate { nonisolated func didLoadLatestProfile(_ profile: AdaptyProfile) { if profile.appliedAttributionSources.contains(where: { $0 == .appleAds }) { // load paywall via Adapty.getPaywall(placementId:) } } } ``` 4. **購読と並行して 3〜5 秒のタイマーを開始します。** タイマーが先に発火した場合は、`.appleAds` が現れなくてもペイウォールをリクエストします: どちらのパスが先に発火しても、その時点でペイウォールを読み込み、もう一方のパスはスキップします。ペイウォールが 2 回フェッチされないよう、単一の状態フラグ(例:`hasLoadedPaywall`)を使って重複を排除してください。ネットワークリクエストが失敗してもユーザーが詰まらないよう、プレースメントに [フォールバックペイウォール](fallback-paywalls) を設定してください。 ## 完全なサンプル \{#complete-example\} 以下の実装は、アトリビューションとタイムアウトを競争させ、デフォルトのオーディエンスのペイウォールを並行してプリフェッチし、適切なペイウォールを返します。呼び出し元は単一の非同期関数を await するだけで、呼び出し側でデリゲートや状態フラグを管理する必要はありません。 `ProfileObserver` は `AdaptyDelegate` からプロファイルの更新を公開する再利用可能なシングルトンです。`PaywallLoader.getPaywallOrDefault` は structured concurrency の `TaskGroup` を使って競争を実行します: - タイムアウト内にアトリビューションが届いた場合、`getPaywall(placementId:)` を通じてセグメント化されたペイウォールを返します。 - `timeout` が先に経過した場合、`getPaywallForDefaultAudience(placementId:)` を通じてプリフェッチ済みのデフォルトオーディエンスのペイウォールを返します。 ```swift title="PaywallLoader.swift" /// Demonstrates how to fetch a paywall that depends on attribution being applied, /// falling back to the default-audience paywall if attribution doesn't arrive in time. /// /// Stateless and self-contained: every call kicks off its own default-audience /// prefetch and races it against attribution + segmented fetch. enum PaywallLoader { static func getPaywallOrDefault( placementId: String, timeout: TimeInterval ) async throws -> AdaptyPaywall { struct TimedOut: Error {} // Kick off the default-audience request immediately so it has the full // `timeout` window to load. We'll either cancel it on success or await // its result on timeout — never a duplicate network call. let defaultPaywallTask = Task { try await Adapty.getPaywallForDefaultAudience(placementId: placementId) } do { // Race two child tasks: whichever finishes first wins. let result = try await withThrowingTaskGroup(of: AdaptyPaywall.self) { group in // 1. Wait for attribution, then ask Adapty for the segmented paywall. group.addTask { await waitForAttribution() return try await Adapty.getPaywall(placementId: placementId) } // 2. Time-bomb: throws `TimedOut` after `timeout` seconds. group.addTask { try await Task.sleep(nanoseconds: UInt64(timeout * 1_000_000_000)) throw TimedOut() } guard let value = try await group.next() else { throw CancellationError() } group.cancelAll() // stop the loser (sleeper or the attribution wait). return value } // Segmented paywall won — we no longer need the default-audience prefetch. defaultPaywallTask.cancel() return result } catch is TimedOut { // Attribution didn't apply in time — return the prefetched default // (instant if already done, otherwise we await the in-flight request). return try await defaultPaywallTask.value } } /// Suspends until a profile with the desired attribution source is observed. /// `@Published.values` emits the current profile immediately on subscription, /// so this returns on the first iteration if attribution is already applied. @MainActor private static func waitForAttribution() async { for await profile in ProfileObserver.shared.$profile.values { if profile?.appliedAttributionSources.contains(.appleAds) == true { return } } } } @MainActor final class ProfileObserver: AdaptyDelegate { static let shared = ProfileObserver() @Published private(set) var profile: AdaptyProfile? nonisolated func didLoadLatestProfile(_ profile: AdaptyProfile) { Task { @MainActor [weak self] in self?.profile = profile } } } ``` `Adapty.activate()` の完了後、一度だけ `ProfileObserver` を `AdaptyDelegate` に接続します: ```swift Adapty.delegate = ProfileObserver.shared ``` スプラッシュスクリーンから呼び出します: ```swift do { let paywall = try await PaywallLoader.getPaywallOrDefault( placementId: "YOUR_PLACEMENT_ID", timeout: 5 ) // present the paywall } catch { // handle the error or show a fallback paywall } ``` 他の目的(例:[サブスクリプションのアップデートを監視する](ios-check-subscription-status#listen-to-subscription-updates))のために既に `AdaptyDelegate` を使用している場合は、`Adapty.delegate = ProfileObserver.shared` を設定する代わりに、既存のデリゲートから `ProfileObserver.shared` に `didLoadLatestProfile` を転送してください。 --- # File: ios-test --- --- title: "iOSSDKのテストとリリース" description: "AdaptyでiOSアプリのサブスクリプション状態を確認する方法を学びましょう。" --- AdaptyのSDKをiOSアプリに実装したら、すべてが正しく設定されており、購入が期待どおりに動作することをテストしましょう。これには、SDKの統合と実際の購入の両方のテストが含まれます。 ## アプリをテストする \{#test-your-app\} サンドボックステストやTestFlightの検証を含むアプリ内課金の包括的なテストについては、[テストガイド](test-purchases-in-sandbox)をご覧ください。 ## リリースの準備 \{#prepare-for-release\} アプリをストアに申請する前に、[リリースチェックリスト](release-checklist)に従って以下を確認してください: - ストア接続とサーバー通知が設定されている - 購入が完了し、Adaptyに報告されている - アクセスが正しく解除および復元される - プライバシーおよびレビュー要件が満たされている --- # File: InvalidProductIdentifiers --- --- title: "Code-1000 noProductIDsFound エラーの修正" description: "Adapty でサブスクリプションを管理する際の無効なプロダクト識別子エラーを解決します。" --- 1000 コードエラー `noProductIDsFound` は、ペイウォールでリクエストしたプロダクトが App Store に登録されているにもかかわらず、購入可能な状態でないことを示します。このエラーには `InvalidProductIdentifiers` の警告が伴う場合があります。エラーなしに警告だけが表示される場合は、無視して問題ありません。 `noProductIDsFound` エラーが発生している場合は、以下の手順で解決してください。 ## ステップ 1. Bundle ID を確認する \{#step-2-check-bundle-id\} --- no_index: true --- 1. [App Store Connect](https://appstoreconnect.apple.com/apps) を開きます。アプリを選択し、**General** → **App Information** セクションに進みます。 2. **General Information** サブセクションで **Bundle ID** をコピーします。 <Zoom> <img src="/docs/img/afd5012-bundle_id_apple.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> </Zoom> 3. Adapty のトップメニューから [**App settings** -> **iOS SDK** タブ](https://app.adapty.io/settings/ios-sdk) を開き、コピーした値を **Bundle ID** フィールドに貼り付けます。 <Zoom> <img src="/docs/img/2d64163-bundle_id.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> </Zoom> 4. App Store Connect の **App information** ページに戻り、**Apple ID** をコピーします。 5. Adapty ダッシュボードの [**App settings** -> **iOS SDK**](https://app.adapty.io/settings/ios-sdk) ページで、**Apple app ID** フィールドにその ID を貼り付けます。 ## ステップ 2. プロダクトを確認する \{#step-2-check-products\} 1. **App Store Connect** を開き、左側のメニューから [**Monetization** → **Subscriptions**](https://appstoreconnect.apple.com/apps/6477523342/distribution/subscriptions) に移動します。 <img src="/assets/shared/img/subscription_group_open.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. サブスクリプショングループ名をクリックすると、**Subscriptions** セクションにプロダクトの一覧が表示されます。 3. テスト対象のプロダクトが **Ready to Submit** になっていることを確認してください。なっていない場合は、[App Store のプロダクト](app-store-products)ページの手順に従ってください。 <img src="/assets/shared/img/ready-to-submit.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. テーブルに表示されているプロダクト ID と、Adapty ダッシュボードの [**Products**](https://app.adapty.io/products) タブに登録されているプロダクト ID を照合してください。ID が一致しない場合は、テーブルからプロダクト ID をコピーして、Adapty ダッシュボードで[プロダクトを作成](create-product)してください。 <img src="/assets/shared/img/product-id-copy.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## ステップ 3. プロダクトの利用可能地域を確認する \{#step-4-check-product-availability\} 1. **App Store Connect** に戻り、同じ **Subscriptions** セクションを開きます。 <img src="/assets/shared/img/subscription_group_open.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. サブスクリプショングループ名をクリックして、プロダクト一覧を表示します。 3. テスト対象のプロダクトを選択します。 <img src="/assets/shared/img/click-product.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **Availability** セクションまでスクロールし、必要な国と地域がすべて一覧に含まれていることを確認してください。 <img src="/assets/shared/img/product-availability.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## ステップ 4. プロダクトの価格を確認する \{#step-5-check-product-prices\} 1. 再び **App Store Connect** の **Monetization** → **Subscriptions** セクションに移動します。 <img src="/assets/shared/img/subscription_group_open.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. サブスクリプショングループ名をクリックします。 3. テスト対象のプロダクトを選択します。 <img src="/assets/shared/img/click-product.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **Subscription Pricing** までスクロールし、**Current Pricing for New Subscribers** セクションを展開します。 <img src="/assets/shared/img/check-prices.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. 必要な価格がすべて一覧に含まれていることを確認してください。 <img src="/assets/shared/img/product-pricing.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## ステップ 5. アプリの有料ステータス、銀行口座、税務フォームがアクティブであることを確認する \{#step-5-check-app-paid-status-bank-account-and-tax-forms-are-active\} 1. [**App Store Connect**](https://appstoreconnect.apple.com/) のホームページで **Business** をクリックします。 <img src="/assets/shared/img/business.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. 会社名を選択します。 <img src="/assets/shared/img/business-name.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. 下にスクロールして、**Paid Apps Agreement**、**Bank Account**、**Tax forms** がすべて **Active** になっていることを確認します。 <img src="/assets/shared/img/appstore-connect-status.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 以上の手順を実行することで、`InvalidProductIdentifiers` の警告を解消し、プロダクトをストアで公開できるようになります。 ## ステップ 6. プロダクトがスタックしている場合は再作成する \{#step-6-recreate-the-product-if-its-stuck\} ステップ 1〜5 がすべて問題なく通過している場合(`Approved` ステータス、Bundle ID の一致、有効な API キーなど)でも、SDK が `1000 noProductIDsFound` を返し続けることがあります。この場合、プロダクトが Apple のレジストリでスタックしている可能性があります。App Store Connect の UI 上にはプロダクトが存在していても、StoreKit のルックアップパスに公開されていない状態になることがあります。 App Store Connect でプロダクトを削除し、同じプロダクト ID で再作成してください。再作成後、反映されるまで最大 24 時間かかる場合があります。 --- # File: cantMakePayments --- --- title: "Code-1003 cantMakePayment エラーの修正" description: "Adapty でサブスクリプションを管理する際に発生する支払いエラーを解決します。" --- 1003エラー(`cantMakePayments`)は、このデバイスでアプリ内課金ができないことを示しています。 `cantMakePayments`エラーが発生している場合、通常は以下のいずれかの原因が考えられます: - デバイスの制限:このエラーはAdaptyとは無関係です。以下の解決方法を参照してください。 - オブザーバーモードの設定:`makePurchase`メソッドとオブザーバーモードは同時に使用できません。以下のセクションを参照してください。 ## 問題:デバイスの制限 \{#issue-device-restrictions\} | 問題 | 解決方法 | |-----------------------------|---------------------------------------------------------| | スクリーンタイムの制限 | [スクリーンタイム](https://support.apple.com/en-us/102470)でアプリ内課金の制限を無効にする | | アカウントの停止 | Appleサポートに連絡してアカウントの問題を解決する | | 地域の制限 | 対応地域のApp Storeアカウントを使用する | ## 問題:オブザーバーモードとmakePurchaseの併用 \{#issue-using-both-observer-mode-and-makepurchase\} 購入処理に`makePurchase`を使用している場合、オブザーバーモードを使用する必要はありません。[オブザーバーモード](observer-vs-full-mode)が必要なのは、購入ロジックを自分で実装する場合のみです。 したがって、`makePurchase`を使用している場合は、SDK有効化コードからオブザーバーモードの有効化を安全に削除できます。 --- # File: migration-to-ios-sdk-v4 --- --- title: "Adapty iOS SDK を v4.0 に移行する" description: "ペイウォール API をフロー API に置き換えることで Adapty iOS SDK v4.0 (beta) に移行します。Flow Builder と Paywall Builder の両方に対応しています。" --- Adapty iOS SDK 4.0 (beta) ではフローが導入され、それに伴いペイウォール API の名称が変更されました。新しい API は新しい Flow Builder と既存の Paywall Builder の両方に対応しており、Adapty ダッシュボード側での設定変更は不要です。 ## クイックリファレンス \{#quick-reference\} | v3 | v4 | |---|---| | `Adapty.getPaywall(placementId:locale:)` | `Adapty.getFlow(placementId:)` | | `AdaptyUI.getPaywallConfiguration(forPaywall:)` | `AdaptyUI.getFlowConfiguration(forFlow:locale:)` | | `Adapty.getPaywallProducts(paywall:)` | `Adapty.getPaywallProducts(flow:)` | | `Adapty.logShowPaywall(_:)` | `Adapty.logShowFlow(_:)` | | `AdaptyPaywallController` | `AdaptyFlowController` | | `AdaptyPaywallControllerDelegate` | `AdaptyFlowControllerDelegate` | | `AdaptyUI.paywallController(with:delegate:)` | `AdaptyUI.flowController(with:delegate:)` | | `.paywall()` (SwiftUI modifier) | `.flow()` | | `AdaptyPaywallView` | `AdaptyFlowView` | | `didFailRenderingWith:` / `didFailRendering:` | `didReceiveError:` | | `Adapty.updateAttribution(_:source:)` (`source: String`) | `Adapty.updateAttribution(_:source:)` (`source: AdaptyAttributionSource`) | | `Adapty.setIntegrationIdentifier(key:value:)` | `Adapty.setIntegrationIdentifier(_:)` (`AdaptyIntegrationIdentifier`) | ## iOS 最小バージョン \{#minimum-ios-version\} Adapty iOS SDK 4.0 では、最小デプロイメントターゲットが iOS 13.0 から **iOS 15.0** に引き上げられました。アップグレードの前に、プロジェクトの iOS Deployment Target を 15.0 以上に設定してください。 ## インストール:CocoaPods のサポート終了 \{#installation-cocoapods-no-longer-supported\} Adapty iOS SDK 4.0 では CocoaPods のサポートが廃止されました。SDK のインストールには [Swift Package Manager](sdk-installation-ios#install-adapty-sdk) をご利用ください。 プロジェクトで引き続き CocoaPods を使用している場合は、`Podfile` から `Adapty` および `AdaptyUI` の pod を削除し、`pod install` を実行してクリーンアップした後、Xcode の **File → Add Package Dependency** から `https://github.com/adaptyteam/AdaptySDK-iOS.git` を使ってパッケージを追加してください。 ## 削除された API \{#removed-apis\} - **`Adapty.getPaywallProductsWithoutDeterminingOffer(paywall:)`** — 削除されました。すべてのプロダクトにオファー情報が含まれるようになったため、個別の対象資格確認パスは不要になりました。 - **`AdaptyPaywallProductWithoutDeterminingOffer`** — 削除されました。以前このタイプを渡していたコールバック(`didSelectProduct` など)は、今後 `AdaptyPaywallProduct` を渡すようになります。 ## App Store プロモートアプリ内課金の一時的な削除 \{#app-store-promoted-in-app-purchases-temporarily-removed\} StoreKit 2 への移行の一環として、Adapty iOS SDK 4.0 では App Store プロモートアプリ内課金のサポートが削除されました。`shouldAddStorePayment(for:)` デリゲートメソッドおよびそれが受け取る `AdaptyDeferredProduct` 型は、4.0 では使用できません。 :::warning この削除は一時的なものです — プロモートアプリ内課金のサポートは、今後の 4.x リリースで復活する予定です。アプリがプロモートアプリ内課金に依存している場合は、サポートが戻るまで iOS SDK 3.x をご利用ください。 ::: ## ペイウォールの取得 \{#fetching-paywalls\} ### getPaywall + getPaywallConfiguration → getFlow + getFlowConfiguration 返却される型は `AdaptyPaywall` / `AdaptyUI.PaywallConfiguration` から `AdaptyFlow` / `AdaptyUI.FlowConfiguration` に変わります。`locale` パラメータはフェッチ呼び出しから `getFlowConfiguration` に移動します。 ```diff showLineNumbers - let paywall = try await Adapty.getPaywall(placementId: "YOUR_PLACEMENT_ID", locale: "en") - let paywallConfiguration = try await AdaptyUI.getPaywallConfiguration(forPaywall: paywall) + let flow = try await Adapty.getFlow(placementId: "YOUR_PLACEMENT_ID") + let flowConfiguration = try await AdaptyUI.getFlowConfiguration(forFlow: flow, locale: "en") ``` ### getPaywallProducts(paywall:) → getPaywallProducts(flow:) `getPaywallProducts` は、`Adapty.getFlow` によって返された `AdaptyFlow` を受け取るようになりました: ```diff showLineNumbers - let products = try await Adapty.getPaywallProducts(paywall: paywall) + let products = try await Adapty.getPaywallProducts(flow: flow) ``` ## ペイウォールの表示を記録する \{#tracking-paywall-views\} ### logShowPaywall(_:) → logShowFlow(_:) `logShowPaywall` は `logShowFlow` にリネームされ、`AdaptyPaywall` の代わりに `AdaptyFlow` を受け取るようになりました。イベントは引き続き同じバリアントに対して記録されるため、既存のファネルや A/B テストの指標はダッシュボードの変更なしに引き続き機能します。 ```diff showLineNumbers - try await Adapty.logShowPaywall(paywall) + try await Adapty.logShowFlow(flow) ``` v3と同様に、[Flow Builder](adapty-flow-builder)や[Paywall Builder](adapty-paywall-builder)でレンダリングされたフローやペイウォールを表示する際には、このメソッドを呼び出す必要はありません。これらのビューはAdaptyが自動的にトラッキングします。 ## UIKit \{#uikit\} ### AdaptyPaywallController → AdaptyFlowController コントローラーの型とファクトリーメソッドの名前を変更します: ```diff showLineNumbers - let controller = try AdaptyUI.paywallController( - with: paywallConfiguration, - delegate: self - ) + let controller = try AdaptyUI.flowController( + with: flowConfiguration, + delegate: self + ) ``` ### AdaptyPaywallControllerDelegate → AdaptyFlowControllerDelegate プロトコルの名前を変更し、すべてのメソッドシグネチャを更新してください。なお、`didSelectProduct` は削除された `AdaptyPaywallProductWithoutDeterminingOffer` の代わりに `AdaptyPaywallProduct` を受け取るようになりました。 ```diff showLineNumbers - class YourClass: AdaptyPaywallControllerDelegate { + class YourClass: AdaptyFlowControllerDelegate { - func paywallControllerDidAppear(_ controller: AdaptyPaywallController) { } + func flowControllerDidAppear(_ controller: AdaptyFlowController) { } - func paywallControllerDidDisappear(_ controller: AdaptyPaywallController) { } + func flowControllerDidDisappear(_ controller: AdaptyFlowController) { } - func paywallController(_ controller: AdaptyPaywallController, - didPerform action: AdaptyUI.Action) { } + func flowController(_ controller: AdaptyFlowController, + didPerform action: AdaptyUI.Action) { } - func paywallController(_ controller: AdaptyPaywallController, - didSelectProduct product: AdaptyPaywallProductWithoutDeterminingOffer) { } + func flowController(_ controller: AdaptyFlowController, + didSelectProduct product: AdaptyPaywallProduct) { } - func paywallController(_ controller: AdaptyPaywallController, - didStartPurchase product: AdaptyPaywallProduct) { } + func flowController(_ controller: AdaptyFlowController, + didStartPurchase product: AdaptyPaywallProduct) { } - func paywallController(_ controller: AdaptyPaywallController, - didFinishPurchase product: AdaptyPaywallProduct, - purchaseResult: AdaptyPurchaseResult) { } + func flowController(_ controller: AdaptyFlowController, + didFinishPurchase product: AdaptyPaywallProduct, + purchaseResult: AdaptyPurchaseResult) { } - func paywallController(_ controller: AdaptyPaywallController, - didFailPurchase product: AdaptyPaywallProduct, - error: AdaptyError) { } + func flowController(_ controller: AdaptyFlowController, + didFailPurchase product: AdaptyPaywallProduct, + error: AdaptyError) { } - func paywallControllerDidStartRestore(_ controller: AdaptyPaywallController) { } + func flowControllerDidStartRestore(_ controller: AdaptyFlowController) { } - func paywallController(_ controller: AdaptyPaywallController, - didFinishRestoreWith profile: AdaptyProfile) { } + func flowController(_ controller: AdaptyFlowController, + didFinishRestoreWith profile: AdaptyProfile) { } - func paywallController(_ controller: AdaptyPaywallController, - didFailRestoreWith error: AdaptyError) { } + func flowController(_ controller: AdaptyFlowController, + didFailRestoreWith error: AdaptyError) { } - func paywallController(_ controller: AdaptyPaywallController, - didFailRenderingWith error: AdaptyUIError) { } + func flowController(_ controller: AdaptyFlowController, + didReceiveError error: AdaptyUIError) { } - func paywallController(_ controller: AdaptyPaywallController, - didFailLoadingProductsWith error: AdaptyError) -> Bool { } + func flowController(_ controller: AdaptyFlowController, + didFailLoadingProductsWith error: AdaptyError) -> Bool { } - func paywallController(_ controller: AdaptyPaywallController, - didPartiallyLoadProducts failedIds: [String]) { } + func flowController(_ controller: AdaptyFlowController, + didPartiallyLoadProducts failedIds: [String]) { } - func paywallController(_ controller: AdaptyPaywallController, - didFinishWebPaymentNavigation product: AdaptyPaywallProduct?, - error: AdaptyError?) { } + func flowController(_ controller: AdaptyFlowController, + didFinishWebPaymentNavigation product: AdaptyPaywallProduct?, + error: AdaptyError?) { } } ``` ## SwiftUI \{#swiftui\} ### .paywall() モディファイアを .flow() に変更する \{#paywall-modifier--flow\} モディファイアの名前を変更し、設定パラメータ名を更新してください。 ```diff showLineNumbers @State var flowPresented = false // rename freely — the variable name is your choice var body: some View { Text("Hello, AdaptyUI!") - .paywall( + .flow( isPresented: $flowPresented, - paywallConfiguration: paywallConfiguration, + flowConfiguration: flowConfiguration, didFailPurchase: { product, error in /* handle the error */ }, didFinishRestore: { profile in /* check access level and dismiss */ }, didFailRestore: { error in /* handle the error */ }, - didFailRendering: { error in flowPresented = false } + didReceiveError: { error in flowPresented = false } ) } ``` 名前が変更されたコールバックは、`didFailRendering` が対応していたのと同じレンダリングエラーに加え、フロースクリプトの新しいランタイムエラー(`AdaptyUIError` コード `4105` — `.jsException` の JavaScript 例外)にも対応します。既存のハンドラー本体はコードを変更する必要はありません。パラメーターの名前を変更するだけです。 ### AdaptyPaywallView → AdaptyFlowView ビューの名前を変更し、設定パラメーターを更新し、`didSelectProduct` クロージャを更新してください — `AdaptyPaywallProductWithoutDeterminingOffer` が削除され、代わりに `AdaptyPaywallProduct` を受け取るようになりました: ```diff showLineNumbers - AdaptyPaywallView( - paywallConfiguration: paywallConfiguration, - didSelectProduct: { product: AdaptyPaywallProductWithoutDeterminingOffer in /* handle */ }, + AdaptyFlowView( + flowConfiguration: flowConfiguration, + didSelectProduct: { product: AdaptyPaywallProduct in /* handle */ }, didFailPurchase: { product, error in /* handle the error */ }, didFinishRestore: { profile in /* check access level and dismiss */ }, didFailRestore: { error in /* handle the error */ }, - didFailRendering: { error in /* handle the error */ } + didReceiveError: { error in /* handle the error */ } ) ``` ## AdaptyUI カスタムアセット \{#adaptyui-custom-assets\} ### AdaptyUICustomVideoAsset 既存のすべての呼び出し箇所に影響する変更が2点あります。 - `.player` が `AVQueuePlayer` の代わりに `AVPlayer` を受け取るようになりました。 - すべてのケースに末尾の `resolution: CGSize?` パラメータが追加されました。現在の動作を維持するには `nil` を渡してください。動画が読み込まれる前にプレイヤーがレイアウトスペースを確保できるよう(アスペクト比 = `width / height`)、実際のピクセルサイズを渡すこともできます。 ```diff showLineNumbers - case file(url: URL, preview: AdaptyUICustomImageAsset?) - case remote(url: URL, preview: AdaptyUICustomImageAsset?) - case player(item: AVPlayerItem, player: AVQueuePlayer, preview: AdaptyUICustomImageAsset?) + case file(url: URL, preview: AdaptyUICustomImageAsset?, resolution: CGSize?) + case remote(url: URL, preview: AdaptyUICustomImageAsset?, resolution: CGSize?) + case player(item: AVPlayerItem, player: AVPlayer, preview: AdaptyUICustomImageAsset?, resolution: CGSize?) ``` ## アトリビューションと連携識別子 \{#attribution-and-integration-identifiers\} ### updateAttribution(_:source:) `source` パラメーターの型が `String` から新しい `AdaptyAttributionSource` 型に変更され、以前はネストされていた `AdaptyProfile.AttributionSource` がトップレベルの `AdaptyAttributionSource` に改名されました。定義済みのソースを使用するか、その他のソースには文字列リテラルを渡してください。`AdaptyAttributionSource` は `ExpressibleByStringLiteral` に準拠しているため、既存の文字列リテラルによる呼び出しはそのままコンパイルできます。 ```diff showLineNumbers - try await Adapty.updateAttribution(attribution, source: "adjust") + try await Adapty.updateAttribution(attribution, source: .adjust) ``` 定義済みソース: `.appleAds`、`.adjust`、`.appsflyer`、`.branch`、`.tenjin`。ソースを `String` 変数で保持している場合は、`AdaptyAttributionSource(rawValue: yourSource)` でラップしてください。 ### setIntegrationIdentifier(_:) \{#setintegrationidentifier\} `setIntegrationIdentifier(key:value:)` は、1つ以上の `AdaptyIntegrationIdentifier` 値を受け取る可変長引数メソッドに置き換えられました。生の文字列キーの代わりに、定義済みのファクトリーメソッドを使用してください: ```diff showLineNumbers - try await Adapty.setIntegrationIdentifier(key: "appsflyer_id", value: uid) + try await Adapty.setIntegrationIdentifier(.appsflyerId(uid)) ``` 1回の呼び出しで複数の識別子を設定できます: ```swift showLineNumbers try await Adapty.setIntegrationIdentifier( .appsflyerId(uid), .adjustDeviceId(adid) ) ``` 各古いキー文字列をそのファクトリーメソッドに置き換えます: | v3 キー | v4 ファクトリー | |---|---| | `"adjust_device_id"` | `.adjustDeviceId(_:)` | | `"airbridge_device_id"` | `.airbridgeDeviceId(_:)` | | `"amplitude_user_id"` | `.amplitudeUserId(_:)` | | `"amplitude_device_id"` | `.amplitudeDeviceId(_:)` | | `"appmetrica_device_id"` | `.appmetricaDeviceId(_:)` | | `"appmetrica_profile_id"` | `.appmetricaProfileId(_:)` | | `"appsflyer_id"` | `.appsflyerId(_:)` | | `"branch_id"` | `.branchId(_:)` | | `"facebook_anonymous_id"` | `.facebookAnonymousId(_:)` | | `"firebase_app_instance_id"` | `.firebaseAppInstanceId(_:)` | | `"mixpanel_user_id"` | `.mixpanelUserId(_:)` | | `"one_signal_subscription_id"` | `.oneSignalSubscriptionId(_:)` | | `"one_signal_player_id"` | `.oneSignalPlayerId(_:)` | | `"posthog_distinct_user_id"` | `.posthogDistinctUserId(_:)` | | `"pushwoosh_hwid"` | `.pushwooshHWID(_:)` | | `"tenjin_analytics_installation_id"` | `.tenjinAnalyticsInstallationId(_:)` | --- # File: migration-to-ios-315 --- --- title: "Adapty iOS SDK を v3.15 に移行する" description: "Adapty iOS SDK v3.15 に移行して、パフォーマンスの向上と新しいマネタイズ機能をご利用ください。" --- [オブザーバーモード](observer-vs-full-mode)で[ペイウォールビルダー](adapty-paywall-builder)を使用している場合、iOS SDK 3.15 以降では新しいメソッド `observerModeDidInitiateRestorePurchases(onStartRestore:onFinishRestore:)` を実装する必要があります。このメソッドにより、リストアロジックをより細かく制御できるようになり、カスタムフローで購入のリストアを処理できます。実装の詳細については、[オブザーバーモードでペイウォールビルダーのペイウォールを表示する](ios-present-paywall-builder-paywalls-in-observer-mode)を参照してください。 ```diff showLineNumbers func observerMode(didInitiatePurchase product: AdaptyPaywallProduct, onStartPurchase: @escaping () -> Void, onFinishPurchase: @escaping () -> Void) { // use the product object to handle the purchase // use the onStartPurchase and onFinishPurchase callbacks to notify AdaptyUI about the process of the purchase } + func observerModeDidInitiateRestorePurchases(onStartRestore: @escaping () -> Void, + onFinishRestore: @escaping () -> Void) { + // use the onStartRestore and onFinishRestore callbacks to notify AdaptyUI about the process of the restore + } ``` --- # File: migration-to-ios-sdk-34 --- --- title: "Adapty iOS SDK を v3.4 へ移行する" description: "Adapty iOS SDK v3.4 に移行して、パフォーマンスの向上と新しいマネタイズ機能を活用しましょう。" --- Adapty SDK 3.4.0 はメジャーリリースであり、お客様側での移行手順が必要な改善が含まれています。 ## Adapty SDK のアクティベーションを更新する \{#update-adapty-sdk-activation\} <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```diff showLineNumbers // In your AppDelegate class: let configurationBuilder = AdaptyConfiguration .builder(withAPIKey: "PUBLIC_SDK_KEY") - Adapty.activate(with: configurationBuilder) { error in + Adapty.activate(with: configurationBuilder.build()) { error in // handle the error } ``` **フォールバックペイウォールファイルを更新する** 新しい SDK バージョンとの互換性を確保するために、フォールバックペイウォールファイルを更新してください。 1. Adapty ダッシュボードから[更新されたフォールバックペイウォールファイルをダウンロード](fallback-paywalls)します。 2. モバイルアプリ内の既存のフォールバックペイウォールを[新しいファイルに置き換え](ios-use-fallback-paywalls)ます。 </TabItem> <TabItem value="swiftui" label="SwiftUI" default> ```diff showLineNumbers @main struct SampleApp: App { init() { let configurationBuilder = AdaptyConfiguration .builder(withAPIKey: "PUBLIC_SDK_KEY") Task { - try await Adapty.activate(with: configurationBuilder) + try await Adapty.activate(with: configurationBuilder.build()) } } var body: some Scene { WindowGroup { ContentView() } } } ``` **フォールバックペイウォールファイルを更新する** 新しい SDK バージョンとの互換性を確保するために、フォールバックペイウォールファイルを更新してください。 1. Adapty ダッシュボードから[更新されたフォールバックペイウォールファイルをダウンロード](fallback-paywalls)します。 2. モバイルアプリ内の既存のフォールバックペイウォールを[新しいファイルに置き換え](ios-use-fallback-paywalls)ます。 </TabItem> </Tabs> --- # File: migration-to-ios330 --- --- title: "Adapty iOS SDK を v3.3 に移行する" description: "パフォーマンス向上と新しいマネタイゼーション機能のために Adapty iOS SDK v3.3 に移行します。" --- Adapty SDK 3.3.0 はメジャーリリースであり、いくつかの改善が加えられています。ただし、一部の移行手順が必要になる場合があります。 1. `Adapty.Configuration` を `AdaptyConfiguration` にリネームする。 2. `getViewConfiguration` メソッドを `getPaywallConfiguration` にリネームする。 3. SwiftUI から `didCancelPurchase` と `paywall` パラメータを削除し、`viewConfiguration` パラメータを `paywallConfiguration` にリネームする。 4. `AdaptyDelegate` メソッドから `defermentCompletion` パラメータを削除して、App Store からのプロモーション用アプリ内課金の処理方法を更新する。 5. `getProductsIntroductoryOfferEligibility` メソッドを削除する。 6. Adjust、AirBridge、Amplitude、AppMetrica、Appsflyer、Branch、Facebook Ads、Firebase と Google Analytics、Mixpanel、OneSignal、Pushwoosh のインテグレーション設定を更新する。 7. オブザーバーモードの実装を更新する。 <div style={{ textAlign: 'center' }}> <iframe width="560" height="315" src="https://www.youtube.com/embed/9Xs8d0lt_RY?si=xvWhUO2tlG1tKP5f" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen> </iframe> </div> ## Adapty.Configuration を AdaptyConfiguration にリネームする \{#rename-adaptyconfiguration-to-adaptyconfiguration\} 次のように Adapty iOS SDK の有効化コードを更新してください: <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```diff showLineNumbers // In your AppDelegate class: let configurationBuilder = - Adapty.Configuration + AdaptyConfiguration .builder(withAPIKey: "PUBLIC_SDK_KEY") .with(observerMode: false) .with(customerUserId: "YOUR_USER_ID") .with(idfaCollectionDisabled: false) .with(ipAddressCollectionDisabled: false) Adapty.activate(with: configurationBuilder) { error in // handle the error } ``` </TabItem> <TabItem value="swiftui" label="SwiftUI" default> ```diff showLineNumbers @main struct SampleApp: App { init() let configurationBuilder = - Adapty.Configuration + AdaptyConfiguration .builder(withAPIKey: "PUBLIC_SDK_KEY") .with(observerMode: false) // optional .with(customerUserId: "YOUR_USER_ID") // optional .with(idfaCollectionDisabled: false) // optional .with(ipAddressCollectionDisabled: false) // optional Task { try await Adapty.activate(with: configurationBuilder) } } var body: some Scene { WindowGroup { ContentView() } } } ``` </TabItem> </Tabs> ## getViewConfiguration メソッドを getPaywallConfiguration にリネームする \{#rename-getviewconfiguration-method-to-getpaywallconfiguration\} ペイウォールの `viewConfiguration` を取得するメソッド名を次のように更新してください: ```diff showLineNumbers guard paywall.hasViewConfiguration else { // use your custom logic return } do { - let paywallConfiguration = try await AdaptyUI.getViewConfiguration( + let paywallConfiguration = try await AdaptyUI.getPaywallConfiguration( forPaywall: paywall ) // use loaded configuration } catch { // handle the error } ``` メソッドの詳細については、[ペイウォールビルダーで作成したペイウォールのビュー設定を取得する](get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder)をご覧ください。 ## SwiftUI のパラメータを変更する \{#change-parameters-in-swiftui\} SwiftUI に以下の変更が加えられています: 1. `didCancelPurchase` パラメータが削除されました。代わりに `didFinishPurchase` を使用してください。 2. `.paywall()` メソッドはペイウォールオブジェクトを受け付けなくなりました。 3. `paywallConfiguration` パラメータが `viewConfiguration` パラメータに置き換わりました。 次のようにコードを更新してください: ```diff showLineNumbers @State var paywallPresented = false var body: some View { Text("Hello, AdaptyUI!") .paywall( isPresented: $paywallPresented, - paywall: <paywall object>, - viewConfiguration: <LocalizedViewConfiguration>, + paywallConfiguration: <AdaptyUI.PaywallConfiguration>, didPerformAction: { action in switch action { case .close: paywallPresented = false default: // Handle other actions break } }, - didFinishPurchase: { product, profile in paywallPresented = false }, + didFinishPurchase: { product, purchaseResult in /* handle the result*/ }, didFailPurchase: { product, error in /* handle the error */ }, didFinishRestore: { profile in /* check access level and dismiss */ }, didFailRestore: { error in /* handle the error */ }, didFailRendering: { error in paywallPresented = false } - didCancelPurchase: { product in /* handle the result*/} ) } ``` ## App Store からのプロモーション用アプリ内課金の処理を更新する \{#update-handling-of-promotional-in-app-purchases-from-app-store\} 以下の例のように `AdaptyDelegate` メソッドから `defermentCompletion` パラメータを削除して、App Store からのプロモーション用アプリ内課金の処理方法を更新してください: ```swift showLineNumbers title="Swift" final class YourAdaptyDelegateImplementation: AdaptyDelegate { nonisolated func shouldAddStorePayment(for product: AdaptyDeferredProduct) -> Bool { // 1a. // Return `true` to continue the transaction in your app. // 1b. // Store the product object and return `false` to defer or cancel the transaction. false } // 2. Continue the deferred purchase later on by passing the product to `makePurchase` func continueDeferredPurchase() async { let storedProduct: AdaptyDeferredProduct = // get the product object from the 1b. do { try await Adapty.makePurchase(product: storedProduct) } catch { // handle the error } } } ``` ## getProductsIntroductoryOfferEligibility メソッドを削除する \{#remove-getproductsintroductoryoffereligibility-method\} Adapty iOS SDK 3.3.0 より前は、ユーザーが対象かどうかに関わらず、プロダクトオブジェクトには常にオファーが含まれていました。そのため、オファーを使用する前に資格を手動で確認する必要がありました。 現在は、ユーザーが対象の場合にのみプロダクトオブジェクトにオファーが含まれます。つまり、資格を確認する必要はなくなりました。オファーが存在する場合、そのユーザーは対象です。 対象外のユーザーのオファーを確認したい場合は、`sk1Product` および `sk2Product` を参照してください。 ## サードパーティインテグレーション SDK の設定を更新する \{#update-third-party-integration-sdk-configuration\} Adapty iOS SDK 3.3.0 から、`updateAttribution` メソッドの公開 API が更新されました。以前は `[AnyHashable: Any]` 辞書を受け付けており、各サービスのアトリビューションオブジェクトをそのまま渡すことができました。現在は `[String: any Sendable]` が必要なため、渡す前にアトリビューションオブジェクトを変換する必要があります。 Adapty iOS SDK 3.3.0 以降でインテグレーションが正常に動作するよう、以下のセクションに従って各インテグレーションの SDK 設定を更新してください。 ### Adjust 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[Adjust インテグレーションの SDK 設定](adjust#connect-your-app-to-adjust)をご確認ください。 <Tabs groupId="current-os" queryString> <TabItem value="v5" label="Adjust 5.x+" default> ```diff showLineNumbers class AdjustModuleImplementation { - func updateAdjustAttribution() { - Adjust.attribution { attribution in - guard let attributionDictionary = attribution?.dictionary()?.toSendableDict() else { return } - - Adjust.adid { adid in - guard let adid else { return } - - Adapty.updateAttribution(attributionDictionary, source: .adjust, networkUserId: adid) { error in - // handle the error - } - } - } - } + func updateAdjustAdid() { + Adjust.adid { adid in + guard let adid else { return } + + Adapty.setIntegrationIdentifier(key: "adjust_device_id", value: adid) + } + } + + func updateAdjustAttribution() { + Adjust.attribution { attribution in + guard let attribution = attribution?.dictionary() else { + return + } + + Adapty.updateAttribution(attribution, source: "adjust") + } + } } ``` </TabItem> <TabItem value="v4" label="Adjust 4.x" default> ```diff showLineNumbers class YourAdjustDelegateImplementation { // Find your implementation of AdjustDelegate // and update adjustAttributionChanged method: func adjustAttributionChanged(_ attribution: ADJAttribution?) { - if let attribution = attribution?.dictionary()?.toSendableDict() { - Adapty.updateAttribution(attribution, source: .adjust) + if let attribution = attribution?.dictionary() { + Adapty.updateAttribution(attribution, source: "adjust") } } } ``` </TabItem> </Tabs> ### AirBridge 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[AirBridge インテグレーションの SDK 設定](airbridge#connect-your-app-to-airbridge)をご確認ください。 ```diff showLineNumbers import AirBridge - let builder = AdaptyProfileParameters.Builder() - .with(airbridgeDeviceId: AirBridge.deviceUUID()) - - Adapty.updateProfile(params: builder.build()) + do { + try await Adapty.setIntegrationIdentifier( + key: "airbridge_device_id", + value: AirBridge.deviceUUID() + ) + } catch { + // handle the error + } ``` ### Amplitude 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[Amplitude インテグレーションの SDK 設定](amplitude#sdk-configuration)をご確認ください。 ```diff showLineNumbers import Amplitude - let builder = AdaptyProfileParameters.Builder() - .with(amplitudeUserId: Amplitude.instance().userId) - .with(amplitudeDeviceId: Amplitude.instance().deviceId) - - Adapty.updateProfile(params: builder.build()) + do { + try await Adapty.setIntegrationIdentifier( + key: "amplitude_user_id", + value: Amplitude.instance().userId + ) + try await Adapty.setIntegrationIdentifier( + key: "amplitude_device_id", + value: Amplitude.instance().deviceId + ) + } catch { + // handle the error + } ``` ### AppMetrica 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[AppMetrica インテグレーションの SDK 設定](appmetrica#sdk-configuration)をご確認ください。 ```diff showLineNumbers import AppMetricaCore - if let deviceID = AppMetrica.deviceID { - let builder = AdaptyProfileParameters.Builder() - .with(appmetricaDeviceId: deviceID) - .with(appmetricaProfileId: "YOUR_ADAPTY_CUSTOMER_USER_ID") - - Adapty.updateProfile(params: builder.build()) - } + if let deviceID = AppMetrica.deviceID { + do { + try await Adapty.setIntegrationIdentifier( + key: "appmetrica_device_id", + value: deviceID + ) + try await Adapty.setIntegrationIdentifier( + key: "appmetrica_profile_id", + value: "YOUR_ADAPTY_CUSTOMER_USER_ID" + ) + } catch { + // handle the error + } + } ``` ### AppsFlyer 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[AppsFlyer インテグレーションの SDK 設定](appsflyer#connect-your-app-to-appsflyer)をご確認ください。 ```diff showLineNumbers class YourAppsFlyerLibDelegateImplementation { // Find your implementation of AppsFlyerLibDelegate // and update onConversionDataSuccess method: func onConversionDataSuccess(_ conversionInfo: [AnyHashable : Any]) { let uid = AppsFlyerLib.shared().getAppsFlyerUID() - Adapty.updateAttribution( - conversionInfo.toSendableDict(), - source: .appsflyer, - networkUserId: uid - ) + Adapty.setIntegrationIdentifier(key: "appsflyer_id", value: uid) + Adapty.updateAttribution(conversionInfo, source: "appsflyer") } } ``` ### Branch 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[Branch インテグレーションの SDK 設定](branch#connect-your-app-to-branch)をご確認ください。 ```diff showLineNumbers class YourBranchImplementation { func initializeBranch() { // Pass the attribution you receive from the initializing method of Branch iOS SDK to Adapty. Branch.getInstance().initSession(launchOptions: launchOptions) { (data, error) in - if let data = data?.toSendableDict() { - Adapty.updateAttribution(data, source: .branch) - } + if let data { + Adapty.updateAttribution(data, source: "branch") + } } } } ``` ### Facebook Ads 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[Facebook Ads インテグレーションの SDK 設定](facebook-ads#connect-your-app-to-facebook-ads)をご確認ください。 ```diff showLineNumbers import FacebookCore - let builder = AdaptyProfileParameters.Builder() - .with(facebookAnonymousId: AppEvents.shared.anonymousID) - - do { - try Adapty.updateProfile(params: builder.build()) - } catch { - // handle the error - } + do { + try await Adapty.setIntegrationIdentifier( + key: "facebook_anonymous_id", + value: AppEvents.shared.anonymousID + ) + } catch { + // handle the error + } ``` ### Firebase と Google Analytics 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[Firebase と Google Analytics インテグレーションの SDK 設定](firebase-and-google-analytics)をご確認ください。 ```diff showLineNumbers import FirebaseCore import FirebaseAnalytics FirebaseApp.configure() - if let appInstanceId = Analytics.appInstanceID() { - let builder = AdaptyProfileParameters.Builder() - .with(firebaseAppInstanceId: appInstanceId) - Adapty.updateProfile(params: builder.build()) { error in - // handle error - } - } + if let appInstanceId = Analytics.appInstanceID() { + do { + try await Adapty.setIntegrationIdentifier( + key: "firebase_app_instance_id", + value: appInstanceId + ) + } catch { + // handle the error + } + } ``` ### Mixpanel 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[Mixpanel インテグレーションの SDK 設定](mixpanel#sdk-configuration)をご確認ください。 ```diff showLineNumbers import Mixpanel - let builder = AdaptyProfileParameters.Builder() - .with(mixpanelUserId: Mixpanel.mainInstance().distinctId) - - do { - try await Adapty.updateProfile(params: builder.build()) - } catch { - // handle the error - } + do { + try await Adapty.setIntegrationIdentifier( + key: "mixpanel_user_id", + value: Mixpanel.mainInstance().distinctId + ) + } catch { + // handle the error + } ``` ### OneSignal 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[OneSignal インテグレーションの SDK 設定](onesignal#sdk-configuration)をご確認ください。 ```diff showLineNumbers // PlayerID (pre-v5 OneSignal SDK) // in your OSSubscriptionObserver implementation func onOSSubscriptionChanged(_ stateChanges: OSSubscriptionStateChanges) { if let playerId = stateChanges.to.userId { - let params = AdaptyProfileParameters.Builder() - .with(oneSignalPlayerId: playerId) - .build() - - Adapty.updateProfile(params:params) { error in - // check error - } + Task { + try await Adapty.setIntegrationIdentifier( + key: "one_signal_player_id", + value: playerId + ) + } } } // SubscriptionID (v5+ OneSignal SDK) OneSignal.Notifications.requestPermission({ accepted in - let id = OneSignal.User.pushSubscription.id - - let builder = AdaptyProfileParameters.Builder() - .with(oneSignalSubscriptionId: id) - - Adapty.updateProfile(params: builder.build()) + Task { + try await Adapty.setIntegrationIdentifier( + key: "one_signal_subscription_id", + value: OneSignal.User.pushSubscription.id + ) + } }, fallbackToSettings: true) ``` ### Pushwoosh 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[Pushwoosh インテグレーションの SDK 設定](pushwoosh#sdk-configuration)をご確認ください。 ```diff showLineNumbers - let params = AdaptyProfileParameters.Builder() - .with(pushwooshHWID: Pushwoosh.sharedInstance().getHWID()) - .build() - - Adapty.updateProfile(params: params) { error in - // handle the error - } + do { + try await Adapty.setIntegrationIdentifier( + key: "pushwoosh_hwid", + value: Pushwoosh.sharedInstance().getHWID() + ) + } catch { + // handle the error + } ``` ## オブザーバーモードの実装を更新する \{#update-observer-mode-implementation\} ペイウォールとトランザクションを紐付ける方法を更新してください。以前は `setVariationId` メソッドを使用して `variationId` を割り当てていました。現在は、新しい `reportTransaction` メソッドを使用してトランザクションを記録する際に `variationId` を直接含めることができます。最終的なコード例については、[オブザーバーモードでペイウォールを購入トランザクションに関連付ける](report-transactions-observer-mode)をご確認ください。 :::warning `reportTransaction` メソッドを使用してトランザクションを必ず記録してください。この手順を省略すると、Adapty はトランザクションを認識できず、アクセスレベルの付与、アナリティクスへの反映、インテグレーションへの送信が行われません。この手順は必須です! ::: ```diff showLineNumbers - let variationId = paywall.variationId - - // There are two overloads: for StoreKit 1 and StoreKit 2 - Adapty.setVariationId(variationId, forPurchasedTransaction: transaction) { error in - if error == nil { - // successful binding - } - } + do { + // every time when calling transaction.finish() + try await Adapty.reportTransaction(transaction, withVariationId: <YOUR_PAYWALL_VARIATION_ID>) + } catch { + // handle the error + } ``` --- # File: migration-to-ios-sdk-v3 --- --- title: "Adapty iOS SDK を v3.0 に移行する" description: "パフォーマンスの向上と新しいマネタイズ機能のために、Adapty iOS SDK v3.0 に移行しましょう。" --- Adapty SDK v3.0 では、新しい [Adapty ペイウォールビルダー](adapty-paywall-builder)をサポートしています。これはペイウォールをノーコードで作成できる使いやすいツールの最新バージョンです。高い柔軟性と豊富なデザイン機能により、ペイウォールの効果と収益性をさらに高めることができます。 :::info AdaptyUI ライブラリは非推奨となり、現在は AdaptySDK の一部として含まれています。 ::: ## Swift Package Manager で Adapty SDK v3.x を再インストールする \{#reinstall-adapty-sdk-v3x-via-swift-package-manager\} 1. AdaptyUI SDK のパッケージ依存関係をプロジェクトから削除してください。今後は不要です。 2. すでに追加済みであっても、Adapty SDK の依存関係を再追加する必要があります。Xcode で **File** -> **Add Package Dependency...** を開いてください。パッケージ依存関係の追加方法は Xcode のバージョンによって異なる場合があります。必要に応じて Xcode のドキュメントをご参照ください。 3. リポジトリ URL `https://github.com/adaptyteam/AdaptySDK-iOS.git` を入力してください。 4. バージョンを選択し、**Add package** ボタンをクリックしてください。 5. 必要なモジュールを選択してください: 1. **Adapty** は必須モジュールです。 2. **AdaptyUI** は [Adapty ペイウォールビルダー](adapty-paywall-builder) を使用する場合に必要なオプションモジュールです。 6. Xcode がプロジェクトにパッケージ依存関係を追加します。インポートするには、**Choose Package Products** ウィンドウで **Add package** ボタンを再度クリックしてください。パッケージが **Packages** リストに表示されます。 ## CocoaPods で Adapty SDK v3.x を再インストールする \{#reinstall-adapty-sdk-v3x-via-cocoapods\} 1. `Podfile` に Adapty を追加してください。必要なモジュールを選択してください: 1. **Adapty** は必須モジュールです。 2. **AdaptyUI** は [Adapty ペイウォールビルダー](adapty-paywall-builder) を使用する場合に必要なオプションモジュールです。 2. ```shell showLineNumbers title="Podfile" pod 'Adapty', '~> 3.2.0' pod 'AdaptyUI', '~> 3.2.0' # optional module needed only for Paywall Builder ``` 3. 次を実行してください: ```sh showLineNumbers title="Shell" pod install ``` これにより、アプリ用の `.xcworkspace` ファイルが作成されます。以後のアプリ開発にはこのファイルを使用してください。 Adapty および AdaptyUI SDK モジュールを有効化してください。v3.0 以前は AdaptyUI を有効化していませんでしたが、**AdaptyUI の有効化を追加**することを忘れないでください。パラメーターに変更はないため、そのまま使用してください。 <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift showLineNumbers // In your AppDelegate class: let configurationBuilder = AdaptyConfiguration .Builder(withAPIKey: "PUBLIC_SDK_KEY") .with(observerMode: false) .with(customerUserId: "YOUR_USER_ID") .with(idfaCollectionDisabled: false) .with(ipAddressCollectionDisabled: false) Adapty.activate(with: configurationBuilder) { error in // handle the error } // Only if you are going to use AdaptyUI AdaptyUI.activate() ``` </TabItem> <TabItem value="swiftui" label="SwiftUI" default> ```swift title="" showLineNumbers @main struct SampleApp: App { init() let configurationBuilder = AdaptyConfiguration .Builder(withAPIKey: "PUBLIC_SDK_KEY") .with(observerMode: false) // optional .with(customerUserId: "YOUR_USER_ID") // optional .with(idfaCollectionDisabled: false) // optional .with(ipAddressCollectionDisabled: false) // optional Adapty.activate(with: configurationBuilder) { error in // handle the error } // Only if you are going to use AdaptyUI AdaptyUI.activate() } var body: some Scene { WindowGroup { ContentView() } } } ``` </TabItem> </Tabs> --- # End of Documentation _Generated on: 2026-06-24T14:36:28.548Z_ _Successfully processed: 44/44 files_ # KMP - Adapty Documentation (Full Content) This file contains the complete content of all documentation pages for this platform. Locale: ja Generated on: 2026-06-24T14:36:28.550Z Total files: 50 --- # File: kmp-sdk-overview --- --- title: "Kotlin Multiplatform SDK overview" description: "Learn about Adapty Kotlin Multiplatform SDK and its key features." --- [![Release](https://img.shields.io/github/v/release/adaptyteam/AdaptySDK-KMP.svg?style=flat&logo=kotlin)](https://github.com/adaptyteam/AdaptySDK-KMP/releases) Welcome! We're here to make in-app purchases a breeze 🚀 We've built the Adapty Kotlin Multiplatform SDK to take the headache out of in-app purchases so you can focus on what you do best – building amazing apps. Here's what we handle for you: - Handle purchases, receipt validation, and subscription management out of the box - Create and test paywalls without app updates - Get detailed purchase analytics with zero setup - cohorts, LTV, churn, and funnel analysis included - Keep the user subscription status always up to date across app sessions and devices - Integrate your app with marketing attribution and analytics services using just one line of code :::note Before diving into the code, you'll need to integrate Adapty with Google Play Console and set up products in the dashboard. Check out our [quickstart guide](quickstart) to get everything configured first. ::: ## Get started For a fully automated integration, use the [adapty-sdk-integration skill](https://github.com/adaptyteam/adapty-sdk-integration-skill): it runs the whole integration from your AI coding tool in one command. Here's what we'll cover in the integration guide: 1. [Install & configure SDK](sdk-installation-kotlin-multiplatform): Add the SDK as a dependency to your project and activate it in the code. 2. [Enable purchases through paywalls](kmp-quickstart-paywalls): Set up the purchase flow so users can buy products. 3. [Check the subscription status](kmp-check-subscription-status): Automatically check the user's subscription state and control their access to paid content. 4. [Identify users (optional)](kmp-quickstart-identify): Associate users with their Adapty profiles to ensure their data is stored consistently across devices. ### See it in action Want to see how it all comes together? We've got you covered: - **Sample app**: Check out our [complete example](https://github.com/adaptyteam/AdaptySDK-KMP/tree/main/example) that demonstrates the full setup - **Video tutorial**: Follow along with our step-by-step implementation video below <iframe width="560" height="315" src="https://www.youtube.com/embed/JfwJvwnloNw?si=HskPxRk4WGkF_u9s" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe> ## Main concepts Before diving into the code, let's get familiar with the key concepts that make Adapty work. The beauty of Adapty's approach is that only placements are hardcoded in your app. Everything else – products, paywall designs, pricing, and offers – can be managed flexibly from the Adapty dashboard without app updates: 1. [**Product**](product) - Anything available for purchase in your app – subscription, consumable product, or lifetime access. 2. [**Paywall**](paywalls) - The only way to retrieve products from Adapty and use it to its full power. We've designed it this way to make it easier to track how different product combinations affect your monetization metrics. A paywall in Adapty serves as both a specific set of your products and the visual configuration that accompanies them. 3. [**Placement**](placements) - A strategic point in your user journey where you want to show a paywall. Think of placements as the "where" and "when" of your monetization strategy. Common placements include: - `main` - Your primary paywall location - `onboarding` - Shown during the user onboarding flow - `settings` - Accessible from your app's settings Start with the basics like `main` or `onboarding` for your first integration, then [think about where else in your app users might be ready to purchase](choose-meaningful-placements). 4. [**Profile**](profiles-crm) - When users purchase a product, their profile is assigned an **access level** which you use to define access to paid features. --- # File: sdk-installation-kotlin-multiplatform --- --- title: "Adapty Kotlin Multiplatform SDK のインストールと設定" description: "Kotlin Multiplatform アプリ向けに Adapty SDK をインストールして設定する方法を説明します。" --- Adapty SDKは、モバイルアプリへのシームレスな統合を実現する2つの主要モジュールで構成されています。 - **Core Adapty**: Adaptyがアプリで正常に機能するために必要な必須SDKです。 - **AdaptyUI** (`io.adapty:adapty-kmp-ui`): Compose Multiplatformレンダリングレイヤー(`view.present()`)で[Adapty ペイウォールビルダー](adapty-paywall-builder)を使用する場合に必要なモジュールです。プロジェクトでCompose Multiplatformを使用していない場合は、代わりにコアモジュールの[`createNativePaywallView`](kmp-present-paywalls#without-compose-multiplatform)および[`createNativeOnboardingView`](kmp-present-onboardings#without-compose-multiplatform)を使用できます。 :::tip Adapty SDK がモバイルアプリにどのように統合されるか、実際の例を見てみたいですか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを示す[サンプルアプリ](https://github.com/adaptyteam/AdaptySDK-KMP/tree/main/example)をご覧ください。 ::: 完全な実装のウォークスルーについては、以下の動画もご参照ください: <iframe width="560" height="315" src="https://www.youtube.com/embed/JfwJvwnloNw?si=HskPxRk4WGkF_u9s" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe> ## 動作要件 \{#requirements\} Adapty Kotlin Multiplatform SDK は Xcode 16.2 以降に対応しています。 :::info SDK v3.17 以降、Adapty SDK はデフォルトで Google Play Billing Library v8.0.0 を使用します。 ::: --- no_index: true --- import Callout from '../../../components/Callout.astro'; <Callout type="info"> SDKのインストールは、Adaptyセットアップのステップ5です。アプリ内で課金が機能するようにするには、アプリをストアに接続し、Adapty ダッシュボードでプロダクト、ペイウォール、プレースメントを作成する必要があります。[クイックスタートガイド](quickstart)では、必要なすべての手順を説明しています。 </Callout> ## GradleでAdapty SDKをインストールする \{#install-adapty-sdk-via-gradle\} Adapty SDKのGradleによるインストールは、AndroidとiOSの両方のアプリに必要です。 依存関係の設定方法を選択してください: - 標準Gradle: **モジュールレベル**の`build.gradle`に依存関係を追加する - プロジェクトで`.gradle.kts`ファイルを使用している場合は、**モジュールレベル**の`build.gradle.kts`に依存関係を追加する - バージョンカタログを使用している場合は、`libs.versions.toml`ファイルに依存関係を追加し、`build.gradle.kts`で参照する <Tabs> <TabItem value="module-level build.gradle" label="module-level build.gradle" default> ```kotlin showLineNumbers kotlin { sourceSets { commonMain { dependencies { implementation libs.adapty.kmp } } } } ``` </TabItem> <TabItem value="module-level build.gradle.kts" label="module-level build.gradle.kts" default> ```kotlin showLineNumbers kotlin { sourceSets { val commonMain by getting { dependencies { implementation(libs.adapty.kmp) } } } } ``` </TabItem> <TabItem value="version-catalog" label="バージョンライブラリ" default> ```toml showLineNumbers // libs.versions.toml [versions] .. adapty-kmp = "<the latest SDK version>" [libraries] .. adapty-kmp = { module = "io.adapty:adapty-kmp", version.ref = "adapty-kmp" } // build.gradle.kts kotlin { sourceSets { val commonMain by getting { dependencies { implementation(libs.adapty.kmp) } } } } ``` </TabItem> </Tabs> :::note Maven 関連のエラーが発生した場合は、Gradle スクリプトに `mavenCentral()` が含まれていることを確認してください。 <details> <summary>追加方法の手順</summary> プロジェクトの `settings.gradle` に `dependencyResolutionManagement` がない場合は、トップレベルの `build.gradle` のリポジトリ末尾に以下を追加してください: ```groovy showLineNumbers title="top-level build.gradle" allprojects { repositories { ... mavenCentral() } } ``` `dependencyResolutionManagement` がある場合は、`settings.gradle` の `dependencyResolutionManagement` セクション内の `repositories` に以下を追加してください: ```groovy showLineNumbers title="settings.gradle" dependencyResolutionManagement { ... repositories { ... google() mavenCentral() } } ``` </details> ::: ## Adapty SDK を有効化する \{#activate-adapty-sdk\} ### 基本セットアップ \{#basic-setup\} 初期化はできるだけ早い段階で追加してください。通常は、両プラットフォーム共通の Kotlin コード内で行います。 :::note Adapty SDK はアプリ内で一度だけ有効化すれば十分です。 ::: ```kotlin title="Kotlin" showLineNumbers val config = AdaptyConfig .Builder("PUBLIC_SDK_KEY") .build() Adapty.activate(configuration = config) .onSuccess { Log.d("Adapty", "SDK initialised") } .onError { error -> Log.e("Adapty", "Adapty init error: ${error.message}") } ``` :::important 他の Adapty SDK メソッドを呼び出す前に、`activate` の完了を待ってください。詳細な順序については、[Kotlin Multiplatform SDK の呼び出し順序](kmp-sdk-call-order)を参照してください。 ::: **Public SDK Key** を取得するには: 1. Adapty ダッシュボードを開き、[App settings → General](https://app.adapty.io/settings/general) に移動します。 2. **Api keys** セクションから **Public SDK Key**(Secret Key ではありません)をコピーします。 3. コード内の `"YOUR_PUBLIC_SDK_KEY"` を置き換えます。 :::info - Adapty の初期化には必ずパブリック SDK キーを使用してください。シークレットキーは[サーバーサイド API](getting-started-with-server-side-api) 専用です。 - SDK キーはアプリごとに固有です。複数のアプリがある場合は、正しいキーを選択してください。 ::: 次に、アプリにペイウォールを設定します: - [Adapty ペイウォールビルダー](adapty-paywall-builder)を使う場合は、まず以下の[AdaptyUI モジュールを有効化](#activate-adaptyui-module-of-adapty-sdk)してから、[ペイウォールビルダーのクイックスタート](kmp-quickstart-paywalls)に進んでください。 - 独自のペイウォール UI を構築する場合は、[カスタムペイウォールのクイックスタート](kmp-quickstart-manual)を参照してください。 ## AdaptyUI モジュールを有効化する \{#activate-adaptyui-module-of-adapty-sdk\} [ペイウォールビルダー](kmp-present-paywalls)を使用するために **AdaptyUI** モジュールを有効化する場合は、設定に `.withActivateUI(true)` を追加してください。 :::info 重要 コード内では、AdaptyUI を有効化する前に、コアの Adapty モジュールを先に有効化する必要があります。 ::: ```kotlin title="Kotlin" showLineNumbers val config = AdaptyConfig .Builder("PUBLIC_SDK_KEY") .withActivateUI(true) // true for activating the AdaptyUI module .build() Adapty.activate(configuration = config) .onSuccess { Log.d("Adapty", "SDK initialised") } .onError { error -> Log.e("Adapty", "Adapty init error: ${error.message}") } ``` ## Proguard の設定(Android) \{#configure-proguard-android\} 本番環境でアプリを公開する前に、Proguard の設定に `-keep class com.adapty.** { *; }` を追加する必要がある場合があります。 ## オプション設定 \{#optional-setup\} ### ログ記録 \{#logging\} #### ログシステムのセットアップ \{#set-up-the-logging-system\} Adapty はエラーやその他の重要な情報をログに記録し、何が起きているかを把握できるようにします。利用可能なログレベルは以下のとおりです: | レベル | 説明 | | :----------------------- | :------------------------------------------------------------------------------------------------------------------------ | | `AdaptyLogLevel.ERROR` | エラーのみがログに記録されます。 | | `AdaptyLogLevel.WARN` | エラーと、致命的なエラーは引き起こさないものの注意が必要なSDKからのメッセージがログに記録されます。 | | `AdaptyLogLevel.INFO` | エラー、警告、およびさまざまな情報メッセージがログに記録されます。デフォルト値。 | | `AdaptyLogLevel.VERBOSE` | 関数呼び出しやAPIクエリなど、デバッグ時に役立つ可能性のある追加情報がログに記録されます。 | | `AdaptyLogLevel.DEBUG` | 内部デバッグデータを含む、最も詳細な情報がログに記録されます。 | Adapty を設定する前に、アプリでログレベルを設定できます: ```kotlin title="Kotlin" showLineNumbers val config = AdaptyConfig .Builder("PUBLIC_SDK_KEY") .withLogLevel(AdaptyLogLevel.VERBOSE) // recommended for development .build() ``` ### データポリシー \{#data-policies\} #### IPアドレスの収集と共有を無効にする \{#disable-ip-address-collection-and-sharing\} Adaptyモジュールを有効にする際、`ipAddressCollectionDisabled` を `true` に設定すると、ユーザーのIPアドレスの収集と共有を無効にできます。デフォルト値は `false` です。 このパラメーターは、ユーザーのプライバシーを強化する場合、GDPRやCCPAなどの地域データ保護規制に準拠する場合、またはIPベースの機能がアプリに不要な場合に不要なデータ収集を減らすために活用してください。 ```kotlin title="Kotlin" showLineNumbers val config = AdaptyConfig .Builder("PUBLIC_SDK_KEY") .withIpAddressCollectionDisabled(true) .build() ``` #### 広告IDの収集と共有を無効にする \{#disable-advertising-id-collection-and-sharing\} Adapty モジュールを有効化する際、広告識別子の収集を無効にするには `appleIdfaCollectionDisabled`(iOS)または `googleAdvertisingIdCollectionDisabled`(Android)を true に設定してください。デフォルト値は false です。 このパラメータは、App Store/Play Storeのポリシーに準拠するため、App Tracking Transparencyのプロンプト表示を避けるため、または広告IDに基づくアドバタイジングアトリビューションやアナリティクスがアプリに不要な場合に使用してください。 ```kotlin title="Kotlin" showLineNumbers val config = AdaptyConfig .Builder("PUBLIC_SDK_KEY") .withGoogleAdvertisingIdCollectionDisabled(true) // Android only .withAppleIdfaCollectionDisabled(true) // iOS only .build() ``` #### AdaptyUI のメディアキャッシュ設定 \{#set-up-media-cache-configuration-for-adaptyui\} デフォルトでは、AdaptyUI はパフォーマンスの向上とネットワーク使用量の削減のために、メディア(画像や動画など)をキャッシュします。カスタム設定を提供することで、キャッシュの設定をカスタマイズできます。 `mediaCache` を使用して、デフォルトのキャッシュ設定を上書きします。 ```kotlin val config = AdaptyConfig .Builder("PUBLIC_SDK_KEY") .withMediaCacheConfiguration( AdaptyConfig.MediaCacheConfiguration( memoryStorageTotalCostLimit = 200 * 1024 * 1024, // 200 MB memoryStorageCountLimit = Int.MAX_VALUE, diskStorageSizeLimit = 200 * 1024 * 1024 // 200 MB ) ) .build() ``` ### ローカルアクセスレベルの有効化(Android) \{#enable-local-access-levels-android\} デフォルトでは、Android では[ローカルアクセスレベル](local-access-levels)が無効になっています。有効にするには、`withLocalAccessLevelAllowed` を `true` に設定します: ```kotlin title="Kotlin" showLineNumbers val config = AdaptyConfig .Builder("PUBLIC_SDK_KEY") .withGoogleLocalAccessLevelAllowed(true) .build() ``` ### バックアップ復元時のデータ消去 \{#clear-data-on-backup-restore\} `withAppleClearDataOnBackup` を `true` に設定すると、アプリが iCloud バックアップから復元されたことを SDK が検出し、キャッシュされたプロファイル情報、プロダクト詳細、ペイウォールなど、ローカルに保存されているすべての SDK データを削除します。その後、SDK はクリーンな状態で初期化されます。デフォルト値は `false` です。 :::note 削除されるのはローカルの SDK キャッシュのみです。Apple とのトランザクション履歴や Adapty サーバー上のユーザーデータは変更されません。 ::: ```swift showLineNumbers val config = AdaptyConfig .Builder("PUBLIC_SDK_KEY") .withAppleClearDataOnBackup(true) .build() ``` ## トラブルシューティング \{#troubleshooting\} #### Android バックアップルール(自動バックアップの設定) \{#android-backup-rules-auto-backup-configuration\} 一部のSDK(Adaptyを含む)には、独自のAndroid Auto Backup設定が含まれています。バックアップルールを定義する複数のSDKを使用している場合、Androidのマニフェストマージャーが `android:fullBackupContent`、`android:dataExtractionRules`、または `android:allowBackup` に関するエラーで失敗することがあります。 よくあるエラーの症状: `Manifest merger failed: Attribute application@dataExtractionRules value=(@xml/your_data_extraction_rules) is also present at [com.other.sdk:library:1.0.0] value=(@xml/other_sdk_data_extraction_rules)` :::note これらの変更は、Androidプラットフォームのディレクトリ(通常はプロジェクトの `android/` フォルダー内)で行う必要があります。 ::: この問題を解決するには、以下が必要です: - バックアップ関連の属性に対して、アプリの値を使用するようマニフェストマージャーに指示する。 - AdaptyのルールとほかのSDKのルールをマージしたバックアップルールファイルを作成する。 #### 1. マニフェストに `tools` 名前空間を追加する \{#1-add-the-tools-namespace-to-your-manifest\} `AndroidManifest.xml` ファイルのルートの `<manifest>` タグに tools が含まれていることを確認してください: ```xml <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="com.example.app"> ... </manifest> ``` #### 2. `<application>` でバックアップ属性を上書きする \{#2-override-backup-attributes-in-application\} 同じ `AndroidManifest.xml` ファイルで、`<application>` タグを更新して、アプリが最終的な値を提供し、マニフェストマージャーにライブラリの値を置き換えるよう指示します: ```xml <application android:name=".App" android:allowBackup="true" android:fullBackupContent="@xml/sample_backup_rules" android:dataExtractionRules="@xml/sample_data_extraction_rules" tools:replace="android:fullBackupContent,android:dataExtractionRules"> ... </application> ``` いずれかのSDKが `android:allowBackup` も設定している場合は、`tools:replace` に含めてください: ```xml tools:replace="android:allowBackup,android:fullBackupContent,android:dataExtractionRules" ``` #### 3. マージしたバックアップルールファイルを作成する \{#3-create-merged-backup-rules-files\} AndroidプロジェクトのAdaptyのルールとほかのSDKのルールを組み合わせた `res/xml/` ディレクトリにXMLファイルを作成します。AndroidはOSのバージョンによって異なるバックアップルール形式を使用するため、両方のファイルを作成することで、アプリがサポートするすべてのAndroidバージョンとの互換性が確保されます。 :::note 以下の例では、サンプルのサードパーティSDKとしてAppsFlyerを使用しています。アプリで使用しているほかのSDKのルールに置き換えるか、追加してください。 ::: **Android 12以降**(新しいデータ抽出ルール形式を使用): ```xml title="sample_data_extraction_rules.xml" <?xml version="1.0" encoding="utf-8"?> <data-extraction-rules> <cloud-backup> <exclude domain="sharedpref" path="appsflyer-data"/> <exclude domain="sharedpref" path="appsflyer-purchase-data"/> <exclude domain="database" path="afpurchases.db"/> <exclude domain="sharedpref" path="AdaptySDKPrefs.xml"/> </cloud-backup> <device-transfer> <exclude domain="sharedpref" path="appsflyer-data"/> <exclude domain="sharedpref" path="appsflyer-purchase-data"/> <exclude domain="database" path="afpurchases.db"/> <exclude domain="sharedpref" path="AdaptySDKPrefs.xml"/> </device-transfer> </data-extraction-rules> ``` **Android 11以前**(従来のフルバックアップコンテンツ形式を使用): ```xml title="sample_backup_rules.xml" <?xml version="1.0" encoding="utf-8"?> <full-backup-content> <exclude domain="sharedpref" path="appsflyer-data"/> <exclude domain="sharedpref" path="AdaptySDKPrefs.xml"/> :::important Kotlin Multiplatform プロジェクトでは、APK/AAB を生成する Android アプリケーションモジュール(例:`androidApp` または `app`)に以下の変更を適用してください: - マニフェスト:`androidApp/src/main/AndroidManifest.xml` - バックアップルール XML:`androidApp/src/main/res/xml/` ::: #### Android で別のアプリから戻った後に購入が失敗する \{#purchases-fail-after-returning-from-another-app-in-android\} 購入フローを開始するアクティビティが非デフォルトの `launchMode` を使用している場合、ユーザーが Google Play、銀行アプリ、またはブラウザから戻ったときに Android がそのアクティビティを誤って再生成または再利用することがあります。これにより、購入結果が失われたり、キャンセル扱いになったりする可能性があります。 購入が正常に機能するよう、購入フローを開始するアクティビティには `standard` または `singleTop` のみを使用し、他のモードは避けてください。 `AndroidManifest.xml` で、購入フローを開始するアクティビティが `standard` または `singleTop` に設定されていることを確認してください: ```xml <activity android:name=".MainActivity" android:launchMode="standard" /> ``` --- # File: kmp-quickstart-paywalls --- --- title: "Kotlin Multiplatform SDKのペイウォールを使用してアプリ内課金を有効にする" description: "アプリ内サブスクリプション管理のためにAdaptyをセットアップするクイックスタートガイド。" --- アプリ内課金を有効にするには、3つの重要な概念を理解する必要があります: - [**プロダクト**](product) – ユーザーが購入できるもの(サブスクリプション、消耗型アイテム、永続アクセスなど) - [**ペイウォール**](paywalls) – どのプロダクトを提供するかを定義する設定です。Adaptyでは、ペイウォールがプロダクトを取得する唯一の手段ですが、この設計によりアプリのコードを変更せずに商品内容、価格、プロダクトの組み合わせを変更できます。 - [**プレースメント**](placements) – アプリ内でペイウォールを表示する場所とタイミング(`main`、`onboarding`、`settings`など)。ダッシュボードでプレースメントにペイウォールを設定し、コード内ではプレースメントIDで取得します。これにより、A/B テストの実施やユーザーごとに異なるペイウォールの表示が簡単になります。 Adaptyでは、アプリ内課金を有効にする3つの方法を提供しています。アプリの要件に応じていずれかを選択してください: | 実装方法 | 複雑さ | 適した場面 | |---------------------------|------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Adapty ペイウォールビルダー | ✅ 簡単 | [ノーコードビルダーで完全な購入対応のペイウォールを作成](quickstart-paywalls)します。Adaptyが自動的にレンダリングし、複雑な購入フロー、レシート検証、サブスクリプション管理をすべて裏側で処理します。 | | 手動作成のペイウォール | 🟡 中程度 | アプリコードでペイウォールUIを実装しますが、プロダクト提供の柔軟性を維持するためAdaptyからペイウォールオブジェクトを取得します。[ガイド](kmp-quickstart-manual)を参照してください。 | | オブザーバーモード | 🔴 難しい | 既に独自の購入処理インフラを持っており、それを引き続き使用したい場合。オブザーバーモードにはAdaptyでの制限があります。[記事](observer-vs-full-mode)を参照してください。 | :::important **以下の手順は、Adaptyペイウォールビルダーで作成したペイウォールの実装方法を示しています。** ペイウォールビルダーを使用しない場合は、[手動作成のペイウォールで購入を処理するガイド](kmp-making-purchases)を参照してください。 ::: Adaptyペイウォールビルダーで作成したペイウォールをアプリコードに表示するには、以下の手順だけが必要です: 1. **ペイウォールを取得する**:AdaptyからペイウォールのPaywallオブジェクトを取得します。 2. **ペイウォールを表示し、Adaptyが購入を処理する**:取得したペイウォールコンテナをアプリに表示します。 3. **ボタンアクションを処理する**:ペイウォール上のユーザー操作と、アプリの応答を関連付けます。たとえば、ユーザーがボタンをクリックしたときにリンクを開いたり、ペイウォールを閉じたりします。 ## 開始前の準備 \{#before-you-start\} 開始前に、以下の手順を完了してください: 1. Adapty ダッシュボードでアプリを[App Store](initial_ios)や[Google Play](initial-android)に接続します。 2. Adaptyで[プロダクトを作成](create-product)します。 3. [ペイウォールを作成してプロダクトを追加](create-paywall)します。 4. [プレースメントを作成してペイウォールを追加](create-placement)します。 5. アプリコードに[Adapty SDKをインストールして有効化](sdk-installation-kotlin-multiplatform)します。 :::tip これらの手順を最も素早く完了するには、[クイックスタートガイド](quickstart)に従うか、[Developer CLI](developer-cli-quickstart)を使用してペイウォールとプレースメントを作成してください。 ::: ## 1. ペイウォールを取得する \{#1-get-the-paywall\} ペイウォールはダッシュボードで設定されたプレースメントに紐付けられています。プレースメントを使用することで、異なるオーディエンスに異なるペイウォールを表示したり、[A/B テスト](ab-tests)を実施したりできます。 Adaptyペイウォールビルダーで作成したペイウォールを取得するには、以下の手順が必要です: 1. `getPaywall`メソッドを使用して[プレースメント](placements)IDから`paywall`オブジェクトを取得し、それがビルダーで作成されたペイウォールかどうかを確認します。 2. `createPaywallView`メソッドを使用してペイウォールのビュー設定を取得します。ビュー設定にはペイウォールを表示するために必要なUI要素とスタイリングが含まれています。 :::important ビュー設定を取得するには、ペイウォールビルダーで **Show on device** トグルをオンにする必要があります。オンにしないと空のビュー設定が返され、ペイウォールが表示されません。 ::: ```kotlin showLineNumbers Adapty.getPaywall("YOUR_PLACEMENT_ID") .onSuccess { paywall -> if (!paywall.hasViewConfiguration) { return@onSuccess } val paywallView = AdaptyUI.createPaywallView(paywall = paywall) paywallView?.present() } .onError { error -> // handle the error } ``` ## 2. ペイウォールを表示する \{#2-display-the-paywall\} ペイウォールの設定を取得したら、数行追加するだけでペイウォールを表示できます。 デバイス画面にビジュアルなペイウォールを表示するには、まず設定を行う必要があります。`AdaptyUI.createPaywallView()`メソッドを呼び出してください: ```kotlin showLineNumbers val paywallView = AdaptyUI.createPaywallView(paywall = paywall) paywallView?.present() ``` ビューの作成が完了したら、デバイスの画面に表示できます。 :::tip ペイウォールの表示方法の詳細については、[ガイド](kmp-present-paywalls)を参照してください。 ::: ## 3. ボタンアクションを処理する \{#3-handle-button-actions\} ユーザーがペイウォール内のボタンをクリックすると、Kotlin Multiplatform SDKが購入、復元、ペイウォールのクローズ、リンクの開封を自動的に処理します。 ただし、カスタムまたは事前定義されたIDを持つボタンについては、コード内でアクションを処理する必要があります。または、デフォルトの動作をオーバーライドしたい場合もあります。 たとえば、以下は閉じるボタンのデフォルトの動作です。コードに追加する必要はありませんが、必要な場合にどのように実装するかを確認できます。 :::tip ボタンの[アクション](kmp-handle-paywall-actions)と[イベント](kmp-handling-events)の処理方法については、ガイドをお読みください。 ::: ```kotlin showLineNumbers AdaptyUI.setPaywallsEventsObserver(object : AdaptyUIPaywallsEventsObserver { override fun paywallViewDidPerformAction(view: AdaptyUIPaywallView, action: AdaptyUIAction) { when (action) { AdaptyUIAction.CloseAction, AdaptyUIAction.AndroidSystemBackAction -> view.dismiss() } } }) ``` ## 次のステップ \{#next-steps\} ペイウォールをアプリに表示する準備ができました。[App Storeサンドボックス](test-purchases-in-sandbox)または[Google Play Store](testing-on-android)でテスト購入を行い、ペイウォールからテスト購入が完了できることを確認してください。 次に、[ユーザーのアクセスレベルを確認](kmp-check-subscription-status)して、適切なユーザーにペイウォールを表示したり、有料機能へのアクセスを付与したりするようにしてください。 ## 完全な例 \{#full-example\} 以下は、これらの手順をアプリにまとめて統合する方法です。 ```kotlin showLineNumbers // Set up the observer for handling paywall actions AdaptyUI.setPaywallsEventsObserver(object : AdaptyUIPaywallsEventsObserver { override fun paywallViewDidPerformAction(view: AdaptyUIPaywallView, action: AdaptyUIAction) { when (action) { is AdaptyUIAction.CloseAction -> view.dismiss() } } }) // Get and display the paywall Adapty.getPaywall("YOUR_PLACEMENT_ID") .onSuccess { paywall -> if (!paywall.hasViewConfiguration) { // Use custom logic return@onSuccess } val paywallView = AdaptyUI.createPaywallView(paywall = paywall) paywallView?.present() } .onError { error -> // handle the error } ``` --- # File: kmp-check-subscription-status --- --- title: "Kotlin Multiplatform SDKでサブスクリプションのステータスを確認する" description: "AdaptyでKotlin Multiplatformアプリのサブスクリプションステータスを確認する方法を学びましょう。" --- ユーザーが有料コンテンツにアクセスできるかどうか、またはペイウォールを表示するかどうかを判断するには、プロファイル内の[アクセスレベル](access-level)を確認する必要があります。 この記事では、プロファイルの状態にアクセスして、ペイウォールを表示するか有料機能へのアクセスを許可するかを判断する方法を説明します。 ## サブスクリプションステータスを取得する \{#get-subscription-status\} ペイウォールや有料コンテンツをユーザーに表示するかどうかを決める際には、プロファイル内の[アクセスレベル](access-level)を確認します。方法は2つあります。 - アプリ起動時など、最新のプロファイルデータがすぐに必要な場合や強制的に更新したい場合は、`getProfile` を呼び出す。 - **プロファイルの自動更新**を設定して、サブスクリプションのステータスが変わるたびに自動的に更新されるローカルコピーを保持する。 ### プロファイルを取得する \{#get-profile\} サブスクリプションのステータスを確認するもっとも簡単な方法は、`getProfile` メソッドを使ってプロファイルにアクセスすることです。 ```kotlin showLineNumbers Adapty.getProfile() .onSuccess { profile -> // check the access } .onError { error -> // handle the error } ``` ### サブスクリプションの更新を監視する \{#listen-to-subscription-updates\} アプリ内でプロファイルの更新を自動的に受け取るには、次のようにします。 1. `Adapty.setOnProfileUpdatedListener()` を使ってプロファイルの変更を監視する。ユーザーのサブスクリプションステータスが変わるたびに、Adaptyが自動的にこのメソッドを呼び出します。 2. このメソッドが呼び出されたときに更新されたプロファイルデータを保存しておくと、追加のネットワークリクエストなしにアプリ全体で利用できます。 ```kotlin showLineNumbers class SubscriptionManager { private var currentProfile: AdaptyProfile? = null init { // Listen for profile updates Adapty.setOnProfileUpdatedListener { profile -> currentProfile = profile // Update UI, unlock content, etc. } } // Use stored profile instead of calling getProfile() fun hasAccess(): Boolean { return currentProfile?.accessLevels?.get("YOUR_ACCESS_LEVEL")?.isActive == true } } ``` :::note Adaptyはアプリ起動時にプロファイル更新リスナーを自動的に呼び出し、デバイスがオフラインでもキャッシュされたサブスクリプションデータを提供します。 ::: ## プロファイルとペイウォールのロジックを連携させる \{#connect-profile-with-paywall-logic\} ペイウォールの表示や有料機能へのアクセス許可をすぐに判断する必要がある場合は、ユーザーのプロファイルを直接確認できます。この方法は、アプリ起動時、プレミアムセクションへの遷移時、特定のコンテンツ表示前といったシナリオで役立ちます。 ```kotlin showLineNumbers private fun checkAccessAndShowPaywall() { // First, check if user has access Adapty.getProfile() .onSuccess { profile -> val hasAccess = profile.accessLevels?.get("YOUR_ACCESS_LEVEL")?.isActive == true if (!hasAccess) { // User doesn't have access, show paywall showPaywall() } else { // User has access, show premium content showPremiumContent() } } .onError { error -> // If we can't check access, show paywall as fallback showPaywall() } } private fun showPaywall() { // Get and display paywall using the KMP SDK Adapty.getPaywall("YOUR_PLACEMENT_ID") .onSuccess { paywall -> if (paywall.hasViewConfiguration) { val paywallView = AdaptyUI.createPaywallView(paywall = paywall) paywallView?.present() } else { // Handle remote config paywall or show custom UI handleRemoteConfigPaywall(paywall) } } .onError { error -> // Handle paywall loading error showError("Unable to load paywall") } } private fun showPremiumContent() { // Show your premium content here // This is where you unlock paid features } ``` ## 次のステップ \{#next-steps\} サブスクリプションのステータスを追跡する方法を理解したら、次は[ユーザープロファイルの操作](kmp-quickstart-identify)を学んで、ユーザーが購入済みのコンテンツに確実にアクセスできるようにしましょう。 --- # File: kmp-quickstart-identify --- --- title: "Kotlin Multiplatform SDKでユーザーを識別する" description: "KMPでアプリ内サブスクリプション管理のためにAdaptyをセットアップするためのクイックスタートガイド。" --- :::important このガイドは、独自の認証システムをお持ちの方を対象としています。ここでは、既存の認証システムと連携するように、AdaptyでユーザープロファイルをAdaptyで管理する方法について説明します。 ::: ユーザーの購入履歴をどのように管理するかは、アプリの認証モデルによって異なります。 - アプリがバックエンド認証を使用せず、ユーザーデータを保存しない場合は、[匿名ユーザーに関するセクション](#anonymous-users)を参照してください。 - アプリにバックエンド認証がある(またはある予定の)場合は、[識別済みユーザーに関するセクション](#identified-users)を参照してください。 **主要な概念**: - **プロファイル**はSDKが動作するために必要なエンティティです。Adaptyが自動的に作成します。 - 匿名(**カスタマーユーザーIDなし**)または識別済み(**カスタマーユーザーIDあり**)のどちらかになります。 - **カスタマーユーザーID**を提供することで、Adaptyのプロファイルと内部の認証システムとを相互参照できます。 匿名ユーザーと識別済みユーザーの違いは次のとおりです。 | | 匿名ユーザー | 識別済みユーザー | |-------------------------|---------------------------------------------------|-------------------------------------------------------------------------| | **購入管理** | ストアレベルの購入復元 | カスタマーユーザーIDを通じてデバイス間で購入履歴を維持 | | **プロファイル管理** | 再インストールのたびに新しいプロファイルを作成 | セッションとデバイスをまたいで同一プロファイルを使用 | | **データの永続性** | 匿名ユーザーのデータはアプリのインストールに紐付けられる | 識別済みユーザーのデータはアプリのインストールをまたいで保持される | ## 匿名ユーザー \{#anonymous-users\} バックエンド認証がない場合、**アプリのコードで認証を処理する必要はありません**。 1. アプリの初回起動時にSDKがアクティベートされると、Adaptyは**ユーザーの新しいプロファイルを作成します**。 2. ユーザーがアプリ内で何かを購入すると、その購入は**ユーザーのAdaptyプロファイルおよびストアアカウントに関連付けられます**。 3. ユーザーがアプリを**再インストール**したり、**新しいデバイス**にインストールしたりすると、Adaptyはアクティベート時に**新しい匿名プロファイルを作成します**。 4. ユーザーが以前にアプリで購入している場合、SDKのアクティベート時にデフォルトで購入がApp Storeから自動的に同期されます。 匿名ユーザーの場合、インストールのたびに新しいプロファイルが作成されますが、Adaptyのアナリティクスで[新規インストールとみなす基準を設定できる](general#4-installs-definition-for-analytics)ため、問題ありません。 匿名ユーザーの場合、インストール数は**デバイスID**でカウントする必要があります。この場合、再インストールを含め、デバイスへのアプリインストールがそれぞれ1回のインストールとしてカウントされます。 :::note バックアップからの復元は再インストールとは異なる動作をします。デフォルトでは、ユーザーがバックアップから復元した場合、SDKはキャッシュされたデータを保持し、新しいプロファイルは作成しません。この動作は`withAppleClearDataOnBackup`設定で変更できます。[詳細を確認する](sdk-installation-kotlin-multiplatform#clear-data-on-backup-restore)。 ::: ## 識別済みユーザー \{#identified-users\} ユーザーをアプリ内で識別するには2つの方法があります。 - [**ログイン/サインアップ時:**](#during-loginsignup) アプリ起動後にユーザーがサインインする場合、認証時に`identify()`をカスタマーユーザーIDとともに呼び出します。 - [**SDKアクティベーション時:**](#during-the-sdk-activation) アプリ起動時にすでにカスタマーユーザーIDが保存されている場合は、`activate()`の呼び出し時にそれを渡します。 :::important デフォルトでは、Adaptyが現在別のカスタマーユーザーIDに関連付けられているカスタマーユーザーIDからの購入を受け取った場合、アクセスレベルは共有されるため、両方のプロファイルが有料アクセスを持つことになります。この設定を変更して、有料アクセスを一方のプロファイルから他方に移行したり、共有を完全に無効にしたりすることができます。詳細は[こちらの記事](general#6-sharing-paid-access-between-user-accounts)をご覧ください。 ::: <img src="/assets/shared/img/identify-diagram.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### ログイン/サインアップ時 \{#during-loginsignup\} アプリ起動後にユーザーを識別する場合(たとえば、アプリへのログインやサインアップ後など)、`identify`メソッドを使用してカスタマーユーザーIDを設定します。 - **このカスタマーユーザーIDを以前に使用したことがない**場合、Adaptyは自動的に現在のプロファイルにリンクします。 - **このカスタマーユーザーIDでユーザーを以前に識別したことがある**場合、AdaptyはそのカスタマーユーザーIDに関連付けられたプロファイルを使用するよう切り替えます。 :::important カスタマーユーザーIDは各ユーザーで一意である必要があります。パラメータの値をハードコードすると、すべてのユーザーが同一人物とみなされます。 ::: 他のSDKメソッドを呼び出す前に、`identify`の完了(`onSuccess`コールバック)を待ってください。同時に呼び出すと、匿名プロファイルに処理が行われる可能性があります。[Kotlin Multiplatform SDKでの呼び出し順序](kmp-sdk-call-order)を参照してください。 ```kotlin showLineNumbers Adapty.identify("YOUR_USER_ID") // Unique for each user .onSuccess { // successful identify } .onError { error -> // handle the error } ``` ### SDKアクティベーション時 \{#during-the-sdk-activation\} SDKをアクティベートする際にすでにカスタマーユーザーIDが分かっている場合、`identify`を別途呼び出す代わりに`activate`メソッドで渡すことができます。 カスタマーユーザーIDが分かっているにもかかわらず、アクティベーション後にのみ設定した場合、アクティベーション時にAdaptyが新しい匿名プロファイルを作成し、`identify`を呼び出した後にのみ既存のプロファイルに切り替わることになります。 既存のカスタマーユーザーID(以前に使用したもの)でも新しいものでも渡すことができます。新しいものを渡した場合、アクティベーション時に作成された新しいプロファイルが自動的にそのカスタマーユーザーIDにリンクされます。 :::note デフォルトでは、匿名プロファイルの作成はアナリティクスのダッシュボードに影響しません。インストール数はデバイスIDに基づいてカウントされるためです。 デバイスIDは、デバイス上のストアからのアプリの単一のインストールを表し、アプリが再インストールされた場合にのみ再生成されます。 初回インストールか再インストールか、または既存のカスタマーユーザーIDが使用されているかどうかには依存しません。 プロファイルの作成(SDKのアクティベーション時またはログアウト時)、ログイン、またはアプリを再インストールせずにアップグレードしても、追加のインストールイベントは生成されません。 デバイスではなくユニークユーザーに基づいてインストール数をカウントしたい場合は、**App settings**に移動して[**Installs definition for analytics**](general#4-installs-definition-for-analytics)を設定してください。 ::: ```kotlin showLineNumbers AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withCustomerUserId("user123") // Customer user IDs must be unique for each user. If you hardcode the parameter value, all users will be considered as one. .build() ``` ### ユーザーのログアウト \{#log-users-out\} ユーザーのログアウトボタンがある場合は、`logout`メソッドを使用します。 :::important ユーザーをログアウトすると、そのユーザーのために新しい匿名プロファイルが作成されます。 ::: ```kotlin showLineNumbers Adapty.logout() .onSuccess { // successful logout } .onError { error -> // handle the error } ``` :::info ユーザーをアプリに再度ログインさせるには、`identify`メソッドを使用します。 ::: ### ログインなしでの購入を許可する \{#allow-purchases-without-login\} ユーザーがアプリへのログイン前後の両方で購入できる場合、ログイン後もアクセスが維持されるように設定する必要があります。 1. ログアウト状態のユーザーが購入すると、Adaptyはその購入を匿名プロファイルIDに紐付けます。 2. ユーザーがアカウントにログインすると、Adaptyは識別済みプロファイルを使用するよう切り替わります。 - 新しいカスタマーユーザーIDの場合(たとえば、登録前に購入が行われた場合)、Adaptyは現在のプロファイルにカスタマーユーザーIDを割り当てるため、すべての購入履歴が維持されます。 - 既存のカスタマーユーザーIDの場合(カスタマーユーザーIDがすでにプロファイルにリンクされている場合)、プロファイルの切り替え後に実際のアクセスレベルを取得する必要があります。識別後すぐに[`getProfile`](kmp-check-subscription-status)を呼び出すか、[プロファイルの更新をリッスンする](kmp-check-subscription-status)ことでデータが自動的に同期されます。 ## 次のステップ \{#next-steps\} おめでとうございます!アプリにアプリ内課金のロジックが実装できました!アプリの収益化がうまくいくことを願っています! Adaptyをさらに活用するために、以下のトピックも確認してください。 - [**テスト**](troubleshooting-test-purchases):すべてが期待どおりに動作することを確認する - [**インテグレーション**](configuration):マーケティングアトリビューションや分析サービスとわずか1行のコードで連携する - [**カスタムプロファイル属性の設定**](kmp-setting-user-attributes):ユーザープロファイルにカスタム属性を追加してセグメントを作成し、A/Bテストを実施したり、ユーザーに応じて異なるペイウォールを表示したりする --- # File: adapty-sdk-integration-skill-kmp --- --- title: "SDK統合スキルを使ってKotlin MultiplatformアプリにAdaptyを組み込む" description: "adapty-sdk-integrationスキルを使用して、AIコーディングツールでKotlin MultiplatformアプリにAdapty SDKをエンドツーエンドで統合します。" --- :::important このスキルはベータ版です。処理が止まったり予期しない動作をした場合は、代わりに[ステップバイステップの統合ガイド](adapty-cursor-kmp)を参照してください。AIツールが各ステージを適切なドキュメントとともに順を追って進められるよう設計されています。 ::: --- no_index: true --- [adapty-sdk-integration スキル](https://github.com/adaptyteam/adapty-sdk-integration-skill)は、Adapty のインテグレーションをエンドツーエンドで自動化します。ダッシュボードのセットアップ、SDK のインストール、ペイウォール、各ステージの検証まで対応しています。プラットフォームを自動検出し、各ステージで関連する Adapty ドキュメントを取得します。 **対応ツール**: Claude Code、GitHub Copilot CLI、OpenAI Codex、Gemini CLI。 インストールするには、お使いのツール向けのフォームを選択してください。完全なリストは[スキルの README](https://github.com/adaptyteam/adapty-sdk-integration-skill) をご覧ください。 **Claude Code** ``` claude plugin marketplace add adaptyteam/adapty-sdk-integration-skill claude plugin install adapty-sdk-integration@adapty ``` **GitHub Copilot CLI** ``` gh skill install adaptyteam/adapty-sdk-integration-skill ``` **Gemini CLI** ``` gemini skills install https://github.com/adaptyteam/adapty-sdk-integration-skill ``` **OpenAI Codex またはその他のツール**: リポジトリをクローンし、`plugins/adapty-sdk-integration/skills/adapty-sdk-integration/` をツールのスキルディレクトリにコピーしてください。 インストール後、プロジェクト内でスキルを実行します: ``` /adapty-sdk-integration ``` スキルがいくつかのセットアップ質問を行い、その後ダッシュボードのセットアップ、SDK のインストール、ペイウォール、検証の手順を案内します。 --- # File: adapty-cursor-kmp --- --- title: "AIアシスタンスを使ってAdaptyをKotlin Multiplatformアプリに統合する" description: "Cursor、Context7、ChatGPT、Claude、またはその他のAIツールを使用して、Kotlin MultiplatformアプリにAdaptyを統合するためのステップバイステップガイド。" --- このガイドでは、AIコーディングツールを使いながら、Kotlin MultiplatformアプリへのAdapty統合をステップバイステップで進めます。適切なAdaptyドキュメントを正しい順番でAIに渡していくことがポイントです。 For a fully automated integration, use the [adapty-sdk-integration skill](https://github.com/adaptyteam/adapty-sdk-integration-skill): it runs the whole integration from your AI coding tool in one command. ## はじめる前に:ダッシュボードの設定 \{#before-you-start-dashboard-setup\} AdaptyのSDKコードを書く前に、ダッシュボードでいくつかの設定が必要です。インタラクティブなLLMスキルを使う方法と、ダッシュボードから手動で行う方法があります。 ### スキルを使う方法(推奨) \{#skill-approach-recommended\} Adapty CLIスキルを使うと、アプリ、プロダクト、アクセスレベル、ペイウォール、プレースメントの設定をLLMから直接行えます。ダッシュボードを都度開く必要がありません。必要なのは、ダッシュボードで[ストアを接続する](integrate-payments)ことだけです。 ``` npx skills add adaptyteam/adapty-cli --skill adapty-cli ``` スキルを追加したら、エージェントで `/adapty-cli` を実行してください。各ステップを順番にガイドしてくれます。ストアの接続が必要なタイミングでは、ダッシュボードを開くよう案内されます。 ### ダッシュボードを使う方法 \{#dashboard-approach\} すべて手動で設定したい場合は、コードを書く前に以下の手順を完了してください。ダッシュボードの値はLLMが自動で取得することはできないため、自分で用意する必要があります。 1. **アプリストアを接続する**: Adapty ダッシュボードで **App settings → General** に移動し、KMPアプリがApp StoreとGoogle Play両方を対象とする場合は両方接続してください。これは購入機能を動作させるために必要です。 [アプリストアを接続する](integrate-payments) 2. **Public SDK keyをコピーする**: Adapty ダッシュボードで **App settings → General** に移動し、**API keys** セクションを確認してください。コード上では、Adaptyの設定ビルダーに渡す文字列です。 3. **プロダクトを少なくとも1つ作成する**: Adapty ダッシュボードの **Products** ページで作成してください。コードからプロダクトを直接参照することはなく、Adaptyはペイウォール経由でプロダクトを配信します。 [プロダクトを追加する](quickstart-products) 4. **ペイウォールとプレースメントを作成する**: Adapty ダッシュボードの **Paywalls** ページでペイウォールを作成し、**Placements** ページでプレースメントに割り当ててください。コード上では、`Adapty.getPaywall("YOUR_PLACEMENT_ID")` に渡す文字列がプレースメントIDです。 [ペイウォールを作成する](quickstart-paywalls) 5. **アクセスレベルを設定する**: Adapty ダッシュボードの **Products** ページで各プロダクトに対して設定してください。コード上では `profile.accessLevels["premium"]?.isActive` で確認する文字列です。デフォルトの `premium` アクセスレベルはほとんどのアプリで使えます。プロダクトによってアクセスできる機能が異なる場合(例: `basic` プランと `pro` プラン)は、コーディングを始める前に[追加のアクセスレベルを作成](assigning-access-level-to-a-product)してください。 :::tip 5つすべて揃ったら、コードを書く準備ができています。LLMに「Public SDK keyはX、プレースメントIDはY」と伝えることで、正確な初期化コードとペイウォール取得コードを生成してもらえます。 ::: ### 準備が整ったら設定するもの \{#set-up-when-ready\} コーディングを始めるのに必須ではありませんが、統合が進むにつれて必要になるものです: - **A/B テスト**: **Placements** ページで設定できます。コードの変更は不要です。 [A/B テスト](ab-tests) - **追加のペイウォールとプレースメント**: 異なるプレースメントIDを使って `getPaywall` の呼び出しを追加してください。 - **アナリティクス連携**: **Integrations** ページで設定します。連携方法は各サービスによって異なります。[アナリティクス連携](analytics-integration)と[アトリビューション連携](attribution-integration)を参照してください。 ## AdaptyドキュメントをLLMに渡す \{#feed-adapty-docs-to-your-llm\} ### Context7を使う(推奨) \{#use-context7-recommended\} [Context7](https://context7.com)は、LLMが最新のAdaptyドキュメントに直接アクセスできるMCPサーバーです。質問内容に応じて必要なドキュメントを自動的に取得するため、URLを手動で貼り付ける必要がありません。 Context7は **Cursor**、**Claude Code**、**Windsurf**、その他のMCP対応ツールで利用できます。設定するには次のコマンドを実行してください: ``` npx ctx7 setup ``` エディタを自動検出してContext7サーバーを設定します。手動でセットアップする場合は[Context7 GitHubリポジトリ](https://github.com/upstash/context7)を参照してください。 設定後は、プロンプトでAdaptyライブラリを参照できます: ``` Use the adaptyteam/adapty-docs library to look up how to install the Kotlin Multiplatform SDK ``` :::warning Context7を使えばドキュメントのリンクを手動で貼る手間は省けますが、実装の順序は重要です。以下の[実装ウォークスルー](#implementation-walkthrough)をステップごとに進めて、確実に動作させてください。 ::: ### プレーンテキストのドキュメントを使う \{#use-plain-text-docs\} AdaptyのドキュメントはどれもプレーンテキストのMarkdownで取得できます。URLの末尾に `.md` を付けるか、記事タイトルの下にある **Copy for LLM** をクリックしてください。例: [adapty-cursor-kmp.md](https://adapty.io/docs/ja/adapty-cursor-kmp.md) 以下の[実装ウォークスルー](#implementation-walkthrough)の各ステップには、「LLMに送る内容」ブロックに `.md` リンクが含まれています。 まとめて複数のドキュメントを渡したい場合は、下記の[インデックスファイルとプラットフォーム別サブセット](#plain-text-doc-index-files)を参照してください。 ## 実装ウォークスルー \{#implementation-walkthrough\} このガイドの残りの部分では、実装順にAdaptyの統合を進めます。各ステップにはLLMに送るドキュメント、完了時の確認事項、よくある問題を記載しています。 ### 統合を計画する \{#plan-your-integration\} コードを書き始める前に、LLMにプロジェクトを分析させて実装計画を立てましょう。AIツールにプランニングモードがある場合(CursorやClaude Codeのプランモードなど)、それを使うことでLLMがプロジェクト構造とAdaptyドキュメントの両方を読んでからコードを書いてくれます。 購入の実装方法をLLMに伝えてください。選択によって参照すべきガイドが変わります: - [**Adapty ペイウォールビルダー**](adapty-paywall-builder): Adaptyのノーコードビルダーでペイウォールを作成し、SDKが自動的にレンダリングします。 - [**手動作成のペイウォール**](kmp-making-purchases): 自分でペイウォールUIをコードで作成しますが、プロダクトの取得と購入処理にはAdaptyを使います。 - [**オブザーバーモード**](observer-vs-full-mode): 既存の購入インフラをそのまま使い、Adaptyはアナリティクスと連携のみに使います。 どれを選べばいいか迷ったら、[クイックスタートの比較表](kmp-quickstart-paywalls)を参照してください。 ### SDKのインストールと設定 \{#install-and-configure-the-sdk\} GradleでAdapty SDKの依存関係を追加し、Public SDK keyで有効化してください。これがすべての基盤になります。 **ガイド:** [Adapty SDKのインストールと設定](sdk-installation-kotlin-multiplatform) LLMに送る内容: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/sdk-installation-kotlin-multiplatform.md ``` :::tip[チェックポイント] - **期待される結果:** アプリがビルドされ、起動します。Logcat(Android)またはXcodeコンソール(iOS)にAdaptyの有効化ログが表示されます。 - **注意点:** 「Public API key is missing」→ プレースホルダーをApp settingsの実際のキーに置き換えたか確認してください。 ::: ### ペイウォールの表示と購入処理 \{#show-paywalls-and-handle-purchases\} プレースメントIDでペイウォールを取得し、表示して、購入イベントを処理します。必要なガイドは購入の実装方法によって異なります。 進めながら都度サンドボックスで購入をテストしてください。最後まで待たないようにしましょう。設定方法は[サンドボックスでの購入テスト](test-purchases-in-sandbox)を参照してください。 <Tabs groupId="paywall-approach"> <TabItem value="builder" label="Paywall Builder" default> **ガイド:** - [ペイウォールを使って購入を有効化する(クイックスタート)](kmp-quickstart-paywalls) - [ペイウォールビルダーのペイウォールと設定を取得する](kmp-get-pb-paywalls) - [ペイウォールを表示する](kmp-present-paywalls) - [ペイウォールのイベントを処理する](kmp-handling-events) - [ボタンアクションに対応する](kmp-handle-paywall-actions) LLMに送る内容: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/kmp-quickstart-paywalls.md - https://adapty.io/docs/ja/kmp-get-pb-paywalls.md - https://adapty.io/docs/ja/kmp-present-paywalls.md - https://adapty.io/docs/ja/kmp-handling-events.md - https://adapty.io/docs/ja/kmp-handle-paywall-actions.md ``` :::tip[チェックポイント] - **期待される結果:** 設定したプロダクトとともにペイウォールが表示されます。プロダクトをタップするとサンドボックスの購入ダイアログが表示されます。 - **注意点:** ペイウォールが空または `getPaywall` エラーが出る → プレースメントIDがダッシュボードと完全に一致しているか、プレースメントにオーディエンスが設定されているか確認してください。 ::: </TabItem> <TabItem value="manual" label="Manual paywalls"> **ガイド:** - [カスタムペイウォールで購入を有効化する(クイックスタート)](kmp-quickstart-manual) - [ペイウォールとプロダクトを取得する](fetch-paywalls-and-products-kmp) - [リモートコンフィグで設計したペイウォールをレンダリングする](present-remote-config-paywalls-kmp) - [購入を行う](kmp-making-purchases) - [購入を復元する](kmp-restore-purchase) LLMに送る内容: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/kmp-quickstart-manual.md - https://adapty.io/docs/ja/fetch-paywalls-and-products-kmp.md - https://adapty.io/docs/ja/present-remote-config-paywalls-kmp.md - https://adapty.io/docs/ja/kmp-making-purchases.md - https://adapty.io/docs/ja/kmp-restore-purchase.md ``` :::tip[チェックポイント] - **期待される結果:** カスタムペイウォールにAdaptyから取得したプロダクトが表示されます。プロダクトをタップするとサンドボックスの購入ダイアログが表示されます。 - **注意点:** プロダクトの配列が空 → ダッシュボードのペイウォールにプロダクトが設定されているか、プレースメントにオーディエンスが設定されているか確認してください。 ::: </TabItem> <TabItem value="observer" label="Observer mode"> **ガイド:** - [オブザーバーモードの概要](observer-vs-full-mode) - [オブザーバーモードを実装する](implement-observer-mode-kmp) - [オブザーバーモードでトランザクションを報告する](report-transactions-observer-mode-kmp) LLMに送る内容: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/observer-vs-full-mode.md - https://adapty.io/docs/ja/implement-observer-mode-kmp.md - https://adapty.io/docs/ja/report-transactions-observer-mode-kmp.md ``` :::tip[チェックポイント] - **期待される結果:** 既存の購入フローでサンドボックス購入を行った後、トランザクションがAdaptyダッシュボードの **Event Feed** に表示されます。 - **注意点:** イベントが表示されない → Adaptyへのトランザクション報告が実装されているか、両ストアのサーバー通知が設定されているか確認してください。 ::: </TabItem> </Tabs> ### サブスクリプションのステータスを確認する \{#check-subscription-status\} 購入後、ユーザープロファイルのアクティブなアクセスレベルを確認してプレミアムコンテンツを制限します。 **ガイド:** [サブスクリプションのステータスを確認する](kmp-check-subscription-status) LLMに送る内容: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/kmp-check-subscription-status.md ``` :::tip[チェックポイント] - **期待される結果:** サンドボックス購入後、`profile.accessLevels["premium"]?.isActive` が `true` を返します。 - **注意点:** 購入後に `accessLevels` が空 → ダッシュボードでプロダクトにアクセスレベルが設定されているか確認してください。 ::: ### ユーザーを識別する \{#identify-users\} アプリのユーザーアカウントをAdaptyプロファイルに紐付けて、デバイスをまたいで購入情報を引き継げるようにします。 :::important アプリに認証機能がない場合は、このステップをスキップしてください。 ::: **ガイド:** [ユーザーを識別する](kmp-quickstart-identify) LLMに送る内容: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/kmp-quickstart-identify.md ``` :::tip[チェックポイント] - **期待される結果:** `Adapty.identify("your-user-id")` を呼び出した後、ダッシュボードの **Profiles** セクションにカスタムユーザーIDが表示されます。 - **注意点:** 匿名プロファイルへのアトリビューションを避けるため、`identify` はアクティベーション後、ペイウォールの取得前に呼び出してください。 ::: ### リリースの準備をする \{#prepare-for-release\} サンドボックスで統合の動作確認ができたら、リリースチェックリストを確認してすべて本番環境に対応しているか確認しましょう。 **ガイド:** [リリースチェックリスト](release-checklist) LLMに送る内容: ``` Read these Adapty docs before releasing: - https://adapty.io/docs/ja/release-checklist.md ``` :::tip[チェックポイント] - **期待される結果:** すべてのチェックリスト項目が確認済み:ストアの接続、サーバー通知、購入フロー、アクセスレベルの確認、プライバシー要件。 - **注意点:** サーバー通知が未設定 → **App settings → iOS SDK** でApp Store Server Notificationsを設定し、**App settings → Android SDK** でGoogle Play Real-Time Developer Notificationsを設定してください。 ::: ## プレーンテキストのドキュメントインデックスファイル \{#plain-text-doc-index-files\} 個別のページを超えてLLMにより広いコンテキストを提供したい場合は、Adaptyのすべてのドキュメントをリスト化または統合したインデックスファイルを用意しています: - [`llms.txt`](https://adapty.io/docs/ja/llms.txt): すべてのページを `.md` リンク付きでリスト化しています。LLMがウェブサイトにアクセスしやすくするための[新たな標準](https://llmstxt.org/)です。一部のAIエージェント(ChatGPTなど)では、`llms.txt` をダウンロードしてチャットにファイルとしてアップロードする必要があります。 - [`llms-full.txt`](https://adapty.io/docs/ja/llms-full.txt): Adaptyのドキュメントサイト全体を1つのファイルにまとめたものです。非常に大きいため、全体像が必要なときだけ使用してください。 - Kotlin Multiplatform専用の [`kmp-llms.txt`](https://adapty.io/docs/ja/kmp-llms.txt) と [`kmp-llms-full.txt`](https://adapty.io/docs/ja/kmp-llms-full.txt): サイト全体と比べてトークンを節約できるプラットフォーム別サブセットです。 --- # File: kmp-paywalls --- --- title: "Paywalls in Kotlin Multiplatform SDK" description: "Learn how to work with paywalls in your Kotlin Multiplatform app with Adapty SDK." --- ## Display paywalls ### Adapty Paywall Builder <CustomDocCardList ids={['kmp-get-pb-paywalls', 'kmp-present-paywalls', 'kmp-handling-events', 'kmp-handle-paywall-actions']} /> :::tip To get started with the Adapty Paywall Builder paywalls quickly, see our [quickstart guide](kmp-quickstart-paywalls). ::: ### Implement paywalls manually <CustomDocCardList ids={['kmp-quickstart-manual', 'fetch-paywalls-and-products-kmp', 'present-remote-config-paywalls-kmp', 'kmp-making-purchases']} /> For more guides on implementing paywalls and handling purchases manually, see the [category](kmp-implement-paywalls-manually). ## Useful features <CustomDocCardList ids={['kmp-use-fallback-paywalls', 'kmp-web-paywalls']} /> --- # File: kmp-get-pb-paywalls --- --- title: "Kotlin Multiplatform SDKでペイウォールビルダーのペイウォールと設定を取得する" description: "Kotlin MultiatformアプリのAdaptyでPBペイウォールを取得し、サブスクリプションを管理する方法を学びます。" --- Adapty ダッシュボードの新しいペイウォールビルダーで[ペイウォールのビジュアルデザインを作成](adapty-paywall-builder)したら、モバイルアプリで表示できます。最初のステップは、プレースメントに紐づいたペイウォールと、以下で説明するビュー設定を取得することです。 このトピックはペイウォールビルダーでカスタマイズしたペイウォールに関するものです。ペイウォールを手動で実装する場合は、[モバイルアプリでリモートコンフィグペイウォールのペイウォールとプロダクトを取得する](fetch-paywalls-and-products-kmp)を参照してください。 :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: <details> <summary>モバイルアプリでペイウォールの表示を始める前に(クリックして展開)</summary> 1. Adapty ダッシュボードで[プロダクトを作成](create-product)する。 2. Adapty ダッシュボードで[ペイウォールを作成し、プロダクトを追加](create-paywall)する。 3. Adapty ダッシュボードで[プレースメントを作成し、ペイウォールを追加](create-placement)する。 4. モバイルアプリに[Adapty SDK](sdk-installation-kotlin-multiplatform)をインストールする。 </details> ## ペイウォールビルダーで作成したペイウォールを取得する \{#fetch-paywall-designed-with-paywall-builder\} [ペイウォールビルダーでペイウォールをデザイン](adapty-paywall-builder)した場合、ユーザーに表示するためのレンダリングコードをアプリに書く必要はありません。このようなペイウォールには、表示内容と表示方法の両方が含まれています。ただし、プレースメントを通じてIDを取得し、ビュー設定を取得したうえで、モバイルアプリで表示する必要があります。 パフォーマンスを最適化するには、ペイウォールとその[ビュー設定](kmp-get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder)をできるだけ早く取得し、ユーザーに表示する前に画像のダウンロードが完了するよう時間を確保することが重要です。 ペイウォールを取得するには、`getPaywall` メソッドを使用します。 ```kotlin showLineNumbers Adapty.getPaywall( placementId = "YOUR_PLACEMENT_ID", locale = "en", fetchPolicy = AdaptyPaywallFetchPolicy.Default, loadTimeout = 5.seconds ).onSuccess { paywall -> // the requested paywall }.onError { error -> // handle the error } ``` パラメーター: | パラメーター | 必須/任意 | 説明 | |---------|--------|-----------| | **placementId** | 必須 | 取得したい[プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** | <p>任意</p><p>デフォルト: `en`</p> | <p>[ペイウォールのローカライズ](add-paywall-locale-in-adapty-paywall-builder)の識別子。マイナス(**-**)で区切られた1つまたは2つのサブタグで構成される言語コードです。最初のサブタグは言語、2番目はリージョンを表します。</p><p></p><p>例:`en` は英語、`pt-br` はブラジルポルトガル語を表します。</p><p>ロケールコードの詳細と推奨される使用方法については、[ローカライズとロケールコード](localizations-and-locale-codes)を参照してください。</p> | | **fetchPolicy** | デフォルト: `AdaptyPaywallFetchPolicy.Default` | <p>デフォルトでは、SDKはサーバーからデータを読み込もうとし、失敗した場合はキャッシュデータを返します。ユーザーが常に最新データを取得できるため、この設定を推奨します。</p><p></p><p>ただし、ユーザーが不安定なインターネット環境にいる場合は、`AdaptyPaywallFetchPolicy.ReturnCacheDataElseLoad` を使用してキャッシュデータが存在すればそれを返すことを検討してください。この場合、ユーザーが最新データを取得できないことがありますが、接続状況に関わらず読み込み時間が短縮されます。キャッシュは定期的に更新されるため、セッション中にネットワークリクエストを避けるために使用しても安全です。</p><p></p><p>キャッシュはアプリを再起動しても保持され、アプリの再インストールや手動クリーンアップ時のみクリアされます。</p><p></p><p>Adapty SDKはペイウォールを2層でローカルに保存します。上記の定期更新キャッシュと[フォールバックペイウォール](fallback-paywalls)です。また、CDNを使用してペイウォールを高速に取得し、CDNが到達不可能な場合に備えてスタンドアロンのフォールバックサーバーも用意しています。このシステムは、インターネット接続が不安定な状況でも信頼性を確保しながら、常に最新バージョンのペイウォールを提供するよう設計されています。</p> | | **loadTimeout** | デフォルト: 5秒 | <p>このメソッドのタイムアウト時間を制限します。タイムアウトに達した場合、キャッシュデータまたはローカルフォールバックが返されます。</p><p>内部的に複数のリクエストで構成される場合があるため、まれに `loadTimeout` で指定した時間より若干遅くタイムアウトすることがあります。</p><p>Kotlin Multiplatformでは、`TimeInterval` を拡張関数(例:`import com.adapty.utils.seconds` の `.seconds` を使った `5.seconds`)または `TimeInterval.seconds(5)` で作成できます。制限を設けない場合は `TimeInterval.INFINITE` を使用してください。</p> | レスポンスパラメーター: | パラメーター | 説明 | | :-------- |:----------------------------------------------------------------------------------------------------------------------------------------------------------------| | Paywall | プロダクトIDのリスト、ペイウォール識別子、リモートコンフィグ、その他いくつかのプロパティを含む [`AdaptyPaywall`](https://kmp.adapty.io///adapty/com.adapty.kmp.models/-adapty-paywall/) オブジェクト。 | ## ペイウォールビルダーで作成したペイウォールのビュー設定を取得する \{#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder\} :::important ペイウォールビルダーの **Show on device** トグルが有効になっていることを確認してください。このオプションがオンになっていない場合、ビュー設定を取得できません。 ::: ペイウォールを取得したら、`ViewConfiguration` が含まれているか確認してください。これはペイウォールビルダーで作成されたことを示します。`ViewConfiguration` が存在する場合はペイウォールビルダーのペイウォールとして扱い、存在しない場合は[リモートコンフィグペイウォールとして処理](present-remote-config-paywalls-kmp)してください。 ビュー設定を読み込むには `createPaywallView` メソッドを使用します。 ```kotlin showLineNumbers if (paywall.hasViewConfiguration) { AdaptyUI.createPaywallView( paywall = paywall, loadTimeout = 5.seconds, preloadProducts = true ).onSuccess { paywallView -> // use paywallView }.onError { error -> // handle the error } } else { // use your custom logic } ``` | パラメーター | 必須/任意 | 説明 | | :--------------------------- | :------------- | :----------------------------------------------------------- | | **paywall** | 必須 | 目的のペイウォールのコントローラーを取得するための `AdaptyPaywall` オブジェクト。 | | **loadTimeout** | 任意 | このメソッドのタイムアウト時間を制限します。タイムアウトに達した場合、キャッシュデータまたはローカルフォールバックが返されます。内部的に複数のリクエストで構成される場合があるため、まれに `loadTimeout` で指定した時間より若干遅くタイムアウトすることがあります。`kotlin.time.Duration.Companion` の `5.seconds` などの拡張関数を使用できます。 | | **preloadProducts** | 任意 | パフォーマンス向上のためにプロダクトをプリロードするには `true` に設定します。有効にすると、プロダクトが事前に読み込まれ、ペイウォールの表示にかかる時間が短縮されます。 | | **productPurchaseParams** | 任意 | [`AdaptyProductIdentifier`](https://kmp.adapty.io/adapty/com.adapty.kmp.models/-adapty-product-identifier/) から [`AdaptyPurchaseParameters`](https://kmp.adapty.io/adapty/com.adapty.kmp.models/-adapty-purchase-parameters/) へのマップ。ペイウォール内の個別プロダクトに対して、パーソナライズドオファーやサブスクリプション更新パラメーターなど、購入固有のパラメーターを設定するために使用します。 | :::note 複数の言語を使用している場合は、[ペイウォールビルダーのローカライズ](add-paywall-locale-in-adapty-paywall-builder)を追加する方法を確認してください。 ::: 読み込みが完了したら、[ペイウォールを表示](kmp-present-paywalls)します。 ## デフォルトオーディエンス向けのペイウォールを取得して高速化する \{#get-a-paywall-for-a-default-audience-to-fetch-it-faster\} 通常、ペイウォールはほぼ瞬時に取得できるため、この処理を高速化することを気にする必要はありません。ただし、オーディエンスやペイウォールが多数あり、ユーザーのインターネット接続が弱い場合、ペイウォールの取得に期待以上の時間がかかることがあります。そのような状況では、ペイウォールをまったく表示しないよりも、デフォルトのペイウォールを表示してスムーズなユーザー体験を確保したい場合があります。 この問題に対処するため、指定されたプレースメントの **All Users** オーディエンス向けペイウォールを取得する `getPaywallForDefaultAudience` メソッドを使用できます。ただし、推奨されるアプローチは上記の[ペイウォール情報を取得する](#fetch-paywall-designed-with-paywall-builder)セクションで説明した `getPaywall` メソッドを使用することであることを理解しておくことが重要です。 :::warning `getPaywall` の使用を推奨する理由 `getPaywallForDefaultAudience` メソッドにはいくつかの重大な欠点があります: - **後方互換性の問題**: 現在と将来のアプリバージョンで異なるペイウォールを表示する必要がある場合、課題が生じる可能性があります。現在の(レガシー)バージョンをサポートするペイウォールを設計するか、現在の(レガシー)バージョンのユーザーがレンダリングされないペイウォールに遭遇する可能性を受け入れるかのどちらかになります。 - **ターゲティングの喪失**: すべてのユーザーが **All Users** オーディエンス向けに設計された同じペイウォールを見ることになり、国、マーケティングのアトリビューション、独自のカスタム属性に基づくパーソナライズされたターゲティングが失われます。 ペイウォールの取得を高速化するためにこれらの欠点を受け入れる場合は、以下のように `getPaywallForDefaultAudience` メソッドを使用してください。そうでない場合は、[上記](#fetch-paywall-designed-with-paywall-builder)で説明した `getPaywall` を使用してください。 ::: ```kotlin showLineNumbers Adapty.getPaywallForDefaultAudience( placementId = "YOUR_PLACEMENT_ID", locale = "en", fetchPolicy = AdaptyPaywallFetchPolicy.Default, ).onSuccess { paywall -> // the requested paywall }.onError { error -> // handle the error } ``` | パラメーター | 必須/任意 | 説明 | |---------|--------|-----------| | **placementId** | 必須 | [プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** | <p>任意</p><p>デフォルト: `en`</p> | <p>[ペイウォールのローカライズ](add-remote-config-locale)の識別子。マイナス(**-**)で区切られた1つまたは複数のサブタグで構成される言語コードです。最初のサブタグは言語、2番目はリージョンを表します。</p><p></p><p>例:`en` は英語、`pt-br` はブラジルポルトガル語を表します。</p><p></p><p>ロケールコードの詳細と推奨される使用方法については、[ローカライズとロケールコード](localizations-and-locale-codes)を参照してください。</p> | | **fetchPolicy** | デフォルト: `AdaptyPaywallFetchPolicy.Default` | <p>デフォルトでは、SDKはサーバーからデータを読み込もうとし、失敗した場合はキャッシュデータを返します。ユーザーが常に最新データを取得できるため、この設定を推奨します。</p><p></p><p>ただし、ユーザーが不安定なインターネット環境にいる場合は、`AdaptyPaywallFetchPolicy.ReturnCacheDataElseLoad` を使用してキャッシュデータが存在すればそれを返すことを検討してください。この場合、ユーザーが最新データを取得できないことがありますが、接続状況に関わらず読み込み時間が短縮されます。キャッシュは定期的に更新されるため、セッション中にネットワークリクエストを避けるために使用しても安全です。</p><p></p><p>キャッシュはアプリを再起動しても保持され、アプリの再インストールや手動クリーンアップ時のみクリアされます。</p> | ## アセットをカスタマイズする \{#customize-assets\} ペイウォール内の画像や動画をカスタマイズするには、カスタムアセットを実装します。 ヒーロー画像と動画には事前定義されたID(`hero_image` と `hero_video`)があります。カスタムアセットバンドルでは、これらの要素をIDで指定して動作をカスタマイズします。 その他の画像や動画については、Adapty ダッシュボードで[カスタムIDを設定](custom-media)する必要があります。 たとえば、以下のことができます: - 一部のユーザーに異なる画像や動画を表示する。 - リモートのメイン画像の読み込み中にローカルのプレビュー画像を表示する。 - 動画再生前にプレビュー画像を表示する。 :::important この機能を使用するには、Adapty SDKをバージョン3.7.0以上に更新してください。 ::: マップを使用してカスタムアセットを提供する例を示します: :::info Kotlin Multiplatform SDKはローカルアセットのみをサポートしています。リモートコンテンツの場合は、カスタムアセットで使用する前にアセットをダウンロードしてローカルにキャッシュしてください。 ::: ```kotlin showLineNumbers // Import generated Res class for accessing resources viewModelScope.launch { // Get URIs for bundled resources using Res.getUri() val heroImagePath = Res.getUri("files/images/hero_image.png") val demoVideoPath = Res.getUri("files/videos/demo_video.mp4") // Or read image as byte data val imageByteData = Res.readBytes("files/images/avatar.png") // Create custom assets map val customAssets: Map<String, AdaptyCustomAsset> = mapOf( // Load image from app resources (bundled with the app) // Files should be placed in commonMain/composeResources/files/ "hero_image" to AdaptyCustomAsset.localImageResource( path = heroImagePath ), // Or use image byte data "avatar" to AdaptyCustomAsset.localImageData( data = imageByteData ), // Load video from app resources "demo_video" to AdaptyCustomAsset.localVideoResource( path = demoVideoPath ), // Or use a video file from device storage "intro_video" to AdaptyCustomAsset.localVideoFile( path = "/path/to/local/video.mp4" ), // Apply custom brand colors "brand_primary" to AdaptyCustomAsset.color( colorHex = "#FF6B35" ), // Create gradient background "card_gradient" to AdaptyCustomAsset.linearGradient( colors = listOf("#1E3A8A", "#3B82F6", "#60A5FA"), stops = listOf(0.0f, 0.5f, 1.0f) ) ) // Use custom assets when creating paywall view AdaptyUI.createPaywallView( paywall = paywall, customAssets = customAssets ).onSuccess { paywallView -> // Present the paywall with custom assets paywallView.present() }.onError { error -> // Handle the error - paywall will fall back to default appearance } } ``` :::note アセットが見つからない場合や読み込みに失敗した場合、ペイウォールはペイウォールビルダーで設定されたデフォルトの外観にフォールバックします。 ::: --- # File: kmp-present-paywalls --- --- title: "Kotlin Multiplatform - 新しいペイウォールビルダーのペイウォールを表示する" description: "Kotlin Multiplatformでペイウォールを表示して効果的なマネタイズを実現する方法を学びましょう。" --- ペイウォールビルダーを使ってペイウォールをカスタマイズした場合、モバイルアプリのコードでレンダリングをゼロから実装する必要はありません。ペイウォールには「何を表示するか」と「どのように表示するか」の情報が含まれています。 :::warning このガイドは**新しいペイウォールビルダーのペイウォール**専用です。リモートコンフィグで設計されたペイウォールや [Observer モード](observer-vs-full-mode) では、ペイウォールの表示方法が異なります。 **リモートコンフィグのペイウォール**を表示する方法については、[リモートコンフィグで設計されたペイウォールをレンダリングする](present-remote-config-paywalls-kmp) をご覧ください。 ::: Adapty Kotlin Multiplatform SDK では、ペイウォールを表示する方法が 2 つあります。 - **Compose Multiplatform を使用する** - **Compose Multiplatform を使用しない** ## Compose Multiplatform を使用する \{#with-compose-multiplatform\} ペイウォールを表示するには、[`createPaywallView`](kmp-get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder) メソッドで作成した `view` に対して `view.present()` メソッドを呼び出します。各 `view` は一度しか使用できません。ペイウォールを再度表示する必要がある場合は、`createPaywallView` を再度呼び出して新しい `view` インスタンスを作成してください。 :::warning `view` を再作成せずに使い回すとエラーが発生する場合があります。 ::: ```kotlin showLineNumbers title="Kotlin Multiplatform" viewModelScope.launch { AdaptyUI.createPaywallView(paywall = paywall).onSuccess { view -> view.present() }.onError { error -> // handle the error } } ``` ### ダイアログを表示する \{#show-dialog\} Android でペイウォールビューが表示されている場合は、ネイティブのアラートダイアログの代わりにこのメソッドを使用してください。Android では通常のアラートがペイウォールビューの背後に表示されてしまい、ユーザーから見えなくなります。このメソッドを使うことで、すべてのプラットフォームでペイウォールの上にダイアログが正しく表示されます。 ```kotlin showLineNumbers title="Kotlin Multiplatform" viewModelScope.launch { view.showDialog( title = "Close paywall?", content = "You will lose access to exclusive offers.", primaryActionTitle = "Stay", secondaryActionTitle = "Close" ).onSuccess { action -> if (action == AdaptyUIDialogActionType.SECONDARY) { // User confirmed - close the paywall view.dismiss() } // If primary - do nothing, user stays }.onError { error -> // handle the error } } ``` ### iOS の表示スタイルを設定する \{#configure-ios-presentation-style\} `present()` メソッドに `iosPresentationStyle` パラメータを渡すことで、iOS でのペイウォールの表示スタイルを設定できます。このパラメータには `AdaptyUIIOSPresentationStyle.FULLSCREEN`(デフォルト)または `AdaptyUIIOSPresentationStyle.PAGESHEET` を指定できます。 ```kotlin showLineNumbers viewModelScope.launch { val view = AdaptyUI.createPaywallView(paywall = paywall).getOrNull() view?.present(iosPresentationStyle = AdaptyUIIOSPresentationStyle.PAGESHEET) } ``` ## Compose Multiplatform を使用しない \{#without-compose-multiplatform\} :::note `createNativePaywallView` はコアモジュール `io.adapty:adapty-kmp` に含まれています。プロジェクトで Compose Multiplatform を使用していない場合、`io.adapty:adapty-kmp-ui` への依存は不要です。 ::: Compose Multiplatform を使用せずにペイウォールを埋め込むには、`createNativePaywallView` を呼び出します。このメソッドはレイアウトに追加できる `AdaptyNativePaywallView` を返します。 <Tabs> <TabItem value="android" label="Android"> ```kotlin showLineNumbers title="Kotlin Multiplatform (Android)" val nativeView = AdaptyUI.createNativePaywallView( context = context, viewModelStoreOwner = activity, paywall = paywall, observer = myPaywallObserver, ) // Embed in your Compose layout: AndroidView( factory = { nativeView.view }, modifier = Modifier.fillMaxSize() ) ``` </TabItem> <TabItem value="ios" label="iOS"> KMP インターフェースのデフォルトメソッドは Swift では `@required` になるため、Swift から直接 `AdaptyUIPaywallsEventsObserver` を実装することはできません。まず `iosMain` にオープンな基底クラスを宣言してください。 ```kotlin showLineNumbers title="iosMain (Kotlin)" open class BasePaywallObserver : AdaptyUIPaywallsEventsObserver ``` 次に Swift でサブクラスを作成し、必要なメソッドのみオーバーライドします。 ```swift showLineNumbers title="Swift" class MyPaywallObserver: BasePaywallObserver { override func paywallViewDidPerformAction(view: AdaptyUIPaywallView, action: any AdaptyUIAction) { if action is AdaptyUIActionCloseAction { // remove nativeView from your view hierarchy } } } let nativeView = AdaptyUI.shared.createNativePaywallView( paywall: paywall, observer: MyPaywallObserver() ) // nativeView.viewController is a UIViewController. // Add it to your SwiftUI view or UIKit hierarchy. ``` </TabItem> </Tabs> ### ビューを破棄する \{#dispose-the-view\} レイアウトからビューを削除する際は `dispose()` を呼び出してください。これによりイベントリスナーの登録が解除され、内部リソースが解放されます。 ```kotlin showLineNumbers title="Kotlin Multiplatform" nativeView.dispose() ``` ## カスタムタグ \{#custom-tags\} カスタムタグを使うと、シナリオごとに別々のペイウォールを作らずに済みます。ユーザーデータに応じて動的に変化するペイウォールを 1 つ用意するイメージです。たとえば、"Hello!" という汎用的な文言の代わりに、"Hello, John!" や "Hello, Ann!" のようにユーザーに合わせた挨拶を表示できます。 カスタムタグの活用例を以下に示します。 - ペイウォールにユーザーの名前やメールアドレスを表示する。 - 売上促進のために現在の曜日を表示する(例:「Happy Thursday」)。 - 販売中のプロダクトに関するパーソナライズされた情報(フィットネスプログラムの名称や VoIP アプリの電話番号など)を追加する。 カスタムタグを使うと、様々な状況に柔軟に対応できるペイウォールを作成でき、アプリのインターフェースをよりパーソナライズして魅力的にできます。 :::warning AdaptyUI SDK の古いバージョンを使用しているユーザーを対象とするケースなど、カスタムタグの置換先が不明な場合があります。そのため、未知のカスタムタグを含む行を置き換えるフォールバックテキストを必ず設定してください。設定しないと、タグがコード(`<USERNAME/>`)としてそのまま表示されてしまいます。 ::: ペイウォールでカスタムタグを使用するには、ペイウォールビューを作成する際に渡します。 <Tabs> <TabItem value="standalone" label="With Compose Multiplatform" default> ```kotlin showLineNumbers title="Kotlin Multiplatform" viewModelScope.launch { val customTags = mapOf( "USERNAME" to "John", "DAY_OF_WEEK" to "Thursday" ) AdaptyUI.createPaywallView( paywall = paywall, customTags = customTags ).onSuccess { view -> view.present() }.onError { error -> // handle the error } } ``` </TabItem> <TabItem value="native" label="Without Compose Multiplatform"> ```kotlin showLineNumbers title="Kotlin Multiplatform (Android)" val customTags = mapOf( "USERNAME" to "John", "DAY_OF_WEEK" to "Thursday" ) val nativeView = AdaptyUI.createNativePaywallView( context = context, viewModelStoreOwner = activity, paywall = paywall, observer = myPaywallObserver, customTags = customTags, ) ``` ```kotlin showLineNumbers title="Kotlin Multiplatform (iOS)" val customTags = mapOf( "USERNAME" to "John", "DAY_OF_WEEK" to "Thursday" ) val nativeView = AdaptyUI.createNativePaywallView( paywall = paywall, observer = myPaywallObserver, customTags = customTags, ) ``` </TabItem> </Tabs> ## カスタムタイマー \{#custom-timers\} ペイウォールのタイマーは、期間限定の特別オファーや季節限定オファーを訴求する優れたツールです。ただし、このタイマーはオファーの有効期間やキャンペーンの期間とは連動していません。設定した値からゼロに向かってカウントダウンするだけのスタンドアロンのタイマーです。タイマーがゼロになっても何も起こりません。ゼロのまま停止するだけです。 タイマーの前後にテキストをカスタマイズして、「残り時間:10:00 秒」のようなメッセージを作成できます。 ペイウォールでカスタムタイマーを使用するには、ペイウォールビューを作成する際に渡します。 <Tabs> <TabItem value="standalone" label="With Compose Multiplatform" default> ```kotlin showLineNumbers title="Kotlin Multiplatform" viewModelScope.launch { val customTimers = mapOf( "CUSTOM_TIMER_NY" to LocalDateTime(2025, 1, 1, 0, 0, 0), "CUSTOM_TIMER_SALE" to LocalDateTime(2024, 12, 31, 23, 59, 59) ) AdaptyUI.createPaywallView( paywall = paywall, customTimers = customTimers ).onSuccess { view -> view.present() }.onError { error -> // handle the error } } ``` </TabItem> <TabItem value="native" label="Without Compose Multiplatform"> ```kotlin showLineNumbers title="Kotlin Multiplatform (Android)" val customTimers = mapOf( "CUSTOM_TIMER_NY" to LocalDateTime(2025, 1, 1, 0, 0, 0), "CUSTOM_TIMER_SALE" to LocalDateTime(2024, 12, 31, 23, 59, 59) ) val nativeView = AdaptyUI.createNativePaywallView( context = context, viewModelStoreOwner = activity, paywall = paywall, observer = myPaywallObserver, customTimers = customTimers, ) ``` ```kotlin showLineNumbers title="Kotlin Multiplatform (iOS)" val customTimers = mapOf( "CUSTOM_TIMER_NY" to LocalDateTime(2025, 1, 1, 0, 0, 0), "CUSTOM_TIMER_SALE" to LocalDateTime(2024, 12, 31, 23, 59, 59) ) val nativeView = AdaptyUI.createNativePaywallView( paywall = paywall, observer = myPaywallObserver, customTimers = customTimers, ) ``` </TabItem> </Tabs> --- # File: kmp-handle-paywall-actions --- --- title: "Kotlin Multiplatform SDKでボタンアクションに応答する" description: "Adaptyを使用してKotlin Multiplatformでペイウォールのボタンアクションを処理し、アプリの収益化を向上させます。" --- :::warning **購入と復元のみが自動で処理されます。** ペイウォールを閉じたりリンクを開いたりするような、それ以外のボタンアクションはすべて、アプリのコードで適切なレスポンスを実装する必要があります。 ::: Adaptyのペイウォールビルダーを使ってペイウォールを作成する場合、ボタンを適切に設定することが重要です: 1. [ペイウォールビルダーにボタンを追加](paywall-buttons)し、既存のアクションを割り当てるか、カスタムアクションIDを作成します。 2. 割り当てた各アクションを処理するコードをアプリに記述します。 このガイドでは、コード内でカスタムアクションと既存アクションを処理する方法を説明します。 ## AdaptyUIPaywallsEventsObserverを設定する \{#set-up-the-adaptyuipaywallsevents-observer\} ペイウォールのアクションを処理するには、`AdaptyUIPaywallsEventsObserver`インターフェースを実装し、`AdaptyUI.setPaywallsEventsObserver()`で設定する必要があります。これはアプリのライフサイクルの早い段階、通常はメインアクティビティやアプリの初期化時に行います。 ```kotlin // In your app initialization AdaptyUI.setPaywallsEventsObserver(MyAdaptyUIPaywallsEventsObserver()) ``` ## ペイウォールを閉じる \{#close-paywalls\} ペイウォールを閉じるボタンを追加するには: 1. ペイウォールビルダーでボタンを追加し、**Close**アクションを割り当てます。 2. アプリのコードで、ペイウォールを閉じる`close`アクションのハンドラーを実装します。 :::info Kotlin Multiplatform SDKでは、`CloseAction`と`AndroidSystemBackAction`がデフォルトでペイウォールを閉じます。ただし、必要に応じてコードでこの動作をオーバーライドできます。たとえば、あるペイウォールを閉じたときに別のペイウォールを開くといった使い方が可能です。 ::: ```kotlin class MyAdaptyUIPaywallsEventsObserver : AdaptyUIPaywallsEventsObserver { override fun paywallViewDidPerformAction(view: AdaptyUIPaywallView, action: AdaptyUIAction) { when (action) { AdaptyUIAction.CloseAction, AdaptyUIAction.AndroidSystemBackAction -> view.dismiss() } } } // Set up the observer AdaptyUI.setPaywallsEventsObserver(MyAdaptyUIPaywallsEventsObserver()) ``` [`createNativePaywallView`](kmp-present-paywalls#without-compose-multiplatform)を使用している場合、`view.dismiss()`を呼び出しても効果はありません。このビューはKMPスタックを通じて表示されるのではなく、レイアウトに埋め込まれているためです。代わりに、レイアウトからビューを削除し、`dispose()`を呼び出してください。 ## ペイウォールからURLを開く \{#open-urls-from-paywalls\} :::tip リンクのグループ(利用規約や購入の復元など)を追加したい場合は、ペイウォールビルダーに**Link**要素を追加し、**Open URL**アクションが設定されたボタンと同じ方法で処理してください。 ::: ペイウォールからリンクを開くボタン(例:**利用規約**や**プライバシーポリシー**)を追加するには: 1. ペイウォールビルダーでボタンを追加し、**Open URL**アクションを割り当てて、開きたいURLを入力します。 2. アプリのコードで、受け取ったURLをブラウザで開く`openUrl`アクションのハンドラーを実装します。 :::info Kotlin Multiplatform SDKでは、`OpenUrlAction`が開くべきURLを提供します。確認ダイアログの表示やアプリ独自のURL処理方法を使用するなど、URL開封処理のカスタムロジックを実装できます。 ::: ```kotlin class MyAdaptyUIPaywallsEventsObserver( private val uriHandler: UriHandler ) : AdaptyUIPaywallsEventsObserver { override fun paywallViewDidPerformAction(view: AdaptyUIPaywallView, action: AdaptyUIAction) { when (action) { is AdaptyUIAction.OpenUrlAction -> { // Show confirmation dialog before opening URL mainUiScope.launch { val selectedAction = view.showDialog( title = "Open URL?", content = action.url, primaryActionTitle = "Cancel", secondaryActionTitle = "Open" ).getOrNull() when (selectedAction) { AdaptyUIDialogActionType.PRIMARY -> { // User cancelled } AdaptyUIDialogActionType.SECONDARY -> { // User confirmed - open URL uriHandler.openUri(action.url) } else -> Unit } } } } } } // Set up the observer with UriHandler AdaptyUI.setPaywallsEventsObserver(MyAdaptyUIPaywallsEventsObserver(uriHandler)) ``` ## アプリへのログイン \{#log-into-the-app\} ユーザーをアプリにログインさせるボタンを追加するには: 1. ペイウォールビルダーでボタンを追加し、ID「login」の**Custom**アクションを割り当てます。 2. アプリのコードで、ユーザーを識別するカスタムアクションのハンドラーを実装します。 ```kotlin class MyAdaptyUIObserver : AdaptyUIObserver { override fun paywallViewDidPerformAction(view: AdaptyUIView, action: AdaptyUIAction) { when (action) { is AdaptyUIAction.CustomAction -> { if (action.action == "login") { // Handle login action - navigate to login screen // This depends on your app's navigation system // For example, in Compose Multiplatform: // navController.navigate("login") } } } } } ``` ## カスタムアクションを処理する \{#handle-custom-actions\} その他のアクションを処理するボタンを追加するには: 1. ペイウォールビルダーでボタンを追加し、**Custom**アクションを割り当ててIDを設定します。 2. アプリのコードで、作成したアクションIDのハンドラーを実装します。 たとえば、別のサブスクリプションオファーや買い切り購入がある場合、別のペイウォールを表示するボタンを追加できます: ```kotlin class MyAdaptyUIPaywallsEventsObserver : AdaptyUIPaywallsEventsObserver { override fun paywallViewDidPerformAction(view: AdaptyUIPaywallView, action: AdaptyUIAction) { when (action) { is AdaptyUIAction.CustomAction -> { when (action.action) { "login" -> { // Handle login action - navigate to login screen // This depends on your app's navigation system // For example, in Compose Multiplatform: // navController.navigate("login") } } } } } } // Set up the observer AdaptyUI.setPaywallsEventsObserver(MyAdaptyUIPaywallsEventsObserver()) ``` --- # File: kmp-handling-events --- --- title: "Kotlin Multiplatform - ペイウォールイベントの処理" description: "Adaptyのイベントトラッキングツールを使って、Kotlin Multiplatformのサブスクリプションイベントを効率的に処理します。" --- [ペイウォールビルダー](adapty-paywall-builder)で設定されたペイウォールは、購入や復元を行うための追加コードは不要です。ただし、アプリが対応できるいくつかのイベントが発生します。これらのイベントには、ボタン操作(閉じるボタン、URL、プロダクト選択など)や、ペイウォール上で行われた購入関連のアクションに関する通知が含まれます。以下でこれらのイベントへの対応方法を説明します。 :::warning このガイドは**新しいペイウォールビルダーのペイウォール**専用です。 ::: モバイルアプリのペイウォール画面で発生するプロセスを制御・監視するには、`AdaptyUIPaywallsEventsObserver` インターフェースのメソッドを実装してください。一部のメソッドには、一般的なシナリオを自動的に処理するデフォルト実装があります。 :::note これらのメソッドは、ペイウォールイベントに応じたカスタムロジックを追加する場所です。`view.dismiss()` を使ってペイウォールを閉じることも、その他のカスタム動作を実装することもできます。 ::: ## ユーザー生成イベント \{#user-generated-events\} ### ペイウォールの表示・非表示 \{#paywall-appearance-and-disappearance\} ペイウォールが表示または非表示になると、これらのメソッドが呼び出されます: ```kotlin showLineNumbers title="Kotlin" override fun paywallViewDidAppear(view: AdaptyUIPaywallView) { // Handle paywall appearance // You can track analytics or update UI here } override fun paywallViewDidDisappear(view: AdaptyUIPaywallView) { // Handle paywall disappearance // You can track analytics or update UI here } ``` :::note - iOS では、ユーザーがペイウォール内の[ウェブペイウォールボタン](web-paywall#step-2a-add-a-web-purchase-button)をタップしてアプリ内ブラウザでウェブペイウォールが開いたときにも、`paywallViewDidAppear` が呼び出されます。 - iOS では、ペイウォールからアプリ内ブラウザで開いた[ウェブペイウォール](web-paywall#step-2a-add-a-web-purchase-button)が画面から消えたときにも、`paywallViewDidDisappear` が呼び出されます。 ::: <Details> <summary>イベント例(クリックして展開)</summary> ```javascript // Paywall appeared { // No additional data } // Paywall disappeared { // No additional data } ``` </Details> ### プロダクト選択 \{#product-selection\} ユーザーが購入するプロダクトを選択すると、このメソッドが呼び出されます: ```kotlin showLineNumbers title="Kotlin" override fun paywallViewDidSelectProduct(view: AdaptyUIPaywallView, productId: String) { // Handle product selection // You can update UI or track analytics here } ``` <Details> <summary>イベント例(クリックして展開)</summary> ```javascript { "productId": "premium_monthly" } ``` </Details> ### 購入開始 \{#started-purchase\} ユーザーが購入プロセスを開始すると、このメソッドが呼び出されます: ```kotlin showLineNumbers title="Kotlin" override fun paywallViewDidStartPurchase(view: AdaptyUIPaywallView, product: AdaptyPaywallProduct) { // Handle purchase start // You can show loading indicators or track analytics here } ``` <Details> <summary>イベント例(クリックして展開)</summary> ```javascript { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" } } ``` </Details> ### 購入成功・キャンセル・保留 \{#successful-canceled-or-pending-purchase\} 購入が成功すると、このメソッドが呼び出されます。デフォルトでは、ユーザーによってキャンセルされた場合を除き、ペイウォールを自動的に閉じます: ```kotlin showLineNumbers title="Kotlin" override fun paywallViewDidFinishPurchase( view: AdaptyUIPaywallView, product: AdaptyPaywallProduct, purchaseResult: AdaptyPurchaseResult ) { when (purchaseResult) { is AdaptyPurchaseResult.Success -> { // Check if user has access to premium features if (purchaseResult.profile.accessLevels["premium"]?.isActive == true) { view.dismiss() } } AdaptyPurchaseResult.Pending -> { // Handle pending purchase (e.g., user will pay offline with cash) } AdaptyPurchaseResult.UserCanceled -> { // Handle user cancellation } } } ``` <Details> <summary>イベント例(クリックして展開)</summary> ```javascript // Successful purchase { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "purchaseResult": { "type": "Success", "profile": { "accessLevels": { "premium": { "id": "premium", "isActive": true, "expiresAt": "2024-02-15T10:30:00Z" } } } } } // Pending purchase { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "purchaseResult": { "type": "Pending" } } // User canceled purchase { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "purchaseResult": { "type": "UserCanceled" } } ``` </Details> 購入が成功した場合は、ペイウォール画面を閉じることをお勧めします。 ### 購入失敗 \{#failed-purchase\} エラーにより購入が失敗すると、このメソッドが呼び出されます。これには StoreKit/Google Play Billing のエラー(支払い制限、無効なプロダクト、ネットワーク障害)、トランザクション検証の失敗、システムエラーが含まれます。なお、ユーザーによるキャンセルの場合は、キャンセル結果とともに `paywallViewDidFinishPurchase` が呼び出され、保留中の支払いではこのメソッドは呼び出されません。 ```kotlin showLineNumbers title="Kotlin" override fun paywallViewDidFailPurchase( view: AdaptyUIPaywallView, product: AdaptyPaywallProduct, error: AdaptyError ) { // Add your purchase failure handling logic here // For example: show error message, retry option, or custom error handling } ``` <Details> <summary>イベント例(クリックして展開)</summary> ```javascript { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "error": { "code": "purchase_failed", "message": "Purchase failed due to insufficient funds", "details": { "underlyingError": "Insufficient funds in account" } } } ``` </Details> ### 復元開始 \{#started-restore\} ユーザーが復元プロセスを開始すると、このメソッドが呼び出されます: ```kotlin showLineNumbers title="Kotlin" override fun paywallViewDidStartRestore(view: AdaptyUIPaywallView) { // Handle restore start // You can show loading indicators or track analytics here } ``` ### 復元成功 \{#successful-restore\} 購入の復元が成功すると、このメソッドが呼び出されます: ```kotlin showLineNumbers title="Kotlin" override fun paywallViewDidFinishRestore(view: AdaptyUIPaywallView, profile: AdaptyProfile) { // Add your successful restore handling logic here // For example: show success message, update UI, or dismiss paywall // Check if user has access to premium features if (profile.accessLevels["premium"]?.isActive == true) { view.dismiss() } } ``` <Details> <summary>イベント例(クリックして展開)</summary> ```javascript { "profile": { "accessLevels": { "premium": { "id": "premium", "isActive": true, "expiresAt": "2024-02-15T10:30:00Z" } }, "subscriptions": [ { "vendorProductId": "premium_monthly", "isActive": true, "expiresAt": "2024-02-15T10:30:00Z" } ] } } ``` </Details> ユーザーが必要な `accessLevel` を持っている場合は、画面を閉じることをお勧めします。確認方法については、[サブスクリプションステータス](subscription-status)を参照してください。 ### 復元失敗 \{#failed-restore\} `Adapty.restorePurchases()` が失敗すると、このメソッドが呼び出されます: ```kotlin showLineNumbers title="Kotlin" override fun paywallViewDidFailRestore(view: AdaptyUIPaywallView, error: AdaptyError) { // Add your restore failure handling logic here // For example: show error message, retry option, or custom error handling } ``` <Details> <summary>イベント例(クリックして展開)</summary> ```javascript { "error": { "code": "restore_failed", "message": "Purchase restoration failed", "details": { "underlyingError": "No previous purchases found" } } } ``` </Details> ### ウェブ決済ナビゲーション完了 \{#web-payment-navigation-completion\} ユーザーが[ウェブペイウォール](web-paywall)を使って購入プロセスを開始すると、このメソッドが呼び出されます: ```kotlin showLineNumbers title="Kotlin" override fun paywallViewDidFinishWebPaymentNavigation( view: AdaptyUIPaywallView, product: AdaptyPaywallProduct?, error: AdaptyError? ) { if (error != null) { // Handle web payment navigation error } else { // Handle successful web payment navigation } } ``` <Details> <summary>イベント例(クリックして展開)</summary> ```javascript // Successful web payment navigation { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "error": null } // Failed web payment navigation { "product": null, "error": { "code": "web_payment_failed", "message": "Web payment navigation failed", "details": { "underlyingError": "Network connection error" } } } ``` </Details> ## データ取得とレンダリング \{#data-fetching-and-rendering\} ### プロダクト読み込みエラー \{#product-loading-errors\} 初期化時にプロダクトを渡さない場合、AdaptyUI は必要なオブジェクトをサーバーから自動的に取得します。この操作が失敗した場合、AdaptyUI はこのメソッドを呼び出してエラーを報告します: ```kotlin showLineNumbers title="Kotlin" override fun paywallViewDidFailLoadingProducts(view: AdaptyUIPaywallView, error: AdaptyError) { // Add your product loading failure handling logic here // For example: show error message, retry option, or custom error handling } ``` <Details> <summary>イベント例(クリックして展開)</summary> ```javascript { "error": { "code": "products_loading_failed", "message": "Failed to load products from the server", "details": { "underlyingError": "Network timeout" } } } ``` </Details> ### レンダリングエラー \{#rendering-errors\} インターフェースのレンダリング中にエラーが発生した場合、このメソッドによって報告されます: ```kotlin showLineNumbers title="Kotlin" override fun paywallViewDidFailRendering(view: AdaptyUIPaywallView, error: AdaptyError) { // Handle rendering error // In a normal situation, such errors should not occur // If you come across one, please let us know } ``` <Details> <summary>イベント例(クリックして展開)</summary> ```javascript { "error": { "code": "rendering_failed", "message": "Failed to render paywall interface", "details": { "underlyingError": "Invalid paywall configuration" } } } ``` </Details> 通常の状況では、このようなエラーは発生しないはずです。もし遭遇した場合は、ぜひお知らせください。 --- # File: kmp-use-fallback-paywalls --- --- title: "Kotlin Multiplatform - フォールバックペイウォールを使用する" description: "ユーザーがオフラインの場合やAdaptyサーバーが利用できない場合に対応する" --- スムーズなユーザー体験を維持するために、フロー、[ペイウォール](paywalls)、[オンボーディング](onboardings)に[フォールバック](/fallback-paywalls)を設定することが重要です。この対策により、インターネット接続が部分的または完全に失われた場合でも、アプリケーションの機能を維持できます。 * **アプリケーションが Adapty サーバーにアクセスできない場合:** フォールバックのフローまたはペイウォールを表示し、ローカルのオンボーディング設定にアクセスできます。 * **アプリケーションがインターネットにアクセスできない場合:** フォールバックのフローまたはペイウォールを表示できます。オンボーディングはリモートコンテンツを含むため、動作にはインターネット接続が必要です。 :::important このガイドの手順を進める前に、Adapty からフォールバック設定ファイルを[ダウンロード](/local-fallback-paywalls)してください。 ::: ## 設定 \{#configuration\} 1. フォールバック設定ファイルをアプリケーションに追加します。 * ターゲットプラットフォームが Android の場合、フォールバック設定ファイルを `android/app/src/main/assets/` フォルダに移動します。 * ターゲットプラットフォームが iOS の場合、フォールバック JSON ファイルをプロジェクトバンドルに追加します。(**File** -> **Add Files to YourProjectName**) 2. ターゲットのペイウォールまたはオンボーディングを取得する**前に**、`.setFallback` メソッドを呼び出します。 3. ターゲットプラットフォームに応じて `assetId` パラメータを設定します。 * Android: `assets` ディレクトリからの相対ファイルパスを使用します。 * iOS: ファイル名(拡張子含む)を使用します。 ```kotlin showLineNumbers Adapty.setFallback(assetId = "fallback.json") .onSuccess { // Fallback paywalls loaded successfully } .onError { error -> // Handle the error } ``` パラメータ: | パラメータ | 説明 | | :---------- |:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **assetId** | フォールバック設定のファイル名(iOS)。<br /> `assets` ディレクトリからの相対パスで指定したフォールバック設定ファイルのパス(Android)。 | :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: --- # File: kmp-localizations-and-locale-codes --- --- title: "Kotlin Multiplatform SDKでローカライゼーションとロケールコードを使用する" description: "Kotlin Multiplatformアプリでグローバルなユーザーにリーチするために、アプリのローカライゼーションとロケールコードを管理します。" --- ## なぜこれが重要なのか \{#why-this-is-important\} ロケールコードが必要になるシナリオはいくつかあります。たとえば、アプリの現在のローカライゼーションに合った正しいペイウォールを取得しようとする場合などです。 ロケールコードは複雑で、プラットフォームによって異なることがあります。そのため、Adaptyがサポートするすべてのプラットフォームで統一した内部標準を採用しています。ただし、これらのコードが複雑であるため、サーバーに送信している内容と、その後何が起こるかを正確に理解することがとても重要です。そうすることで、常に期待通りの結果を受け取ることができます。 ## Adaptyにおけるロケールコードの標準 \{#locale-code-standard-at-adapty\} ロケールコードについて、Adaptyは[BCP 47標準](https://en.wikipedia.org/wiki/IETF_language_tag)を若干修正したものを使用しています。各コードは小文字のサブタグをハイフンで区切って構成されます。例:`en`(英語)、`pt-br`(ポルトガル語(ブラジル))、`zh`(簡体字中国語)、`zh-hant`(繁体字中国語)。 ## ロケールコードのマッチング \{#locale-code-matching\} AdaptyがクライアントサイドSDKからロケールコードを含む呼び出しを受け取り、対応するペイウォールのローカライゼーションを検索する際、以下の処理が行われます: 1. 受信したロケール文字列を小文字に変換し、アンダースコア(`_`)をすべてハイフン(`-`)に置換します 2. 完全一致するロケールコードのローカライゼーションを検索します 3. 一致するものが見つからない場合、最初のハイフンより前の部分文字列(`pt-br` に対しては `pt`)を取り出して、一致するローカライゼーションを検索します 4. それでも一致するものが見つからない場合、デフォルトの `en` ローカライゼーションを返します これにより、`'pt_BR'` を送信したiOSデバイス、`pt-BR` を送信したAndroidデバイス、`pt-br` を送信した別のデバイスはすべて同じ結果を受け取ります。 ## ローカライゼーションの実装:推奨方法 \{#implementing-localizations-recommended-way\} ローカライゼーションについて検討しているなら、おそらくすでにプロジェクトでローカライズされた文字列リソースを扱っているでしょう。その場合、各リソースファイルに対応するローカライゼーション用のAdaptyロケールコードをキーと値のペアとして追加することをお勧めします。そして、次のようにSDKを呼び出す際にそのキーの値を取り出して使用してください: ```kotlin showLineNumbers // 1. Add the Adapty locale code to your Compose Multiplatform resources /* composeResources/values/strings.xml (default — English) */ <string name="adapty_paywalls_locale">en</string> /* composeResources/values-es/strings.xml (Spanish) */ <string name="adapty_paywalls_locale">es</string> /* composeResources/values-pt-rBR/strings.xml (Portuguese — Brazil) */ <string name="adapty_paywalls_locale">pt-br</string> // 2. Extract and use the locale code suspend fun fetchPaywall() { val locale = getString(Res.string.adapty_paywalls_locale) Adapty.getPaywall( placementId = "YOUR_PLACEMENT_ID", locale = locale ).onSuccess { paywall -> // the requested paywall }.onError { error -> // handle the error } } ``` この方法により、アプリのすべてのユーザーに対してどのローカライゼーションが取得されるかを完全に制御できます。 Compose Multiplatformのリソースを使用していない場合でも、同じ考え方は他のローカライゼーションライブラリ(例:[moko-resources](https://github.com/icerockdev/moko-resources))にも適用できます。各ロケールのリソースバンドルにAdaptyロケールコードを文字列として保存し、SDKを呼び出す前にそれを読み取るようにしてください。 ## ローカライゼーションの実装:別の方法 \{#implementing-localizations-the-other-way\} すべてのローカライゼーションに対してロケールコードを明示的に定義しなくても、同様の(ただし同一ではない)結果を得ることができます。その場合、デバイスから直接ロケールコードを取得することになりますが、`commonMain` に共通のロケールAPIが存在しないため、`expect`/`actual` 宣言が必要になります: ```kotlin showLineNumbers // commonMain expect fun currentLocaleTag(): String // androidMain actual fun currentLocaleTag(): String = Locale.getDefault().toLanguageTag() // iosMain actual fun currentLocaleTag(): String = NSLocale.currentLocale.localeIdentifier // commonMain — pass the locale code to Adapty suspend fun fetchPaywall() { Adapty.getPaywall( placementId = "YOUR_PLACEMENT_ID", locale = currentLocaleTag() ).onSuccess { paywall -> // the requested paywall }.onError { error -> // handle the error } } ``` この方法はいくつかの理由から推奨しません: 1. iOSでは、ユーザーの優先言語とデバイスの地域ロケールは同一ではありません。`NSLocale.currentLocale.localeIdentifier` は地域ロケールを返しますが、これはユーザーが実際にアプリを読む言語と異なる場合があります。ローカライズされた文字列ファイルを使用するiOSアプリは、Appleの解決ロジックを使って両者を組み合わせており、上記の推奨方法ではこれが自動的に処理されます。 2. デバイスが返す値を正確に予測するのは難しく、それがAdaptyのローカライゼーションと一致するかどうかも不明です。デバイスのロケールには、Adaptyで設定していない拡張子や地域コードが含まれる場合があり、その場合SDKは最初のサブタグの一致、または最終的に `en` にフォールバックします。 それでもこの方法を使用する場合は、関連するすべてのユースケースに対応できていることを確認してください。 --- # File: kmp-web-paywalls --- --- title: "Kotlin Multiplatform SDKでウェブペイウォールを実装する" description: "ストアの手数料や審査なしで課金できるウェブペイウォールを設定します。" --- :::important 始める前に、[ダッシュボードでウェブペイウォールを設定](web-paywall)し、Adapty SDK バージョン3.15以降をインストールしていることを確認してください。 ::: ## ウェブペイウォールを開く \{#open-web-paywalls\} 自分で開発したペイウォールを使用している場合、SDKメソッドを使ってウェブペイウォールを処理する必要があります。`openWebPaywall` メソッドは以下を行います: 1. 特定のユーザーに表示されたペイウォールと、リダイレクト先のウェブページをAdaptyが紐付けるための一意のURLを生成します。 2. ユーザーがアプリに戻ったタイミングを検知し、短い間隔で `getProfile` を呼び出してプロファイルのアクセス権が更新されたかどうかを確認します。 これにより、決済が成功してアクセス権が更新された場合、サブスクリプションはほぼ即座にアプリ内で有効になります。 :::note ユーザーがアプリに戻った後、プロファイルの更新を反映するためにUIを更新してください。AdaptyはプロファイルUpdateイベントを受信して処理します。 ::: ```kotlin showLineNumbers viewModelScope.launch { Adapty.openWebPaywall(product = product).onSuccess { // the web paywall was opened successfully }.onError { error -> // handle the error } } ``` :::note `openWebPaywall` メソッドには2つのバージョンがあります: 1. `openWebPaywall(product = product)` — ペイウォールをもとにURLを生成し、プロダクトのデータもURLに含めます。 2. `openWebPaywall(paywall = paywall)` — ペイウォールをもとにURLを生成しますが、プロダクトのデータはURLに含めません。Adaptyのペイウォールのプロダクトとウェブペイウォールのプロダクトが異なる場合に使用してください。 ::: ## アプリ内ブラウザでウェブペイウォールを開く \{#open-web-paywalls-in-an-in-app-browser\} デフォルトでは、ウェブペイウォールは外部ブラウザで開きます。 シームレスなユーザー体験を提供するために、アプリ内ブラウザでウェブペイウォールを開くことができます。これにより、ウェブ購入ページがアプリ内に表示され、ユーザーはアプリを切り替えることなくトランザクションを完了できます。 これを有効にするには、`openIn` パラメーターを `AdaptyWebPresentation.IN_APP_BROWSER` に設定してください: ```kotlin showLineNumbers viewModelScope.launch { Adapty.openWebPaywall( product = product, openIn = AdaptyWebPresentation.IN_APP_BROWSER // default – EXTERNAL_BROWSER ).onSuccess { // the web paywall was opened successfully }.onError { error -> // handle the error } } ``` --- # File: kmp-troubleshoot-paywall-builder --- --- title: "Kotlin Multiplatform SDK でのペイウォールビルダーのトラブルシューティング" description: "Kotlin Multiplatform SDK でのペイウォールビルダーのトラブルシューティング" --- このガイドでは、Kotlin Multiplatform SDK で Adapty ペイウォールビルダーを使用して作成したペイウォールに関する一般的な問題の解決方法を説明します。 ## ペイウォール設定の取得に失敗する \{#getting-a-paywall-configuration-fails\} **問題**: `createPaywallView` メソッドがペイウォールビューの作成に失敗するか、ペイウォールにビュー設定がない。 **原因**: ペイウォールビルダーでデバイス表示が有効になっていない。 **解決策**: ペイウォールビルダーで **Show on device** トグルを有効にしてください。また、`AdaptyPaywall` オブジェクトの `hasViewConfiguration` プロパティを使用して、ペイウォールにビュー設定があるかどうかを確認することもできます。 <img src="/assets/shared/img/show-on-device.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## ペイウォールのビュー数が多すぎる \{#the-paywall-view-number-is-too-big\} **問題**: ペイウォールのビュー数が予想の2倍になっている。 **原因**: コード内で `logShowPaywall` を呼び出している可能性があります。ペイウォールビルダーを使用している場合、この呼び出しによってビュー数が重複します。ペイウォールビルダーで作成したペイウォールでは、アナリティクスが自動的に記録されるため、このメソッドを使用する必要はありません。 **解決策**: ペイウォールビルダーを使用している場合は、コード内で `logShowPaywall` を呼び出していないことを確認してください。 --- # File: kmp-implement-paywalls-manually --- --- title: "Implement paywalls manually in Kotlin Multiplatform SDK" description: "Learn how to implement paywalls manually in your Kotlin Multiplatform app with Adapty SDK." --- ## Accept purchases If you are working with paywalls you've implemented yourself, you can delegate handling purchases to Adapty, using the `makePurchase` method. This way, we will handle all the user scenarios, and you will only need to handle the purchase results. :::important `makePurchase` works with products created in the Adapty dashboard. Make sure you configure products and ways to retrieve them in the dashboard by following the [quickstart guide](quickstart). ::: <CustomDocCardList ids={['kmp-quickstart-manual', 'fetch-paywalls-and-products-kmp', 'present-remote-config-paywalls-kmp', 'kmp-making-purchases', 'kmp-restore-purchase', 'kmp-troubleshoot-purchases']} /> ## Observer mode If you want to implement your own purchase handling logic from scratch, but still want to benefit from the advanced analytics in Adapty, you can use the observer mode. :::important Consider the observer mode limitations [here](observer-vs-full-mode). ::: <CustomDocCardList ids={['implement-observer-mode-kmp', 'report-transactions-observer-mode-kmp', 'kmp-troubleshoot-purchases']} /> --- # File: kmp-quickstart-manual --- --- title: "Kotlin Multiplatform SDKのカスタムペイウォールで購入を有効にする" description: "Adapty SDKをKotlin Multiplatformのカスタムペイウォールに統合して、アプリ内課金を有効にします。" --- このガイドでは、カスタムペイウォールにAdaptyを統合する方法を説明します。ペイウォールの実装を完全にコントロールしながら、Adapty SDKがプロダクトの取得、新規購入の処理、過去の購入の復元を行います。 :::important **このガイドは、カスタムペイウォールを実装する開発者向けです。** 最も簡単に購入を有効にする方法を使いたい場合は、[Adapty ペイウォールビルダー](kmp-quickstart-paywalls)をご利用ください。ペイウォールビルダーでは、ノーコードのビジュアルエディターでペイウォールを作成でき、Adaptyがすべての購入ロジックを自動で処理します。アプリを再公開せずに異なるデザインをテストすることも可能です。 ::: ## 始める前に \{#before-you-start\} ### プロダクトのセットアップ \{#set-up-products\} アプリ内課金を有効にするには、3つの重要な概念を理解する必要があります。 - [**プロダクト**](product) – ユーザーが購入できるもの(サブスクリプション、消耗型アイテム、永続アクセスなど) - [**ペイウォール**](paywalls) – 提供するプロダクトを定義する設定。Adaptyでは、ペイウォールがプロダクトを取得する唯一の手段です。この設計により、アプリのコードに触れることなく、プロダクト・価格・オファーを変更できます。 - [**プレースメント**](placements) – アプリ内でペイウォールを表示する場所とタイミング(例:`main`、`onboarding`、`settings`)。ダッシュボードでプレースメントにペイウォールを設定し、コード上でプレースメントIDを指定してリクエストします。これにより、A/Bテストの実施や、ユーザーごとに異なるペイウォールを表示することが簡単になります。 カスタムペイウォールを使う場合でも、これらの概念を理解しておくことが重要です。基本的には、アプリで販売するプロダクトを管理するための仕組みです。 カスタムペイウォールを実装するには、**ペイウォール**を作成して**プレースメント**に追加する必要があります。この設定により、プロダクトを取得できるようになります。ダッシュボードで何をすべきかを理解するには、[こちら](quickstart)のクイックスタートガイドに従ってください。 ### ユーザーの管理 \{#manage-users\} バックエンド認証の有無にかかわらず利用できます。 ただし、Adapty SDKは匿名ユーザーと識別済みユーザーを異なる方法で処理します。詳細を理解し、ユーザーを正しく扱うには、[識別クイックスタートガイド](kmp-quickstart-identify)をお読みください。 ## ステップ1. プロダクトを取得する \{#step-1-get-products\} カスタムペイウォール用のプロダクトを取得するには、次の手順を実行します。 1. `getPaywall`メソッドに[プレースメント](placements)IDを渡して`paywall`オブジェクトを取得する。 2. `getPaywallProducts`メソッドを使って、このペイウォールのプロダクト配列を取得する。 ```kotlin showLineNumbers fun loadPaywall() { Adapty.getPaywall(placementId = "YOUR_PLACEMENT_ID") .onSuccess { paywall -> Adapty.getPaywallProducts(paywall = paywall) .onSuccess { products -> // Use products to build your custom paywall UI } .onError { error -> // Handle the error } } .onError { error -> // Handle the error } } ``` ## ステップ2. 購入を受け付ける \{#step-2-accept-purchases\} ユーザーがカスタムペイウォール内でプロダクトをタップしたら、選択したプロダクトを引数に`makePurchase`メソッドを呼び出します。これにより購入フローが処理され、更新されたプロファイルが返されます。 ```kotlin showLineNumbers fun purchaseProduct(product: AdaptyPaywallProduct) { Adapty.makePurchase(product = product) .onSuccess { purchaseResult -> when (purchaseResult) { is AdaptyPurchaseResult.Success -> { val profile = purchaseResult.profile // Purchase successful, profile updated } is AdaptyPurchaseResult.UserCanceled -> { // User canceled the purchase } is AdaptyPurchaseResult.Pending -> { // Purchase is pending (e.g., user will pay offline with cash) } } } .onError { error -> // Handle the error } } ``` ## ステップ3. 購入を復元する \{#step-3-restore-purchases\} アプリストアは、サブスクリプションを提供するすべてのアプリに対して、ユーザーが購入を復元できる手段を提供することを求めています。 ユーザーが復元ボタンをタップしたら`restorePurchases`メソッドを呼び出します。これにより購入履歴がAdaptyと同期され、更新されたプロファイルが返されます。 ```kotlin showLineNumbers fun restorePurchases() { Adapty.restorePurchases() .onSuccess { profile -> // Restore successful, profile updated } .onError { error -> // Handle the error } } ``` ## 次のステップ \{#next-steps\} --- no_index: true --- import Callout from '../../../components/Callout.astro'; <Callout type="tip"> ご質問やお困りのことがあれば、[サポートフォーラム](https://adapty.featurebase.app/)をご覧ください。よくある質問への回答を見つけたり、ご自身の質問を投稿することができます。チームとコミュニティがサポートいたします! </Callout> ペイウォールをアプリに表示する準備が整いました。[App Storeサンドボックス](test-purchases-in-sandbox)または[Google Play Store](testing-on-android)でテスト購入を完了できることを確認してください。本番環境に近い実装例については、サンプルアプリの[AppViewModel.kt](https://github.com/adaptyteam/AdaptySDK-KMP/blob/main/example/composeMultiplatformApp/composeApp/src/commonMain/kotlin/com/adapty/exampleapp/AppViewModel.kt)を参照してください。適切なエラーハンドリングと状態管理を含む購入処理の実装例が確認できます。 次に、[ユーザーが購入を完了しているかどうかを確認](kmp-check-subscription-status)し、ペイウォールを表示するか有料機能へのアクセスを許可するかを判断します。 --- # File: fetch-paywalls-and-products-kmp --- --- title: "Kotlin Multiplatform SDKでリモートコンフィグペイウォールのペイウォールとプロダクトを取得する" description: "Adapty Kotlin Multiplatform SDKでペイウォールとプロダクトを取得し、ユーザーの収益化を強化します。" --- リモートコンフィグやカスタムペイウォールを表示する前に、それらの情報を取得する必要があります。このトピックはリモートコンフィグおよびカスタムペイウォールに関するものです。ペイウォールビルダーでカスタマイズされたペイウォールの取得方法については、[ペイウォールビルダーのペイウォールとその設定を取得する](kmp-get-pb-paywalls)を参照してください。 :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: <details> <summary>モバイルアプリでペイウォールとプロダクトの取得を始める前に(クリックして展開)</summary> 1. Adapty ダッシュボードで[プロダクトを作成する](create-product)。 2. Adapty ダッシュボードで[ペイウォールを作成し、プロダクトをペイウォールに追加する](create-paywall)。 3. Adapty ダッシュボードで[プレースメントを作成し、ペイウォールをプレースメントに追加する](create-placement)。 4. モバイルアプリに[Adapty SDKをインストールする](sdk-installation-kotlin-multiplatform)。 </details> ## ペイウォール情報を取得する \{#fetch-paywall-information\} Adaptyでは、[プロダクト](product)はApp StoreとGoogle Playの両方のプロダクトを組み合わせたものです。これらのクロスプラットフォームプロダクトはペイウォールに統合されており、特定のモバイルアプリのプレースメントで表示できます。 プロダクトを表示するには、`getPaywall`メソッドを使用していずれかの[プレースメント](placements)から[ペイウォール](paywalls)を取得する必要があります。 :::important **プロダクトIDをハードコードしないでください。** ハードコードすべき唯一のIDはプレースメントIDです。ペイウォールはリモートで設定されるため、プロダクトの数や利用可能なオファーはいつでも変更される可能性があります。アプリはこれらの変更を動的に処理する必要があります。今日2つのプロダクトが返され、明日3つになった場合でも、コードを変更せずにすべてを表示できるようにしてください。 ::: ```kotlin showLineNumbers Adapty.getPaywall( placementId = "YOUR_PLACEMENT_ID", locale = "en", fetchPolicy = AdaptyPaywallFetchPolicy.Default, loadTimeout = 5.seconds ).onSuccess { paywall -> // the requested paywall }.onError { error -> // handle the error } ``` | パラメータ | 必須/任意 | 説明 | |---------|--------|-----------| | **placementId** | 必須 | [プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** | <p>任意</p><p>デフォルト: `en`</p> | <p>[ペイウォールのローカライズ](add-remote-config-locale)の識別子。このパラメータはマイナス(**-**)文字で区切られた1つ以上のサブタグで構成される言語コードである必要があります。最初のサブタグは言語、2番目は地域を表します。</p><p></p><p>例: `en` は英語、`pt-br` はブラジルポルトガル語を表します。</p> | | **fetchPolicy** | デフォルト: `AdaptyPaywallFetchPolicy.Default` | <p>デフォルトでは、SDKはサーバーからデータを読み込もうとし、失敗した場合はキャッシュされたデータを返します。ユーザーが常に最新のデータを取得できるため、この方法を推奨します。</p><p></p><p>ただし、ユーザーが不安定なインターネット環境にいると思われる場合は、`AdaptyPaywallFetchPolicy.ReturnCacheDataElseLoad`を使用してキャッシュが存在する場合にキャッシュデータを返すことを検討してください。このシナリオでは、ユーザーが最新のデータを取得できない場合がありますが、インターネット接続が不安定でも読み込み時間が短縮されます。キャッシュは定期的に更新されるため、ネットワークリクエストを避けるためにセッション中に使用しても安全です。</p><p></p><p>キャッシュはアプリの再起動後も保持され、アプリの再インストールまたは手動のクリーンアップ時にのみクリアされます。</p><p></p><p>Adapty SDKはペイウォールを2つのレイヤーで保存します: 上記の定期的に更新されるキャッシュと[フォールバックペイウォール](kmp-use-fallback-paywalls)。また、ペイウォールをより速く取得するためにCDNを使用し、CDNに到達できない場合のスタンドアロンフォールバックサーバーも使用します。このシステムは、インターネット接続が不安定な場合でも、常に最新バージョンのペイウォールを確実に取得できるように設計されています。</p> | | **loadTimeout** | デフォルト: 5秒 | <p>このメソッドのタイムアウト上限を設定します。タイムアウトに達した場合、キャッシュされたデータまたはローカルフォールバックが返されます。</p><p></p><p>まれに、この操作が内部で複数のリクエストで構成されているため、`loadTimeout`で指定した時間より少し遅くタイムアウトする場合があります。</p> | プロダクトIDをハードコードしないでください!ペイウォールはリモートで設定されるため、利用可能なプロダクト、プロダクトの数、特別オファー(無料トライアルなど)は随時変更される可能性があります。コードがこれらのシナリオに対応できるようにしてください。 例えば、最初に2つのプロダクトを取得した場合、アプリはその2つを表示すべきです。後で3つのプロダクトを取得した場合、コードを変更せずに3つすべてを表示できるようにしてください。ハードコードすべき唯一のものはプレースメントIDです。 レスポンスパラメータ: | パラメータ | 説明 | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- | | Paywall | プロダクトIDのリスト、ペイウォール識別子、リモートコンフィグ、その他いくつかのプロパティを含む[`AdaptyPaywall`](https://kmp.adapty.io///adapty/com.adapty.kmp.models/-adapty-paywall/)オブジェクト。 | ## プロダクトを取得する \{#fetch-products\} ペイウォールを取得したら、それに対応するプロダクト配列を取得できます: ```kotlin showLineNumbers Adapty.getPaywallProducts(paywall).onSuccess { products -> // the requested products }.onError { error -> // handle the error } ``` レスポンスパラメータ: | パラメータ | 説明 | | :-------- |:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Products | プロダクト識別子、プロダクト名、価格、通貨、サブスクリプション期間、その他いくつかのプロパティを含む[`AdaptyPaywallProduct`](https://kmp.adapty.io///adapty/com.adapty.kmp.models/-adapty-paywall-product/)オブジェクトのリスト。 | 独自のペイウォールデザインを実装する場合、[`AdaptyPaywallProduct`](https://kmp.adapty.io///adapty/com.adapty.kmp.models/-adapty-paywall-product/)オブジェクトのプロパティにアクセスする必要があるでしょう。以下は最もよく使用されるプロパティですが、利用可能なすべてのプロパティの詳細はリンク先のドキュメントを参照してください。 | プロパティ | 説明 | |-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Title** | プロダクトのタイトルを表示するには、`product.localizedTitle`を使用します。ローカライズはデバイス自体のロケールではなく、ユーザーが選択したストアの国に基づいています。 | | **Price** | ローカライズされた価格を表示するには、`product.price.localizedString`を使用します。このローカライズはデバイスのロケール情報に基づいています。`product.price.amount`を使用して価格を数値として取得することもできます。値はローカル通貨で提供されます。関連する通貨記号を取得するには、`product.price.currencySymbol`を使用します。 | | **Subscription Period** | 期間(週、月、年など)を表示するには、`product.subscriptionDetails?.localizedSubscriptionPeriod`を使用します。このローカライズはデバイスのロケールに基づいています。プログラムでサブスクリプション期間を取得するには、`product.subscriptionDetails?.subscriptionPeriod`を使用します。そこから`unit`列挙型にアクセスして長さ(DAY、WEEK、MONTH、YEAR、またはUNKNOWN)を取得できます。`numberOfUnits`の値は期間単位の数を示します。例えば、四半期サブスクリプションの場合、unitプロパティに`MONTH`、numberOfUnitsプロパティに`3`が表示されます。 | | **Introductory Offer** | サブスクリプションに初回オファーが含まれているかどうかを示すバッジやインジケーターを表示するには、`product.subscriptionDetails?.introductoryOfferPhases`プロパティを確認してください。これは最大2つの割引フェーズ(無料トライアルフェーズと初回価格フェーズ)を含むことができるリストです。各フェーズオブジェクトには以下の便利なプロパティがあります:<br/>• `paymentMode`: `FREE_TRIAL`、`PAY_AS_YOU_GO`、`PAY_UPFRONT`、`UNKNOWN`の値を持つ列挙型。無料トライアルは`FREE_TRIAL`タイプになります。<br/>• `price`: 数値としての割引価格。無料トライアルの場合は`0`を確認してください。<br/>• `localizedNumberOfPeriods`: デバイスのロケールを使用してローカライズされた、オファーの長さを説明する文字列。例えば、3日間のトライアルオファーの場合、このフィールドに`3 days`と表示されます。<br/>• `subscriptionPeriod`: オファー期間の個別の詳細を取得するには、このプロパティを使用します。オファーに対しても前のセクションと同じ方法で機能します。<br/>• `localizedSubscriptionPeriod`: ユーザーのロケール向けにフォーマットされた割引のサブスクリプション期間。 | ## デフォルトオーディエンスのペイウォールでペイウォール取得を高速化する \{#speed-up-paywall-fetching-with-default-audience-paywall\} 通常、ペイウォールはほぼ即座に取得されるため、このプロセスを高速化することを心配する必要はありません。ただし、多数のオーディエンスとペイウォールがあり、ユーザーのインターネット接続が弱い場合、ペイウォールの取得に想定以上の時間がかかる可能性があります。そのような状況では、ペイウォールをまったく表示しないよりも、スムーズなユーザーエクスペリエンスを確保するためにデフォルトのペイウォールを表示したい場合があります。 これに対処するために、指定されたプレースメントの**All Users**オーディエンス向けペイウォールを取得する`getPaywallForDefaultAudience`メソッドを使用できます。ただし、推奨されるアプローチは上記の[ペイウォール情報を取得する](fetch-paywalls-and-products-kmp#fetch-paywall-information)セクションで詳しく説明されている`getPaywall`メソッドを使用することである点を理解することが重要です。 :::warning `getPaywall`を推奨する理由 `getPaywallForDefaultAudience`メソッドにはいくつかの重大な欠点があります: - **潜在的な後方互換性の問題**: 異なるアプリバージョン(現在および将来)に対して異なるペイウォールを表示する必要がある場合、課題が生じる可能性があります。現在の(レガシー)バージョンをサポートするペイウォールを設計するか、現在の(レガシー)バージョンのユーザーがレンダリングされないペイウォールで問題が発生する可能性を受け入れるかのいずれかになります。 - **ターゲティングの喪失**: すべてのユーザーが**All Users**オーディエンス向けに設計された同じペイウォールを見ることになるため、パーソナライズされたターゲティング(国、マーケティングアトリビューション、独自のカスタム属性に基づくものを含む)が失われます。 これらの欠点を許容してペイウォール取得の高速化のメリットを得たい場合は、以下のように`getPaywallForDefaultAudience`メソッドを使用してください。そうでなければ、[上記](fetch-paywalls-and-products-kmp#fetch-paywall-information)で説明した`getPaywall`を使用してください。 ::: ```kotlin showLineNumbers Adapty.getPaywallForDefaultAudience( placementId = "YOUR_PLACEMENT_ID", locale = "en", fetchPolicy = AdaptyPaywallFetchPolicy.Default ).onSuccess { paywall -> // the requested paywall }.onError { error -> // handle the error } ``` | パラメータ | 必須/任意 | 説明 | |---------|--------|-----------| | **placementId** | 必須 | [プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** | <p>任意</p><p>デフォルト: `en`</p> | <p>[ペイウォールのローカライズ](add-remote-config-locale)の識別子。このパラメータはマイナス(**-**)文字で区切られた1つ以上のサブタグで構成される言語コードである必要があります。最初のサブタグは言語、2番目は地域を表します。</p><p></p><p>例: `en` は英語、`pt-br` はブラジルポルトガル語を表します。</p><p></p> | | **fetchPolicy** | デフォルト: `AdaptyPaywallFetchPolicy.Default` | <p>デフォルトでは、SDKはサーバーからデータを読み込もうとし、失敗した場合はキャッシュされたデータを返します。ユーザーが常に最新のデータを取得できるため、この方法を推奨します。</p><p></p><p>ただし、ユーザーが不安定なインターネット環境にいると思われる場合は、`AdaptyPaywallFetchPolicy.ReturnCacheDataElseLoad`を使用してキャッシュが存在する場合にキャッシュデータを返すことを検討してください。このシナリオでは、ユーザーが最新のデータを取得できない場合がありますが、インターネット接続が不安定でも読み込み時間が短縮されます。キャッシュは定期的に更新されるため、ネットワークリクエストを避けるためにセッション中に使用しても安全です。</p><p></p><p>キャッシュはアプリの再起動後も保持され、アプリの再インストールまたは手動のクリーンアップ時にのみクリアされます。</p> | --- # File: present-remote-config-paywalls-kmp --- --- title: "Kotlin Multiplatform SDKでリモートコンフィグを使ったペイウォールをレンダリングする" description: "Adapty Kotlin Multiplatform SDKでリモートコンフィグペイウォールを表示し、ユーザー体験をパーソナライズする方法をご紹介します。" --- リモートコンフィグを使ってペイウォールをカスタマイズした場合は、ユーザーに表示するためのレンダリング処理をモバイルアプリのコードに実装する必要があります。リモートコンフィグはニーズに合わせた柔軟性を提供するため、何を含めるか、またペイウォールのビューをどのように表示するかはすべてあなたの判断に委ねられています。リモートコンフィグを取得するメソッドを提供しており、リモートコンフィグで設定したカスタムペイウォールを自由に表示できます。 ## ペイウォールのリモートコンフィグを取得して表示する \{#get-paywall-remote-config-and-present-it\} ペイウォールのリモートコンフィグを取得するには、`remoteConfig` プロパティにアクセスして必要な値を取り出します。 ```kotlin showLineNumbers Adapty.getPaywall( placementId = "YOUR_PLACEMENT_ID", locale = "en", fetchPolicy = AdaptyPaywallFetchPolicy.Default, loadTimeout = 5.seconds ).onSuccess { paywall -> val headerText = paywall.remoteConfig?.dataMap?.get("header_text") as? String // use the remote config values }.onError { error -> // handle the error } ``` 必要な値をすべて取得したら、それらをレンダリングして視覚的に魅力的なページに組み立てましょう。さまざまなスマートフォンの画面サイズや向きに対応したデザインにして、異なるデバイスでもシームレスで使いやすい体験を提供してください。 :::warning [ペイウォール表示イベントの記録](present-remote-config-paywalls-kmp#track-paywall-view-events)を必ず行ってください。これにより、Adapty アナリティクスがファネルや A/B テストの情報を収集できるようになります。 ::: ペイウォールの表示が完了したら、購入フローの設定に進みます。ユーザーが購入する際は、ペイウォールのプロダクトを使って `.makePurchase()` を呼び出すだけです。`.makePurchase()` メソッドの詳細については、[購入処理](kmp-making-purchases)をご覧ください。 [フォールバックペイウォールというバックアップペイウォールの作成](kmp-use-fallback-paywalls)をお勧めします。このバックアップは、インターネット接続がない場合やキャッシュが利用できない場合にユーザーに表示され、そのような状況でもスムーズな体験を確保します。 ## ペイウォール表示イベントを記録する \{#track-paywall-view-events\} Adapty はペイウォールのパフォーマンス計測をサポートします。購入データは自動的に収集されますが、ペイウォールの表示ログはユーザーがペイウォールを見たタイミングを把握しているのはあなただけなので、手動での記録が必要です。 ペイウォール表示イベントをログに記録するには、`.logShowPaywall(paywall)` を呼び出すだけです。すると、ファネルや A/B テストのペイウォール指標に反映されます。 :::important [ペイウォールビルダー](adapty-paywall-builder)で作成したペイウォールを表示する場合は、`.logShowPaywall(paywall)` の呼び出しは不要です。 ::: ```kotlin showLineNumbers Adapty.logShowPaywall(paywall = paywall) .onSuccess { // paywall view logged successfully } .onError { error -> // handle the error } ``` リクエストパラメータ: | パラメータ | 必須/任意 | 説明 | | :---------- | :------- |:-------------------------------------------------------------------------------------------------------| | **paywall** | 必須 | [`AdaptyPaywall`](https://kmp.adapty.io//////adapty/com.adapty.kmp.models/-adapty-paywall/) オブジェクト。 | --- # File: kmp-making-purchases --- --- title: "Kotlin Multiplatform SDKでモバイルアプリ内で購入を行う" description: "Adaptyを使用したアプリ内課金とサブスクリプションの処理に関するガイド。" --- モバイルアプリ内にペイウォールを表示することは、プレミアムコンテンツやサービスへのアクセスをユーザーに提供するための重要なステップです。ただし、[ペイウォールビルダー](adapty-paywall-builder)を使用してペイウォールをカスタマイズしている場合に限り、ペイウォールを表示するだけで購入をサポートできます。 ペイウォールビルダーを使用しない場合は、購入を完了してコンテンツをアンロックするために、`.makePurchase()` という別のメソッドを使用する必要があります。このメソッドは、ユーザーがペイウォールを利用して購入処理を進めるための入り口となります。 ペイウォールに、ユーザーが購入しようとしているプロダクトに対する有効なプロモーションオファーが設定されている場合、Adaptyは購入時に自動的にそのオファーを適用します。 :::warning 初回オファーが自動的に適用されるのは、ペイウォールビルダーで設定したペイウォールを使用している場合に限ります。 それ以外の場合は、[iOS での初回オファーの適用資格を確認する](fetch-paywalls-and-products#check-intro-offer-eligibility-on-ios)必要があります。この手順を省略すると、リリース時にアプリが審査で却下される可能性があります。また、初回オファーの対象ユーザーに通常価格が請求されるリスクもあります。 ::: [初期設定](quickstart)をすべての手順を飛ばさずに完了していることを確認してください。これが完了していないと、購入を検証できません。 ## 購入を行う \{#make-purchase\} :::note **[ペイウォールビルダー](adapty-paywall-builder)を使用していますか?** 購入は自動的に処理されるため、この手順はスキップできます。 **ステップごとのガイダンスをお探しですか?** エンドツーエンドの実装手順については、[クイックスタートガイド](kmp-implement-paywalls-manually)をご覧ください。 ::: ```kotlin showLineNumbers Adapty.makePurchase(product = product).onSuccess { purchaseResult -> when (purchaseResult) { is AdaptyPurchaseResult.Success -> { val profile = purchaseResult.profile if (profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive == true) { // Grant access to the paid features } } is AdaptyPurchaseResult.UserCanceled -> { // Handle the case where the user canceled the purchase } is AdaptyPurchaseResult.Pending -> { // Handle deferred purchases (e.g., the user will pay offline with cash) } } }.onError { error -> // Handle the error } ``` リクエストパラメータ: | パラメータ | 必須 | 説明 | | :---------- | :------- |:----------------------------------------------------------------------------------------------------------------------------------------------| | **Product** | 必須 | ペイウォールから取得した [`AdaptyPaywallProduct`](https://kmp.adapty.io///adapty/com.adapty.kmp.models/-adapty-paywall-product/) オブジェクト。 | レスポンスパラメータ: | パラメータ | 説明 | |---------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Profile** | <p>リクエストが成功した場合、レスポンスにはこのオブジェクトが含まれます。[AdaptyProfile](https://kmp.adapty.io///adapty/com.adapty.kmp.models/-adapty-profile/) オブジェクトは、ユーザーのアクセスレベル、サブスクリプション、アプリ内の買い切り購入に関する包括的な情報を提供します。</p><p>アクセスレベルのステータスを確認して、ユーザーが必要なアクセス権を持っているかどうかを判断してください。</p> | :::warning **注意:** Apple の StoreKit バージョンが v2.0 未満で、Adapty SDK バージョンが v2.9.0 未満の場合は、代わりに [Apple App Store 共有シークレット](app-store-connection-configuration#step-5-enter-app-store-shared-secret)を提供する必要があります。この方法は現在 Apple により非推奨となっています。 ::: ## 購入時にサブスクリプションを変更する \{#change-subscription-when-making-a-purchase\} ユーザーが現在のサブスクリプションを更新する代わりに新しいサブスクリプションを選択した場合、その動作はアプリストアによって異なります。Google Play の場合、サブスクリプションは自動的に更新されません。以下の説明に従って、モバイルアプリのコードで切り替えを管理する必要があります。 Android でサブスクリプションを別のものに切り替えるには、追加パラメータを指定して `.makePurchase()` メソッドを呼び出してください: ```kotlin showLineNumbers val subscriptionUpdateParams = AdaptyAndroidSubscriptionUpdateParameters( oldSubVendorProductId = "old_subscription_product_id", replacementMode = AdaptyAndroidSubscriptionUpdateReplacementMode.CHARGE_FULL_PRICE ) val purchaseParams = AdaptyPurchaseParameters.Builder() .setSubscriptionUpdateParams(subscriptionUpdateParams) .build() Adapty.makePurchase( product = product, parameters = purchaseParams ).onSuccess { purchaseResult -> when (purchaseResult) { is AdaptyPurchaseResult.Success -> { val profile = purchaseResult.profile // successful cross-grade } is AdaptyPurchaseResult.UserCanceled -> { // user canceled the purchase flow } is AdaptyPurchaseResult.Pending -> { // the purchase has not been finished yet, e.g. user will pay offline by cash } } }.onError { error -> // Handle the error } ``` 追加リクエストパラメータ: | パラメータ | 必須 | 説明 | |:---------------|:---------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **parameters** | 任意 | [`AdaptyPurchaseParameters`](https://kmp.adapty.io/adapty/com.adapty.kmp.models/-adapty-purchase-parameters/) を通じて渡される [`AdaptyAndroidSubscriptionUpdateParameters`](https://kmp.adapty.io/////adapty/com.adapty.kmp.models/-adapty-android-subscription-update-parameters/) オブジェクト。 | サブスクリプションと切り替えモードについては、Google Developer ドキュメントで詳しく確認できます: - [切り替えモードについて](https://developer.android.com/google/play/billing/subscriptions#replacement-modes) - [切り替えモードに関する Google の推奨事項](https://developer.android.com/google/play/billing/subscriptions#replacement-recommendations) - 切り替えモード [`CHARGE_PRORATED_PRICE`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode#CHARGE_PRORATED_PRICE())。注意:このメソッドはサブスクリプションのアップグレードにのみ対応しています。ダウングレードはサポートされていません。 - 切り替えモード [`DEFERRED`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode#DEFERRED())。注意:実際のサブスクリプション変更は、現在のサブスクリプションの請求期間が終了した時点でのみ適用されます。 ## iOS でオファーコードを利用する \{#redeem-offer-codes-in-ios\} --- no_index: true --- import Callout from '../../../components/Callout.astro'; <Details> <summary>オファーコードについて</summary> オファーコードを使うと、特定のユーザーに割引や無料トライアルを提供できます。自動的に適用される通常のオファーとは異なり、オファーコードはメールキャンペーン、SNS、印刷物など、アプリの外で配布します。ユーザーはApp Storeでコードを入力するか、引き換えURLを使うか、アプリ内ダイアログから利用できます。 オファーコードを設定するには、App Store Connectでサブスクリプションを開き、**Offer Codes** セクションに移動してください。オファーコードは[3種類](https://developer.apple.com/help/app-store-connect/manage-subscriptions/set-up-subscription-offer-codes)作成できます。 - **Free** — 指定した期間はサブスクリプションが無料になり、次の更新から通常価格になります。 - **Pay as you go** — 指定した期間、各請求サイクルに割引価格が適用され、その後は通常価格で更新されます。 - **Pay up front** — オファー期間全体に対して一括で割引価格を支払い、その後は通常価格で更新されます。 オファーコードをAdaptyに追加する必要はありません。Appleはオファー期間中のすべてのトランザクションにオファーコードカテゴリのタグを付与します。これには最初の引き換えとその後の割引更新がすべて含まれます。Adaptyはこのタグを検出し、各トランザクションをオファーカテゴリ `offer_code` として記録します。オファー期間が終了してサブスクリプションが通常価格で更新されると、タグは付与されなくなります。[Adapty ダッシュボード](controls-filters-grouping-compare-proceeds)のアナリティクスで **Offer Code** オファータイプによるフィルタリングが可能です。 #### 収益の差異が生じた場合のトラブルシューティング \{#revenue-discrepancy-troubleshooting\} オファーコードのトランザクションが、割引価格ではなく通常価格でAdaptyに記録されている場合は、App Store Connectで以下を確認してください。 - オファーコードに、ユーザーが引き換え可能なすべての地域に対して正しい価格が設定されているか。 - ユーザーの特定の国や地域に対してオファー価格が設定されているか。Appleはトランザクションに地域価格を含めて送信します。その地域のオファー価格が設定されていない場合、Appleは通常価格を送信することがあります。 [Adapty ダッシュボード](controls-filters-grouping-compare-proceeds)で、**Offer Code** オファータイプと **Offer Discount Type** フィルターを使ってオファーコードのトランザクションをフィルタリング・確認できます。 #### レガシープロモコード(非推奨) \{#legacy-promo-codes-deprecated\} <Callout type="warning"> Appleは2026年3月にアプリ内課金向けのプロモコードを廃止しました。オファーコードはより多くの機能(適格性の設定、有効期限、四半期あたり最大100万コード)を備えた後継機能です。アプリ内課金にプロモコードを使用していた場合は、App Store Connectでオファーコードに移行してください。 </Callout> レガシープロモコード(アプリのバージョンごとに最大100件)は、サブスクリプションへの無料アクセスを付与していました。オファーコードとは異なり、Appleはプロモコードのトランザクションに割引情報を含めず、レシートには通常価格が記載されていました。そのため、Adaptyはこれらのトランザクションを通常価格で記録し、Adaptyアナリティクスとレポートの間に収益の差異が生じていました。 本来は無料であるべきトランザクションが通常価格で記録されている履歴がある場合、それはレガシープロモコードによるものと考えられます。これらのコードは現在廃止されているため、正確な収益追跡のためにオファーコードに移行してください。 </Details> アプリ内でコード引き換えシートを表示するには: ```kotlin showLineNumbers Adapty.presentCodeRedemptionSheet() .onSuccess { // code redemption sheet presented successfully } .onError { error -> // handle the error } ``` :::danger 確認された事例によると、一部のアプリではオファーコード引き換えシートが正常に動作しないことがあります。ユーザーを直接 App Store にリダイレクトすることをお勧めします。 そのためには、次の形式の URL を開く必要があります: `https://apps.apple.com/redeem?ctx=offercodes&id={apple_app_id}&code={code}` ::: ## プリペイドプランを管理する(Android) \{#manage-prepaid-plans-android\} アプリユーザーが[プリペイドプラン](https://developer.android.com/google/play/billing/subscriptions#prepaid-plans)(例:数か月分の非更新型サブスクリプションを購入するなど)を利用できる場合、プリペイドプランの[保留中のトランザクション](https://developer.android.com/google/play/billing/subscriptions#pending)を有効にすることができます。 ```kotlin showLineNumbers Adapty.activate( AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withGoogleEnablePendingPrepaidPlans(true) .build() ).onSuccess { // successful activation }.onError { error -> // handle the error } ``` --- # File: kmp-restore-purchase --- --- title: "Kotlin Multiplatform SDKでのアプリ内購入の復元" description: "シームレスなユーザー体験を確保するためにAdaptyで購入を復元する方法を学びます。" --- 購入の復元は、サブスクリプションやアプリ内課金などの以前に購入したコンテンツへのアクセスを、再度料金を請求されることなく取り戻せる機能です。この機能は、アプリをアンインストール・再インストールしたユーザーや、新しいデバイスに切り替えたユーザーが、以前に購入したコンテンツに再度料金を支払わずにアクセスしたい場合に特に便利です。 :::note [ペイウォールビルダー](adapty-paywall-builder)で作成したペイウォールでは、追加のコードなしに購入が自動的に復元されます。その場合は、このステップをスキップできます。 ::: ペイウォールのカスタマイズに[ペイウォールビルダー](adapty-paywall-builder)を使用していない場合に購入を復元するには、`.restorePurchases()`メソッドを呼び出します: ```kotlin showLineNumbers Adapty.restorePurchases().onSuccess { profile -> if (profile.accessLevels["YOUR_ACCESS_LEVEL"]?.isActive == true) { // successful access restore } }.onError { error -> // handle the error } ``` レスポンスパラメーター: | パラメーター | 説明 | |---------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Profile** | <p>[`AdaptyProfile`](https://kmp.adapty.io//////adapty/com.adapty.kmp.models/-adapty-profile/)オブジェクトです。このモデルにはアクセスレベル、サブスクリプション、および非サブスクリプション購入に関する情報が含まれています。</p><p>ユーザーがアプリにアクセスできるかどうかを判断するには、**アクセスレベルのステータス**を確認してください。</p> | :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: --- # File: implement-observer-mode-kmp --- --- title: "Kotlin Multiplatform SDK でオブザーバーモードを実装する" description: "Kotlin Multiplatform SDK において、Adapty のオブザーバーモードを実装してユーザーのサブスクリプションイベントを追跡します。" --- すでに独自の購入インフラを持っており、Adapty への完全移行をまだ検討していない場合は、[オブザーバーモード](observer-vs-full-mode)を試してみてください。基本的な使い方では、オブザーバーモードは高度な分析機能とアトリビューション・アナリティクスシステムとのシームレスな連携を提供します。 このモードで問題なければ、以下の手順だけで利用できます: 1. Adapty SDK を設定する際に `observerMode` パラメータを `true` に設定してオブザーバーモードをオンにします。設定手順は [Kotlin Multiplatform](sdk-installation-kotlin-multiplatform) を参照してください。 2. 既存の購入インフラからのトランザクションを [Adapty に報告](report-transactions-observer-mode-kmp)します。 ## オブザーバーモードの設定 \{#observer-mode-setup\} 購入処理とサブスクリプションステータスの管理を自分で行い、サブスクリプションイベントの送信と分析に Adapty を使用する場合は、オブザーバーモードをオンにしてください。 :::important オブザーバーモードで動作している場合、Adapty SDK はトランザクションをクローズしません。そのため、トランザクションの処理は必ずご自身で行ってください。 ::: ```kotlin showLineNumbers val config = AdaptyConfig .Builder("PUBLIC_SDK_KEY") .withObserverMode(true) // default false .build() Adapty.activate(configuration = config) .onSuccess { Log.d("Adapty", "SDK initialised in observer mode") } .onError { error -> Log.e("Adapty", "Adapty init error: ${error.message}") } ``` パラメータ: | パラメータ | 説明 | | --------------------------- | ------------------------------------------------------------ | | observerMode | [オブザーバーモード](observer-vs-full-mode)を制御する真偽値です。デフォルト値は `false` です。 | ## オブザーバーモードで Adapty のペイウォールを使用する \{#using-adapty-paywalls-in-observer-mode\} Adapty のペイウォールや A/B テスト機能も併用したい場合は可能ですが、オブザーバーモードでは追加の設定が必要です。上記の手順に加えて、以下を行ってください: 1. [リモートコンフィグペイウォール](present-remote-config-paywalls-kmp)の場合と同様に、通常通りペイウォールを表示します。 3. 購入トランザクションに[ペイウォールを紐付け](report-transactions-observer-mode-kmp)ます。 --- # File: report-transactions-observer-mode-kmp --- --- title: "Kotlin Multiplatform SDKのObserverモードでトランザクションを報告する" description: "Kotlin Multiplatform SDKのAdapty ObserverモードでユーザーインサイトとRevenue追跡のための購入トランザクションを報告します。" --- Observerモードでは、Adapty SDKは既存の購入システムを通じて行われた購入を自動的に追跡することができません。アプリストアからのトランザクションを手動で報告する必要があります。アナリティクスのエラーを防ぐために、アプリをリリースする**前**にこの設定を完了することが重要です。 `reportTransaction`を使用して、各トランザクションをAdaptyに明示的に報告してください。 :::warning **トランザクションの報告を省略しないでください!** `reportTransaction`を呼び出さないと、Adaptyはトランザクションを認識できず、アナリティクスに表示されず、インテグレーションにも送信されません。 ::: Adaptyのペイウォールを使用している場合は、トランザクションを報告する際に`variationId`を含めてください。これにより、購入がトリガーしたペイウォールに関連付けられ、正確なペイウォールアナリティクスが確保されます。 ```kotlin showLineNumbers Adapty.reportTransaction( transactionId = "your_transaction_id", variationId = paywall.variationId ).onSuccess { profile -> // Transaction reported successfully // profile contains updated user data }.onError { error -> // handle the error } ``` パラメーター: | パラメーター | 必須/任意 | 説明 | | --------------- | --------- |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | transactionId | 必須 | アプリストアの購入から取得したトランザクションID。通常、ストアから返される購入トークンまたはトランザクション識別子です。 | | variationId | 任意 | バリアントの文字列識別子。[AdaptyPaywall](https://kmp.adapty.io//////adapty/com.adapty.kmp.models/-adapty-paywall/)オブジェクトの`variationId`プロパティを使用して取得できます。 | --- # File: kmp-troubleshoot-purchases --- --- title: "Kotlin Multiplatform SDKの購入に関するトラブルシューティング" description: "Kotlin Multiplatform SDKの購入に関するトラブルシューティング" --- このガイドでは、Kotlin Multiplatform SDKで手動購入を実装する際によく発生する問題の解決方法を説明します。 ## makePurchaseは正常に呼び出されるが、プロファイルが更新されない \{#makepurchase-is-called-successfully-but-the-profile-is-not-being-updated\} **問題**: `makePurchase`メソッドが正常に完了するにもかかわらず、ユーザーのプロファイルとサブスクリプションの状態がAdaptyに反映されない。 **原因**: 通常、これはGoogle Play Storeのセットアップが不完全か、設定に問題があることを示しています。 **解決策**: [Google Playのセットアップ手順](initial-android)がすべて完了しているか確認してください。 ## makePurchaseが2回呼び出される \{#makepurchase-is-invoked-twice\} **問題**: 同じ購入に対して`makePurchase`メソッドが複数回呼び出されている。 **原因**: UIの状態管理の問題や、ユーザーの素早い操作によって購入フローが複数回トリガーされる場合に発生します。 **解決策**: [Google Playのセットアップ手順](initial-android)がすべて完了しているか確認してください。 ## オブザーバーモードでのAdaptyError.cantMakePayments \{#adaptyerror-cantmakepayments-in-observer-mode\} **問題**: オブザーバーモードで`makePurchase`を使用すると`AdaptyError.cantMakePayments`が発生する。 **原因**: オブザーバーモードでは、Adaptyの`makePurchase`メソッドを使用せず、購入処理を自前で行う必要があります。 **解決策**: 購入に`makePurchase`を使用している場合は、オブザーバーモードを無効にしてください。`makePurchase`を使用するか、オブザーバーモードで自前の購入処理を行うか、どちらか一方を選択する必要があります。詳細は[オブザーバーモードの実装](implement-observer-mode-kmp)を参照してください。 ## Adaptyエラー: (code: 103, message: Play Market request failed on purchases updated: responseCode=3, debugMessage=Billing Unavailable, detail: null) \{#adapty-error-code-103-message-play-market-request-failed-on-purchases-updated-responsecode3-debugmessagebilling-unavailable-detail-null\} **問題**: Google Play Storeから課金不可のエラーが返される。 **原因**: このエラーはAdatyとは無関係です。デバイスで課金が利用できないことを示すGoogle Play Billing Libraryのエラーです。 **解決策**: このエラーはAdaptyとは無関係です。Play Storeのドキュメントで詳細を確認できます: [Handle BillingResult response codes](https://developer.android.com/google/play/billing/errors#billing_unavailable_error_code_3) | Play Billing | Android Developers。 ## makePurchasesCompletionHandlersが見つからない \{#not-found-makepurchasescompletionhandlers\} **問題**: `makePurchasesCompletionHandlers`が見つからないというエラーが発生する。 **原因**: 通常、これはサンドボックステストに関連する問題です。 **解決策**: 新しいサンドボックスユーザーを作成して再試行してください。これにより、サンドボックス環境での購入完了ハンドラーの問題が解決することが多いです。 --- # File: kmp-user --- --- title: "Users & access in Kotlin Multiplatform SDK" description: "Learn how to work with users and access levels in your Kotlin Multiplatform app with Adapty SDK." --- This page contains all guides for working with users and access levels in your Kotlin Multiplatform app. Choose the topic you need: - **[Identify users](kmp-identifying-users)** - Learn how to identify users in your app - **[Update user data](kmp-setting-user-attributes)** - Set user attributes and profile data - **[Listen for subscription status changes](kmp-listen-subscription-changes)** - Monitor subscription changes in real-time - **[Kids Mode](kids-mode-kmp)** - Implement Kids Mode for your app --- # File: kmp-identifying-users --- --- title: "Kotlin Multiplatform SDK でユーザーを識別する" description: "Adapty でユーザーを識別して、パーソナライズされたサブスクリプション体験を向上させましょう。" --- Adapty はすべてのユーザーに対して内部プロファイル ID を作成します。ただし、独自の認証システムを持っている場合は、独自の Customer User ID を設定する必要があります。[Profiles](profiles-crm) セクションで Customer User ID によってユーザーを検索したり、すべてのインテグレーションに送信される[サーバーサイド API](getting-started-with-server-side-api) で使用することができます。 ### 設定時に Customer User ID を設定する \{#setting-customer-user-id-on-configuration\} 設定時にユーザー ID がある場合は、`.activate()` メソッドの `customerUserId` パラメータとして渡すだけです: ```kotlin showLineNumbers Adapty.activate( AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withCustomerUserId("YOUR_USER_ID") .build() ).onSuccess { // successful activation }.onError { error -> // handle the error } } ``` :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: ### 設定後に Customer User ID を設定する \{#setting-customer-user-id-after-configuration\} SDK の設定時にユーザー ID がない場合は、後から `.identify()` メソッドを使っていつでも設定できます。このメソッドが最もよく使われるのは、登録後やログイン後に匿名ユーザーから認証済みユーザーへ切り替わるタイミングです。 ```kotlin showLineNumbers Adapty.identify("YOUR_USER_ID").onSuccess { // successful identify }.onError { error -> // handle the error } ``` リクエストパラメータ: - **Customer User ID**(必須): 文字列のユーザー識別子。 :::warning 重要なユーザーデータの再送信 ユーザーが再度アカウントにログインする場合など、Adapty のサーバーにすでにそのユーザーの情報が存在していることがあります。このような場合、Adapty SDK は自動的に新しいユーザーとして動作を切り替えます。カスタム属性やサードパーティネットワークからのアトリビューションなど、匿名ユーザーに対してデータを渡していた場合は、識別されたユーザーに対してそのデータを再送信する必要があります。 また、新しいユーザーのデータが異なる可能性があるため、ユーザーを識別した後はすべてのペイウォールとプロダクトを再取得する必要があることにも注意してください。 ::: ### ログアウトとログイン \{#logging-out-and-logging-in\} `.logout()` メソッドを呼び出すことで、いつでもユーザーをログアウトさせることができます: ```kotlin showLineNumbers Adapty.logout().onSuccess { // successful logout }.onError { error -> // handle the error } ``` その後、`.identify()` メソッドを使ってユーザーをログインさせることができます。 ## `appAccountToken` を割り当てる(iOS) \{#assign-appaccounttoken-ios\} [`iosAppAccountToken`](https://developer.apple.com/documentation/storekit/product/purchaseoption/appaccounttoken(_:)) は、App Store のトランザクションを内部ユーザー ID に紐付けるための **UUID** です。 StoreKit はすべてのトランザクションにこのトークンを関連付けるため、バックエンドで App Store のデータをユーザーと照合することができます。 ユーザーごとに安定した UUID を生成し、同じアカウントに対してデバイスをまたいで再利用してください。 これにより、購入や App Store の通知が正しく紐付けられたままになります。 トークンは、SDK のアクティベーション時またはユーザーの識別時の 2 つの方法で設定できます。 :::important `iosAppAccountToken` は必ず `customerUserId` と一緒に渡す必要があります。 トークンのみを渡した場合、トランザクションに含まれません。 ::: ```kotlin showLineNumbers // During configuration: Adapty.activate( AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withCustomerUserId( id = "YOUR_USER_ID", iosAppAccountToken = "YOUR_IOS_APP_ACCOUNT_TOKEN" ) .build() ).onSuccess { // successful activation }.onError { error -> // handle the error } // Or when identifying users Adapty.identify( customerUserId = "YOUR_USER_ID", iosAppAccountToken = "YOUR_IOS_APP_ACCOUNT_TOKEN" ).onSuccess { // successful identify }.onError { error -> // handle the error } ``` ## 難読化アカウント ID を設定する(Android) \{#set-obfuscated-account-ids-android\} Google Play では、ユーザーのプライバシーとセキュリティを強化するために、特定のユースケースで難読化アカウント ID が必要です。これらの ID は、ユーザー情報を匿名に保ちながら Google Play が購入を識別するのに役立ち、不正防止やアナリティクスにおいて特に重要です。 アプリが機密性の高いユーザーデータを扱っている場合や、特定のプライバシー規制への準拠が求められる場合に、これらの ID を設定する必要があるかもしれません。難読化 ID により、Google Play は実際のユーザー識別子を公開せずに購入を追跡できます。 :::important `androidObfuscatedAccountId` は必ず `customerUserId` と一緒に渡す必要があります。 難読化アカウント ID のみを渡した場合、トランザクションに含まれません。 ::: ```kotlin showLineNumbers // During configuration: Adapty.activate( AdaptyConfig.Builder("PUBLIC_SDK_KEY") .withCustomerUserId( id = "YOUR_USER_ID", androidObfuscatedAccountId = "YOUR_OBFUSCATED_ACCOUNT_ID" ) .build() ).onSuccess { // successful activation }.onError { error -> // handle the error } // Or when identifying users Adapty.identify( customerUserId = "YOUR_USER_ID", androidObfuscatedAccountId = "YOUR_OBFUSCATED_ACCOUNT_ID" ).onSuccess { // successful identify }.onError { error -> // handle the error } ``` ## デバイスをまたいでユーザーを検出する \{#detect-users-across-devices\} --- no_index: true --- SDKが有効化されると、StoreKit(iOS)またはGoogle Play Billing(Android)からユーザーの既存のエンタイトルメントを自動的に読み取り、Adaptyバックエンドと同期します。有効なサブスクリプションは、アプリが`restorePurchases`を呼び出すことなく、Adaptyプロファイルに表示されます。 **自動では行われない**のは、新しいデバイスのプロファイルが元のデバイスと同じユーザーのものであることの認識です。AdaptyはCustomer User IDでプロファイルを照合するため、同一性の継続性はCUIDとして何を使用するかによって異なります。 **デバイス間でAdaptyが検出できること** | あなたの設定 | Adaptyが検出すること | 必要な対応 | | --- | --- | --- | | Customer User ID = `device_id`(アプリのログインなし) | 新しいデバイスは異なるCUIDを取得するため、異なるプロファイルが作成されます。サブスクリプションは**Access level updated**イベントを通じて新しいプロファイルに同期されますが、`subscription_started`は発火しません。新しいプロファイルは元の購入の継承者として扱われます。`subscription_started`に基づくアナリティクスは、リターニングユーザーをカウント不足します。 | リターニングユーザーが既存のプロファイルをデバイス間で照合できるよう、安定したアカウントIDをCustomer User IDとして使用してください。 | | Customer User ID = 安定したアカウントID(すべてのデバイスでログイン) | SDKは`activate()`でサブスクリプションを自動同期し、`identify()`がCUIDで既存のプロファイルを照合します。 | 追加の設定は不要です。IDとサブスクリプションの両方が自動的に解決されます。 | | Apple Family Sharing の継承者 | ファミリーメンバーは**Access level updated**イベントのみを通じてサブスクリプションを受け取ります。`subscription_started`は発火しません。 | **Access level updated**をリッスンしてください。完全なイベントマトリクスは[Apple Family Sharing](apple-family-sharing)を参照してください。 | | 同じApple/Googleアカウント、異なるアプリ内ユーザー | 最初に購入を記録したプロファイルが親になります。その後のプロファイルは継承者チェーンを通じてサブスクリプションを確認し、**Access level updated**イベントが1回発生します。 | ログインを必須にし、あなたのモデルに合った[共有モード](sharing-paid-access-between-user-accounts)を選択してください。 | **新しいデバイスでの購入の復元** ペイウォールにユーザーが操作できる「購入を復元」ボタンを設置してください。Apple App Review(ガイドライン3.1.1)で必須とされており、自動同期がエッジケースを見逃した場合のフォールバックとして機能します。このボタンはSDKの`restorePurchases`を呼び出す必要があります。 初回起動時にプログラムで`restorePurchases`を呼び出すことは、通常の使用では必要ありません。SDKはすでに`activate()`で同等の処理を実行しています。プログラムによる呼び出しは、`activate()`完了後にアクセスが欠落している場合のデバッグなど、強制的に新しいレシートチェックを行う場合にのみ使用してください。 --- # File: kmp-setting-user-attributes --- --- title: "Kotlin Multiplatform SDKでユーザー属性を設定する" description: "Adaptyでユーザー属性を設定して、オーディエンスのセグメンテーションを改善する方法を学びます。" --- メールアドレスや電話番号など、アプリのユーザーにオプションの属性を設定できます。設定した属性は、ユーザー[セグメント](segments)の作成やCRMでの確認に活用できます。 ### ユーザー属性の設定 \{#setting-user-attributes\} ユーザー属性を設定するには、`.updateProfile()` メソッドを呼び出します。 ```kotlin showLineNumbers val builder = AdaptyProfileParameters.Builder() .withEmail("email@email.com") .withPhoneNumber("+18888888888") .withFirstName("John") .withLastName("Appleseed") .withGender(AdaptyProfile.Gender.FEMALE) .withBirthday(AdaptyProfile.Date(1970, 1, 3)) Adapty.updateProfile(builder.build()) .onSuccess { // profile updated successfully } .onError { error -> // handle the error } ``` `updateProfile` メソッドで以前に設定した属性はリセットされません。 :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: ### 使用可能なキーの一覧 \{#the-allowed-keys-list\} `AdaptyProfileParameters.Builder` で使用できるキー `<Key>` と値 `<Value>` は以下のとおりです。 | キー | 値 | |---|-----| | <p>email</p><p>phoneNumber</p><p>firstName</p><p>lastName</p> | String | | gender | Enum(使用可能な値: `AdaptyProfile.Gender.FEMALE`、`AdaptyProfile.Gender.MALE`、`AdaptyProfile.Gender.OTHER`) | | birthday | Date | ### カスタムユーザー属性 \{#custom-user-attributes\} 独自のカスタム属性を設定できます。これらは通常、アプリの使用状況に関連するものです。たとえば、フィットネスアプリであれば週あたりのエクササイズ回数、語学学習アプリであればユーザーの習熟度レベルなどが考えられます。セグメントで使用してターゲットを絞ったペイウォールやオファーを作成したり、アナリティクスでどのプロダクト指標が収益に最も影響するかを分析したりするのに役立ちます。 ```kotlin showLineNumbers val builder = AdaptyProfileParameters.Builder() builder.withCustomAttribute("key1", "value1") ``` 既存のキーを削除するには、`.withRemovedCustomAttribute()` メソッドを使用します。 ```kotlin showLineNumbers val builder = AdaptyProfileParameters.Builder() builder.withRemovedCustomAttribute("key2") ``` 設定済みのカスタム属性を事前に確認したい場合は、`AdaptyProfile` オブジェクトの `customAttributes` フィールドを使用してください。 :::warning `customAttributes` の値は最新の状態でない場合があります。ユーザー属性は複数のデバイスからいつでも送信される可能性があるため、最後の同期以降にサーバー上の属性が変更されている場合があります。 ::: ### 制限事項 \{#limits\} - ユーザーあたり最大30件のカスタム属性 - キー名は最大30文字。キー名には英数字および以下の記号が使用できます: `_` `-` `.` - 値は文字列または小数で、50文字以内。 --- # File: kmp-listen-subscription-changes --- --- title: "Kotlin Multiplatform SDKでサブスクリプションのステータスを確認する" description: "Kotlin MultiplatorformアプリでAdaptyを使用してユーザーのサブスクリプションステータスを追跡・管理し、顧客維持率を向上させましょう。" --- Adaptyを使えば、サブスクリプションのステータス管理が簡単になります。プロダクトIDをコードに手動で埋め込む必要はありません。代わりに、[アクセスレベル](access-level)がアクティブかどうかを確認するだけで、ユーザーのサブスクリプションステータスをすぐに把握できます。 サブスクリプションステータスの確認を始める前に、[リアルタイム デベロッパー通知 (RTDN)](enable-real-time-developer-notifications-rtdn) を設定してください。 ## アクセスレベルとAdaptyProfileオブジェクト \{#access-level-and-the-adaptyprofile-object\} アクセスレベルは [AdaptyProfile](https://kmp.adapty.io///adapty/com.adapty.kmp.models/-adapty-profile/) オブジェクトのプロパティです。アプリ起動時(例:[ユーザーを識別する](android-identifying-users#setting-customer-user-id-on-configuration)タイミングなど)にプロファイルを取得し、変更があれば随時更新することを推奨します。こうすることで、都度リクエストを送らずにプロファイルオブジェクトを活用できます。 プロファイルの更新通知を受け取るには、以下の[サブスクリプションステータスを含むプロファイル更新の監視](android-listen-subscription-changes)セクションで説明しているプロファイル変更のリスナーを設定してください。 :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: ## サーバーからアクセスレベルを取得する \{#retrieving-the-access-level-from-the-server\} サーバーからアクセスレベルを取得するには、`.getProfile()` メソッドを使用してください: ```kotlin showLineNumbers Adapty.getProfile().onSuccess { profile -> // check the access }.onError { error -> // handle the error } ``` レスポンスパラメーター: | パラメーター | 説明 | | --------- |-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Profile | <p>[AdaptyProfile](https://kmp.adapty.io///adapty/com.adapty.kmp.models/-adapty-profile/) オブジェクトです。通常、ユーザーがアプリのプレミアム機能にアクセスできるかどうかを判断するには、プロファイルのアクセスレベルのステータスを確認するだけで十分です。</p><p></p><p>`.getProfile` メソッドは常にAPIへのクエリを試みるため、最新の結果を返します。ネットワーク接続がないなどの理由でAdapty SDKがサーバーから情報を取得できない場合は、キャッシュのデータが返されます。また、Adapty SDKは `AdaptyProfile` のキャッシュを定期的に更新し、情報をできるだけ最新の状態に保ちます。</p> | `.getProfile()` メソッドはユーザープロファイルを返し、そこからアクセスレベルのステータスを取得できます。アプリには複数のアクセスレベルを設定することも可能です。たとえばニュースアプリでトピックごとにサブスクリプションを販売する場合、「sports」や「science」といったアクセスレベルを作成できます。ただし、ほとんどのケースでは1つのアクセスレベルで十分です。その場合はデフォルトの「premium」アクセスレベルをそのままご利用ください。 デフォルトの「premium」アクセスレベルを確認する例: ```kotlin showLineNumbers Adapty.getProfile().onSuccess { profile -> if (profile.accessLevels["premium"]?.isActive == true) { // grant access to premium features } }.onError { error -> // handle the error } ``` ### サブスクリプションステータスの更新を監視する \{#listening-for-subscription-status-updates\} ユーザーのサブスクリプションが変更されるたびに、Adaptyはイベントを発火します。 Adaptyからのメッセージを受け取るには、追加の設定が必要です: ```kotlin showLineNumbers Adapty.setOnProfileUpdatedListener { profile -> // handle any changes to subscription state } ``` Adaptyはアプリ起動時にもイベントを発火します。この場合、キャッシュされたサブスクリプションステータスが渡されます。 ### サブスクリプションステータスのキャッシュ \{#subscription-status-cache\} Adapty SDKに実装されたキャッシュには、プロファイルのサブスクリプションステータスが保存されます。つまり、サーバーが利用できない場合でも、キャッシュされたデータからプロファイルのサブスクリプション情報を取得できます。 ただし、キャッシュから直接データをリクエストすることはできません。SDKは1分ごとにサーバーへ定期的なクエリを行い、プロファイルに関する更新や変更を確認します。新しいトランザクションやその他の更新など、変更が検出された場合は、サーバーとの同期を保つためにキャッシュデータへ反映されます。 --- # File: kmp-deal-with-att --- --- title: "Kotlin Multiplatform SDKでATTを処理する" description: "Kotlin MultiplatformでAdaptyを使い始めて、サブスクリプションのセットアップと管理を効率化しましょう。" --- アプリがAppTrackingTransparencyフレームワークを使用してアプリトラッキングの認証リクエストをユーザーに表示する場合、[認証ステータス](https://developer.apple.com/documentation/apptrackingtransparency/attrackingmanager/authorizationstatus/)をAdaptyに送信する必要があります。 ```kotlin showLineNumbers val profileParameters = AdaptyProfileParameters.Builder() .withAttStatus(3) // 3 = ATTrackingManagerAuthorizationStatusAuthorized .build() Adapty.updateProfile(profileParameters) .onSuccess { // ATT status updated successfully } .onError { error -> // handle AdaptyError } ``` :::warning この値は変更されたらできるだけ早く送信することを強くお勧めします。そうすることで、設定済みのインテグレーションにタイムリーにデータが送信されます。 ::: --- # File: kids-mode-kmp --- --- title: "Kotlin Multiplatform SDKのキッズモード" description: "キッズモードを簡単に有効化してGoogleのポリシーに準拠。Kotlin Multiplatform SDKではGAIDや広告データを収集しません。" --- Kotlin Multiplatformアプリが子ども向けの場合、[Google](https://support.google.com/googleplay/android-developer/answer/9893335)のポリシーに従う必要があります。Adapty SDKを使用している場合、いくつかの簡単な手順でこれらのポリシーに準拠し、アプリストアの審査を通過できるよう設定できます。 ## 必要な対応 \{#whats-required\} Adapty SDKで以下の収集を無効にする必要があります: - [IDFA(広告識別子)](https://en.wikipedia.org/wiki/Identifier_for_Advertisers)(iOS) - [Android Advertising ID(AAID/GAID)](https://support.google.com/googleplay/android-developer/answer/6048248)(Android) - [IPアドレス](https://www.ftc.gov/system/files/ftc_gov/pdf/p235402_coppa_application.pdf) また、カスタマーユーザーIDの扱いにも注意が必要です。`<FirstName.LastName>`形式のユーザーIDやメールアドレスの使用は、個人情報の収集とみなされます。キッズモードでは、ランダム化または匿名化された識別子(ハッシュ化されたIDやデバイス生成のUUIDなど)を使用することがベストプラクティスです。 ## キッズモードの有効化 \{#enabling-kids-mode\} ### Adapty ダッシュボードでの設定 \{#updates-in-the-adapty-dashboard\} Adapty ダッシュボードでIPアドレスの収集を無効にする必要があります。[App settings](https://app.adapty.io/settings/general)に移動し、**Collect users' IP address**の下にある**Disable IP address collection**をクリックしてください。 ### モバイルアプリコードの変更 \{#updates-in-your-mobile-app-code\} ポリシーに準拠するため、Adapty SDKの初期化時にAndroid Advertising ID(AAID/GAID)とIPアドレスの収集を無効にする必要があります: ```kotlin showLineNumbers override fun onCreate() { super.onCreate() val config = AdaptyConfig .Builder("PUBLIC_SDK_KEY") // highlight-start .withGoogleAdvertisingIdCollectionDisabled(true) // set to `true` .withIpAddressCollectionDisabled(true) // set to `true` // highlight-end .build() Adapty.activate(configuration = config) .onSuccess { Log.d("Adapty", "SDK initialised with privacy settings") } .onError { error -> Log.e("Adapty", "Adapty init error: ${error.message}") } } ``` --- # File: kmp-onboardings --- --- title: "Onboardings in Kotlin Multiplatform SDK" description: "Learn how to work with onboardings in your Kotlin Multiplatform app with Adapty SDK." --- <CustomDocCardList /> --- # File: kmp-get-onboardings --- --- title: "Kotlin Multiplatform SDKでオンボーディングを取得する" description: "Kotlin Multiplatform向けのAdaptyでオンボーディングを取得する方法を学びます。" --- Adapty ダッシュボードのビルダーで[オンボーディングのビジュアル部分を設計](design-onboarding)した後、Kotlin Multiplatformアプリに表示できます。このプロセスの最初のステップは、プレースメントに関連付けられたオンボーディングとそのビュー設定を取得することです(以下で説明します)。 始める前に、以下を確認してください: 1. [Adapty Kotlin Multiplatform SDK](sdk-installation-kotlin-multiplatform)バージョン3.15.0以降をインストール済みであること。 2. [オンボーディングを作成](create-onboarding)済みであること。 3. オンボーディングを[プレースメント](placements)に追加済みであること。 ## オンボーディングの取得 \{#fetch-onboarding\} ノーコードビルダーで[オンボーディング](onboardings)を作成すると、アプリが取得して表示する必要のある設定コンテナとして保存されます。このコンテナは、表示されるコンテンツ、表示方法、ユーザーの操作(クイズの回答やフォーム入力など)の処理方法など、エクスペリエンス全体を管理します。また、コンテナは分析イベントを自動的に追跡するため、個別にビュー追跡を実装する必要はありません。 最高のパフォーマンスを得るため、ユーザーに表示する前に画像をダウンロードする十分な時間を確保できるよう、早めにオンボーディング設定を取得してください。 オンボーディングを取得するには、`getOnboarding`メソッドを使用します: ```kotlin showLineNumbers Adapty.getOnboarding( placementId = "YOUR_PLACEMENT_ID", locale = "en", fetchPolicy = AdaptyPaywallFetchPolicy.Default, loadTimeout = 5.seconds ).onSuccess { paywall -> // the requested paywall }.onError { error -> // handle the error } ``` パラメーター: | パラメーター | 必須/任意 | 説明 | |---------|--------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **placementId** | 必須 | 対象の[プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** | <p>任意</p><p>デフォルト: `en`</p> | オンボーディングのローカライズ識別子。このパラメーターは、マイナス(**-**)文字で区切られた1つまたは2つのサブタグで構成された言語コードであることが求められます。最初のサブタグは言語、2つ目はリージョンを表します。<p>例:`en`は英語、`pt-br`はブラジルポルトガル語を表します。</p> | | **fetchPolicy** | デフォルト: `.reloadRevalidatingCacheData` | <p>デフォルトでは、SDKはサーバーからデータの読み込みを試み、失敗した場合はキャッシュデータを返します。ユーザーが常に最新のデータを取得できるため、このオプションを推奨します。</p><p></p><p>ただし、ユーザーがインターネット接続が不安定な状況にある場合は、`.returnCacheDataElseLoad`を使用してキャッシュデータが存在する場合に返すことを検討してください。この場合、ユーザーは最新データを取得できないことがありますが、インターネット接続が不安定な状況でも読み込み時間が短縮されます。キャッシュは定期的に更新されるため、セッション中にネットワークリクエストを避けるために使用しても安全です。</p><p></p><p>キャッシュはアプリを再起動しても保持され、アプリを再インストールするか手動でクリーンアップした場合にのみクリアされます。</p><p></p><p>Adapty SDKはオンボーディングをローカルに2つのレイヤーで保存します:上記の定期更新されるキャッシュとフォールバックオンボーディングです。また、オンボーディングをより高速に取得するためにCDNを使用し、CDNが利用できない場合に備えてスタンドアロンのフォールバックサーバーも使用します。このシステムは、インターネット接続が不安定な場合でも、常に最新バージョンのオンボーディングを取得できるように設計されています。</p> | | **loadTimeout** | デフォルト: 5秒 | <p>このメソッドのタイムアウトを制限する値。タイムアウトに達した場合、キャッシュデータまたはローカルフォールバックが返されます。</p><p>まれに、操作が内部で複数のリクエストで構成される場合があるため、このメソッドは`loadTimeout`で指定した時間よりわずかに遅れてタイムアウトする場合があります。</p> | レスポンスパラメーター: | パラメーター | 説明 | |:----------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Onboarding | オンボーディング識別子と設定、リモートコンフィグ、およびその他のプロパティを含む[`AdaptyOnboarding`](https://kmp.adapty.io///adapty/com.adapty.kmp.models/-adapty-onboarding/)オブジェクト。 | ## デフォルトオーディエンスのオンボーディングで取得を高速化する \{#speed-up-onboarding-fetching-with-default-audience-onboarding\} 通常、オンボーディングはほぼ瞬時に取得されるため、このプロセスの高速化について心配する必要はありません。ただし、多数のオーディエンスとオンボーディングがあり、ユーザーのインターネット接続が不安定な場合、オンボーディングの取得に想定より時間がかかることがあります。そのような状況では、オンボーディングをまったく表示しないよりも、スムーズなユーザーエクスペリエンスを確保するためにデフォルトのオンボーディングを表示したい場合があります。 これに対処するために、`getOnboardingForDefaultAudience`メソッドを使用できます。このメソッドは、**すべてのユーザー**オーディエンス向けに指定されたプレースメントのオンボーディングを取得します。ただし、推奨されるアプローチは、上記の[オンボーディングの取得](#fetch-onboarding)セクションで説明した`getOnboarding`メソッドを使用することであることを理解することが重要です。 :::warning `getOnboardingForDefaultAudience`の代わりに`getOnboarding`の使用を検討してください。前者には重要な制限があります: - **互換性の問題**:複数のアプリバージョンをサポートする場合に問題が発生する可能性があり、下位互換性のあるデザインが必要になるか、古いバージョンが正しく表示されないことを受け入れる必要があります。 - **パーソナライズなし**:「すべてのユーザー」オーディエンス向けのコンテンツのみを表示し、国、アトリビューション、またはカスタム属性に基づくターゲティングが行われません。 ユースケースで高速な取得がこれらのデメリットを上回る場合は、以下に示すように`getOnboardingForDefaultAudience`を使用してください。そうでない場合は、[上記](#fetch-onboarding)で説明した`getOnboarding`を使用してください。 ::: ```kotlin showLineNumbers Adapty.getOnboardingForDefaultAudience( placementId = "YOUR_PLACEMENT_ID", locale = "en", fetchPolicy = AdaptyPaywallFetchPolicy.Default, ).onSuccess { paywall -> // the requested paywall }.onError { error -> // handle the error } ``` パラメーター: | パラメーター | 必須/任意 | 説明 | |---------|--------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **placementId** | 必須 | 対象の[プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** | <p>任意</p><p>デフォルト: `en`</p> | オンボーディングのローカライズ識別子。このパラメーターは、マイナス(**-**)文字で区切られた1つまたは2つのサブタグで構成された言語コードであることが求められます。最初のサブタグは言語、2つ目はリージョンを表します。<br/>例:`en`は英語、`pt-br`はブラジルポルトガル語を表します。 | | **fetchPolicy** | デフォルト: `.reloadRevalidatingCacheData` | <p>デフォルトでは、SDKはサーバーからデータの読み込みを試み、失敗した場合はキャッシュデータを返します。ユーザーが常に最新のデータを取得できるため、このオプションを推奨します。</p><p></p><p>ただし、ユーザーがインターネット接続が不安定な状況にある場合は、`.returnCacheDataElseLoad`を使用してキャッシュデータが存在する場合に返すことを検討してください。この場合、ユーザーは最新データを取得できないことがありますが、インターネット接続が不安定な状況でも読み込み時間が短縮されます。キャッシュは定期的に更新されるため、セッション中にネットワークリクエストを避けるために使用しても安全です。</p><p></p><p>キャッシュはアプリを再起動しても保持され、アプリを再インストールするか手動でクリーンアップした場合にのみクリアされます。</p><p></p><p>Adapty SDKはオンボーディングをローカルに2つのレイヤーで保存します:上記の定期更新されるキャッシュとフォールバックオンボーディングです。また、オンボーディングをより高速に取得するためにCDNを使用し、CDNが利用できない場合に備えてスタンドアロンのフォールバックサーバーも使用します。このシステムは、インターネット接続が不安定な場合でも、常に最新バージョンのオンボーディングを取得できるように設計されています。</p> | --- # File: kmp-present-onboardings --- --- title: "Kotlin Multiplatform SDKでオンボーディングを表示する" description: "コンバージョンを高めるためにオンボーディングを効果的に表示する方法を学びましょう。" --- ビルダーを使ってオンボーディングをカスタマイズした場合、Kotlin Multiplatformアプリのコードでレンダリング処理を記述しなくても、ユーザーに表示できます。このようなオンボーディングには、表示内容と表示方法の両方が含まれています。 始める前に、以下を確認してください: 1. [Adapty Kotlin Multiplatform SDK](sdk-installation-kotlin-multiplatform) 3.16.1以降がインストールされていること。 2. [オンボーディングを作成](create-onboarding)していること。 3. オンボーディングを[プレースメント](placements)に追加していること。 Adapty Kotlin Multiplatform SDKでは、オンボーディングを表示する方法が2つあります: - **Compose Multiplatformを使用する** - **Compose Multiplatformを使用しない** ## Compose Multiplatformを使用する \{#with-compose-multiplatform\} オンボーディングを表示するには、`createOnboardingView`メソッドで作成した`view`に対して`view.present()`メソッドを呼び出します。各`view`は一度しか使用できません。再度オンボーディングを表示する必要がある場合は、`createOnboardingView`をもう一度呼び出して新しい`view`インスタンスを作成してください。 :::warning `view`を再作成せずに再利用すると、エラーが発生する場合があります。 ::: ```kotlin showLineNumbers title="Kotlin Multiplatform" viewModelScope.launch { AdaptyUI.createOnboardingView(onboarding = onboarding).onSuccess { view -> view.present() }.onError { error -> // handle the error } } ``` ### iOSの表示スタイルを設定する \{#configure-ios-presentation-style\} `present()`メソッドに`iosPresentationStyle`パラメータを渡すことで、iOSでのオンボーディングの表示方法を設定できます。パラメータには`AdaptyUIIOSPresentationStyle.FULLSCREEN`(デフォルト)または`AdaptyUIIOSPresentationStyle.PAGESHEET`を指定できます。 ```kotlin showLineNumbers viewModelScope.launch { val view = AdaptyUI.createOnboardingView(onboarding = onboarding).getOrNull() view?.present(iosPresentationStyle = AdaptyUIIOSPresentationStyle.PAGESHEET) } ``` ### オンボーディング内のリンクの開き方をカスタマイズする \{#customize-how-links-open-in-onboardings\} デフォルトでは、オンボーディング内のリンクはアプリ内ブラウザで開きます。これにより、アプリを切り替えることなくウェブページをアプリ内で表示でき、シームレスなユーザー体験を提供します。 代わりに外部ブラウザでリンクを開きたい場合は、`externalUrlsPresentation`パラメータを`AdaptyWebPresentation.EXTERNAL_BROWSER`に設定することでこの動作をカスタマイズできます: ```kotlin showLineNumbers viewModelScope.launch { AdaptyUI.createOnboardingView( onboarding = onboarding, externalUrlsPresentation = AdaptyWebPresentation.EXTERNAL_BROWSER // default – IN_APP_BROWSER ).onSuccess { view -> view.present() }.onError { error -> // handle the error } } ``` ## Compose Multiplatformを使用しない \{#without-compose-multiplatform\} :::note `createNativeOnboardingView`はコアモジュール`io.adapty:adapty-kmp`の一部です。プロジェクトでCompose Multiplatformを使用しない場合、`io.adapty:adapty-kmp-ui`の依存関係は不要です。 ::: Compose Multiplatformを使わずにオンボーディングを埋め込むには、`createNativeOnboardingView`を呼び出します。レイアウトに追加できる`AdaptyNativeOnboardingView`が返されます: <Tabs> <TabItem value="android" label="Android"> ```kotlin showLineNumbers title="Kotlin Multiplatform (Android)" val nativeView = AdaptyUI.createNativeOnboardingView( context = context, viewModelStoreOwner = activity, onboarding = onboarding, observer = myOnboardingObserver, ) // Embed in your Compose layout: AndroidView( factory = { nativeView.view }, modifier = Modifier.fillMaxSize() ) ``` </TabItem> <TabItem value="ios" label="iOS"> KMPのインターフェースデフォルトメソッドはSwiftでは`@required`になるため、SwiftからSwiftから`AdaptyUIOnboardingsEventsObserver`を直接実装することはできません。まず`iosMain`でオープンな基底クラスを宣言してください: ```kotlin showLineNumbers title="iosMain (Kotlin)" open class BaseOnboardingObserver : AdaptyUIOnboardingsEventsObserver ``` 次にSwiftでサブクラス化し、必要なメソッドのみオーバーライドします: ```swift showLineNumbers title="Swift" class MyOnboardingObserver: BaseOnboardingObserver { override func onboardingViewOnCloseAction( view: AdaptyUIOnboardingView, meta: AdaptyUIOnboardingMeta, actionId: String ) { // remove nativeView from your view hierarchy } } let nativeView = AdaptyUI.shared.createNativeOnboardingView( onboarding: onboarding, observer: MyOnboardingObserver() ) // nativeView.viewController is a UIViewController. // Add it to your SwiftUI view or UIKit hierarchy. ``` </TabItem> </Tabs> ### ビューを破棄する \{#dispose-the-view\} レイアウトからビューを削除する際は`dispose()`を呼び出してください。これによりイベントリスナーの登録が解除され、内部リソースが解放されます。 ```kotlin showLineNumbers title="Kotlin Multiplatform" nativeView.dispose() ``` --- # File: kmp-handling-onboarding-events --- --- title: "Kotlin Multiplatform SDKでオンボーディングイベントを処理する" description: "Adaptyを使用してKotlin Multiplatformでオンボーディング関連のイベントを処理する方法。" --- 始める前に、以下を確認してください: 1. [Adapty Kotlin Multiplatform SDK](sdk-installation-kotlin-multiplatform) 3.15.0以降をインストール済みであること。 2. [オンボーディングを作成済み](create-onboarding)であること。 3. オンボーディングを[プレースメント](placements)に追加済みであること。 ビルダーで設定されたオンボーディングは、アプリが応答できるイベントを生成します。これらのイベントへの対応方法について、以下で説明します。 ## オンボーディングイベントオブザーバーの設定 \{#set-up-the-onboarding-event-observer\} オンボーディングイベントを処理するには、`AdaptyUIOnboardingsEventsObserver`インターフェースを実装し、`AdaptyUI.setOnboardingsEventsObserver()`でセットアップする必要があります。これはアプリのライフサイクルの早い段階、通常はメインアクティビティやアプリの初期化時に行ってください。 ```kotlin // In your app initialization AdaptyUI.setOnboardingsEventsObserver(MyAdaptyUIOnboardingsEventsObserver()) ``` ## カスタムアクション \{#custom-actions\} ビルダーでは、ボタンに**カスタム**アクションを追加してIDを割り当てることができます。このIDをコード内で使用して、カスタムアクションとして処理できます。 <img src={require('./img/ios-events-1.webp').default} style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> たとえば、ユーザーが**ログイン**や**通知を許可**といったカスタムボタンをタップすると、デリゲートメソッド`onCustomAction`がビルダーで設定したアクションIDとともに呼び出されます。「allowNotifications」のような独自のIDを作成できます。 ```kotlin class MyAdaptyUIOnboardingsEventsObserver : AdaptyUIOnboardingsEventsObserver { override fun onboardingViewOnCustomAction( view: AdaptyUIOnboardingView, meta: AdaptyUIOnboardingMeta, actionId: String ) { when (actionId) { "openPaywall" -> { // Display paywall from onboarding // You would typically fetch and present a new paywall here mainUiScope.launch { // Example: Get paywall by placement ID // val paywallResult = Adapty.getPaywall("your_placement_id") // paywallResult.onSuccess { paywall -> // val paywallViewResult = AdaptyUI.createPaywallView(paywall) // paywallViewResult.onSuccess { paywallView -> // paywallView.present() // } // } } } "allowNotifications" -> { // Handle notification permissions } else -> { // Handle other custom actions } } } } // Set up the observer AdaptyUI.setOnboardingsEventsObserver(MyAdaptyUIOnboardingsEventsObserver()) ``` <Details> <summary>イベントの例(クリックして展開)</summary> ```json { "actionId": "allowNotifications", "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 0, "screensTotal": 3 } } ``` </Details> ## オンボーディングを閉じる \{#closing-onboarding\} オンボーディングは、ユーザーが**閉じる**アクションが割り当てられたボタンをタップすると閉じたとみなされます。ユーザーがオンボーディングを閉じたときの動作を管理する必要があります。例: :::important ユーザーがオンボーディングを閉じたときの動作を管理する必要があります。たとえば、オンボーディング自体の表示を停止する必要があります。 ::: [`createNativeOnboardingView`](kmp-present-onboardings#without-compose-multiplatform)を使用している場合、`view.isStandaloneView`が`false`のとき、デフォルトの実装では`view.dismiss()`は呼び出されません。このコールバック内でビューをレイアウトから削除し、`dispose()`を呼び出してください。 ```kotlin class MyAdaptyUIOnboardingsEventsObserver : AdaptyUIOnboardingsEventsObserver { override fun onboardingViewOnCloseAction( view: AdaptyUIOnboardingView, meta: AdaptyUIOnboardingMeta, actionId: String ) { // Dismiss the onboarding screen mainUiScope.launch { view.dismiss() } // Additional cleanup or navigation logic can be added here // For example, navigate back or show main app content } } // Set up the observer AdaptyUI.setOnboardingsEventsObserver(MyAdaptyUIOnboardingsEventsObserver()) ``` <Details> <summary>イベントの例(クリックして展開)</summary> ```json { "action_id": "close_button", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "final_screen", "screen_index": 3, "total_screens": 4 } } ``` </Details> ## ペイウォールを開く \{#opening-a-paywall\} :::tip オンボーディングの中でペイウォールを開きたい場合は、このイベントを処理してください。閉じた後にペイウォールを開きたい場合は、[`onboardingViewOnCloseAction`](#closing-onboarding)を処理してイベントデータに依存せずにペイウォールを開く方が、よりシンプルな方法です。 ::: オンボーディング内でペイウォールを最もシームレスに扱う方法は、アクションIDをペイウォールのプレースメントIDと同じにすることです。これにより、プレースメントIDを使ってすぐにペイウォールを取得して開くことができます: ```kotlin class MyAdaptyUIOnboardingsEventsObserver : AdaptyUIOnboardingsEventsObserver { override fun onboardingViewOnPaywallAction( view: AdaptyUIOnboardingView, meta: AdaptyUIOnboardingMeta, actionId: String ) { // Get the paywall using the placement ID from the action mainUiScope.launch { val paywallResult = Adapty.getPaywall(placementId = actionId) paywallResult.onSuccess { paywall -> val paywallViewResult = AdaptyUI.createPaywallView(paywall) paywallViewResult.onSuccess { paywallView -> paywallView.present() }.onError { error -> // handle the error } }.onError { error -> // handle the error } } } } // Set up the observer AdaptyUI.setOnboardingsEventsObserver(MyAdaptyUIOnboardingsEventsObserver()) ``` <Details> <summary>イベントの例(クリックして展開)</summary> ```json { "action_id": "premium_offer_1", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "pricing_screen", "screen_index": 2, "total_screens": 4 } } ``` </Details> ## オンボーディングの読み込み完了 \{#finishing-loading-onboarding\} オンボーディングの読み込みが完了すると、このメソッドが呼び出されます: ```kotlin class MyAdaptyUIOnboardingsEventsObserver : AdaptyUIOnboardingsEventsObserver { override fun onboardingViewDidFinishLoading( view: AdaptyUIOnboardingView, meta: AdaptyUIOnboardingMeta ) { // Handle loading completion // You can add any initialization logic here } } // Set up the observer AdaptyUI.setOnboardingsEventsObserver(MyAdaptyUIOnboardingsEventsObserver()) ``` <Details> <summary>イベントの例(クリックして展開)</summary> ```json { "meta": { "onboarding_id": "onboarding_123", "screen_cid": "welcome_screen", "screen_index": 0, "total_screens": 4 } } ``` </Details> ## ナビゲーションイベント \{#navigation-events\} `onboardingViewOnAnalyticsEvent`メソッドは、オンボーディングフロー中にさまざまなアナリティクスイベントが発生したときに呼び出されます。 `event`オブジェクトは以下のいずれかの型になります: | 型 | 説明 | |------------|-------------| | `AdaptyOnboardingsAnalyticsEventOnboardingStarted` | オンボーディングが読み込まれたとき | | `AdaptyOnboardingsAnalyticsEventScreenPresented` | 任意の画面が表示されたとき | | `AdaptyOnboardingsAnalyticsEventScreenCompleted` | 画面が完了したとき。省略可能な`elementId`(完了した要素の識別子)と省略可能な`reply`(ユーザーからの回答)を含む。ユーザーが画面を離れるアクションを実行したときにトリガーされる。 | | `AdaptyOnboardingsAnalyticsEventSecondScreenPresented` | 2番目の画面が表示されたとき | | `AdaptyOnboardingsAnalyticsEventUserEmailCollected` | 入力フィールドでユーザーのメールアドレスが収集されたときにトリガーされる | | `AdaptyOnboardingsAnalyticsEventOnboardingCompleted` | ユーザーが`final` IDを持つ画面に到達したときにトリガーされる。このイベントが必要な場合は、最後の画面に`final` IDを割り当てる。 | | `AdaptyOnboardingsAnalyticsEventUnknown` | 認識されないイベントタイプの場合。`name`(不明なイベントの名前)と`meta`(追加のメタデータ)を含む。 | 各イベントには以下の`meta`情報が含まれます: | フィールド | 説明 | |------------|-------------| | `onboardingId` | オンボーディングフローの一意の識別子 | | `screenClientId` | 現在の画面の識別子 | | `screenIndex` | フロー内の現在の画面の位置 | | `screensTotal` | フロー内の画面の総数 | アナリティクスイベントをトラッキングに使用する例: ```kotlin class MyAdaptyUIOnboardingsEventsObserver : AdaptyUIOnboardingsEventsObserver { override fun onboardingViewOnAnalyticsEvent( view: AdaptyUIOnboardingView, meta: AdaptyUIOnboardingMeta, event: AdaptyOnboardingsAnalyticsEvent ) { when (event) { is AdaptyOnboardingsAnalyticsEventOnboardingStarted -> { // Track onboarding start trackEvent("onboarding_started", event.meta) } is AdaptyOnboardingsAnalyticsEventScreenPresented -> { // Track screen presentation trackEvent("screen_presented", event.meta) } is AdaptyOnboardingsAnalyticsEventScreenCompleted -> { // Track screen completion with user response trackEvent("screen_completed", event.meta, event.elementId, event.reply) } is AdaptyOnboardingsAnalyticsEventOnboardingCompleted -> { // Track successful onboarding completion trackEvent("onboarding_completed", event.meta) } is AdaptyOnboardingsAnalyticsEventUnknown -> { // Handle unknown events trackEvent(event.name, event.meta) } // Handle other cases as needed } } private fun trackEvent(eventName: String, meta: AdaptyUIOnboardingMeta, elementId: String? = null, reply: String? = null) { // Implement your analytics tracking here // For example, send to your analytics service } } // Set up the observer AdaptyUI.setOnboardingsEventsObserver(MyAdaptyUIOnboardingsEventsObserver()) ``` <Details> <summary>イベントの例(クリックして展開)</summary> ```javascript // OnboardingStarted { "meta": { "onboardingId": "onboarding_123", "screenClientId": "welcome_screen", "screenIndex": 0, "screensTotal": 4 } } // ScreenPresented { "meta": { "onboardingId": "onboarding_123", "screenClientId": "interests_screen", "screenIndex": 2, "screensTotal": 4 } } // ScreenCompleted { "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 1, "screensTotal": 4 }, "elementId": "profile_form", "reply": "success" } // SecondScreenPresented { "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 1, "screensTotal": 4 } } // UserEmailCollected { "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 1, "screensTotal": 4 } } // OnboardingCompleted { "meta": { "onboardingId": "onboarding_123", "screenClientId": "final_screen", "screenIndex": 3, "screensTotal": 4 } } ``` </Details> --- # File: kmp-onboarding-input --- --- title: "Kotlin Multiplatform SDKでオンボーディングのデータを処理する" description: "Adapty SDKを使用してKotlin MultiplatformアプリでオンボーディングのデータをKotlin Multiplatformで保存・活用する方法。" --- ユーザーがクイズの質問に回答したり、入力フィールドにデータを入力したりすると、`onboardingViewOnStateUpdatedAction` メソッドが呼び出されます。コード内でフィールドの種類を保存したり処理したりすることができます。 例: ```kotlin class MyAdaptyUIOnboardingsEventsObserver : AdaptyUIOnboardingsEventsObserver { override fun onboardingViewOnStateUpdatedAction( view: AdaptyUIOnboardingView, meta: AdaptyUIOnboardingMeta, elementId: String, params: AdaptyOnboardingsStateUpdatedParams ) { // Store user preferences or responses when (params) { is AdaptyOnboardingsSelectParams -> { // Handle single selection val id = params.id val value = params.value val label = params.label AppLogger.d("Selected option: $label (id: $id, value: $value)") } is AdaptyOnboardingsMultiSelectParams -> { // Handle multiple selections } is AdaptyOnboardingsInputParams -> { // Handle text input } is AdaptyOnboardingsDatePickerParams -> { // Handle date selection } } } } // Set up the observer AdaptyUI.setOnboardingsEventsObserver(MyAdaptyUIOnboardingsEventsObserver()) ``` <Details> <summary>保存されたデータの例(実装によってフォーマットが異なる場合があります)</summary> ```javascript // Example of a saved select action { "id": "onboarding_on_state_updated_action", "view": { /* AdaptyUI.OnboardingView object */ }, "meta": { "onboarding_id": "onboarding_123", "screen_cid": "preferences_screen", "screen_index": 1, "total_screens": 3 }, "action": { "element_id": "preference_selector", "element_type": "select", "value": { "id": "option_1", "value": "premium", "label": "Premium Plan" } } } // Example of a saved multi-select action { "id": "onboarding_on_state_updated_action", "view": { /* AdaptyUI.OnboardingView object */ }, "meta": { "onboarding_id": "onboarding_123", "screen_cid": "interests_screen", "screen_index": 2, "total_screens": 3 }, "action": { "element_id": "interests_selector", "element_type": "multi_select", "value": [ { "id": "interest_1", "value": "sports", "label": "Sports" }, { "id": "interest_2", "value": "music", "label": "Music" } ] } } // Example of a saved input action { "id": "onboarding_on_state_updated_action", "view": { /* AdaptyUI.OnboardingView object */ }, "meta": { "onboarding_id": "onboarding_123", "screen_cid": "profile_screen", "screen_index": 0, "total_screens": 3 }, "action": { "element_id": "name_input", "element_type": "input", "value": { "type": "text", "value": "John Doe" } } } // Example of a saved date picker action { "id": "onboarding_on_state_updated_action", "view": { /* AdaptyUI.OnboardingView object */ }, "meta": { "onboarding_id": "onboarding_123", "screen_cid": "profile_screen", "screen_index": 0, "total_screens": 3 }, "action": { "element_id": "birthday_picker", "element_type": "date_picker", "value": { "day": 15, "month": 6, "year": 1990 } } } ``` </Details> ## ユースケース \{#use-cases\} ### 入力データでユーザープロファイルを充実させる \{#enrich-user-profiles-with-data\} 入力データをユーザープロファイルにすぐに紐付けて、同じ情報を二度聞かないようにするには、アクションを処理する際に入力データで[ユーザープロファイルを更新](kmp-setting-user-attributes)する必要があります。 例えば、`name` というIDのテキストフィールドにユーザーの名前を入力させ、そのフィールドの値をユーザーの名前(ファーストネーム)として設定したい場合や、`email` フィールドにメールアドレスを入力させたい場合、アプリのコードは次のようになります: ```kotlin class MyAdaptyUIOnboardingsEventsObserver : AdaptyUIOnboardingsEventsObserver { override fun onboardingViewOnStateUpdatedAction( view: AdaptyUIOnboardingView, meta: AdaptyUIOnboardingMeta, elementId: String, params: AdaptyOnboardingsStateUpdatedParams ) { // Store user preferences or responses when (params) { is AdaptyOnboardingsInputParams -> { // Handle text input val builder = AdaptyProfileParameters.Builder() // Map elementId to appropriate profile field when (elementId) { "name" -> { when (val input = params.input) { is AdaptyOnboardingsTextInput -> { builder.withFirstName(input.value) } } } "email" -> { when (val input = params.input) { is AdaptyOnboardingsEmailInput -> { builder.withEmail(input.value) } } } } // Update profile asynchronously mainUiScope.launch { val profileParams = builder.build() val result = Adapty.updateProfile(profileParams) result.onSuccess { profile -> // Profile updated successfully AppLogger.d("Profile updated: ${profile.email}") }.onError { error -> // Handle the error AppLogger.e("Failed to update profile: ${error.message}") } } } } } } // Set up the observer AdaptyUI.setOnboardingsEventsObserver(MyAdaptyUIOnboardingsEventsObserver()) ``` ### 回答に基づいてペイウォールをカスタマイズする \{#customize-paywalls-based-on-answers\} オンボーディングのクイズを活用して、オンボーディング完了後にユーザーへ表示するペイウォールをカスタマイズすることもできます。 例えば、スポーツの経験についてユーザーに質問し、ユーザーグループによって異なるCTAやプロダクトを表示できます。 1. オンボーディングビルダーで[クイズを追加](onboarding-quizzes)し、各選択肢に意味のあるIDを割り当てます。 2. クイズの回答をIDに基づいて処理し、ユーザーに[カスタム属性を設定](kmp-setting-user-attributes)します。 ```kotlin class MyAdaptyUIOnboardingsEventsObserver : AdaptyUIOnboardingsEventsObserver { override fun onboardingViewOnStateUpdatedAction( view: AdaptyUIOnboardingView, meta: AdaptyUIOnboardingMeta, elementId: String, params: AdaptyOnboardingsStateUpdatedParams ) { // Handle quiz responses and set custom attributes when (params) { is AdaptyOnboardingsSelectParams -> { // Handle quiz selection val builder = AdaptyProfileParameters.Builder() // Map quiz responses to custom attributes when (elementId) { "experience" -> { // Set custom attribute 'experience' with the selected value (beginner, amateur, pro) builder.withCustomAttribute("experience", params.value) } } // Update profile asynchronously mainUiScope.launch { val profileParams = builder.build() val result = Adapty.updateProfile(profileParams) result.onSuccess { profile -> // Profile updated successfully AppLogger.d("Custom attribute 'experience' set to: ${params.value}") }.onError { error -> // Handle the error AppLogger.e("Failed to update profile: ${error.message}") } } } } } } // Set up the observer AdaptyUI.setOnboardingsEventsObserver(MyAdaptyUIOnboardingsEventsObserver()) ``` 3. カスタム属性の値ごとに[セグメントを作成](segments)します。 4. [プレースメント](placements)を作成し、作成した各セグメントに対して[オーディエンス](audience)を追加します。 5. アプリのコードでそのプレースメントの[ペイウォールを表示](kmp-paywalls)します。オンボーディングにペイウォールを開くボタンがある場合は、[このボタンのアクションへの応答](kmp-handling-onboarding-events#opening-a-paywall)としてペイウォールのコードを実装してください。 --- # File: kmp-best-practices --- --- title: "Best practices in Kotlin Multiplatform SDK" description: "Reference patterns for integrating Adapty SDK on Kotlin Multiplatform — call order, error handling, and other production-readiness rules." --- <CustomDocCardList /> --- # File: kmp-sdk-call-order --- --- title: "Kotlin Multiplatform SDKの呼び出し順序" description: "Adapty SDKのメソッドを正しい順序で呼び出すことで、プレミアムアクセスの消失、アトリビューションの欠落、断続的な有効化エラーを防ぎます。" --- `Adapty.activate()` は、他のAdapty SDKメソッドを呼び出す前に完了している必要があります。完了するまで、SDKには状態がありません。`activate()` の前または並行して発行された呼び出しは、有効化エラーで失敗します。[Kotlin Multiplatform SDKでのエラー処理](kmp-handle-errors)を参照してください。 アプリでユーザー認証を行い、起動後にカスタマーユーザーIDを取得する場合は、そのタイミングで `Adapty.identify()` を呼び出してください。`identify` が完了するまで、ユーザーアクションのメソッドを呼び出さないでください。`identify` と競合する呼び出しはエラーを返すか、有効化時に作成された匿名プロファイルに対して実行されます。これが発生すると、アトリビューション、`appsflyer_id` などのMMP IDやインストールの所有権が、識別済みプロファイルに必ずしも引き継がれません。アプリでユーザー認証を行わない場合は、`identify` をスキップして匿名プロファイルで作業を続けてください。 MMP・アナリティクスSDK(AppsFlyer、Adjust、Branch、PostHog)も同じルールに従います。まずそれらを初期化し、UID コールバックを受け取ってから `Adapty.activate` を呼び出してください。そうしないと、MMP IDが一時的な匿名プロファイルに紐付けられ、識別済みプロファイルに必ずしも引き継がれません。AppsFlyerの詳細については、[AppsFlyer](appsflyer)を参照してください。 ## 正しい呼び出し順序 \{#the-correct-order\} どのパスをたどるかは、カスタマーユーザーIDをいつ取得できるか、およびMMPやアナリティクスSDKを使用するかどうかによって異なります。 - **ステップ2と5**:すべてのアプリで必須です。SDKを有効化してから、SDKメソッドを呼び出します。 - **ステップ1と3**:MMPやアナリティクスSDK(AppsFlyer、Adjust、Branch、PostHog)を統合する場合のみ必要です。 - **ステップ4**:アプリでユーザー認証を行い、起動後にカスタマーユーザーIDを収集する場合のみ必要です。 アプリ起動時にカスタマーユーザーIDがわかっている場合は、`activate()` を呼び出す前(ステップ2a)に `AdaptyConfig.Builder` に渡してください。このパスでは匿名プロファイルが作成されないため、ステップ4は不要です。 | ステップ | 呼び出し | タイミング | 備考 | |------|---------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------| | 1 | MMPまたはアナリティクスSDKを初期化する(AppsFlyer、Adjust、PostHog、Branch) | アプリ起動時、最初に | MMPのUIDコールバック(例:`getAppsFlyerUID`)を待ってください。 | | 2a | `Adapty.activate(configuration = AdaptyConfig.Builder("KEY").withCustomerUserId(...).build())` | アプリ起動時、ステップ1の後、カスタマーユーザーIDがある場合 | 推奨。匿名プロファイルは一切作成されません。 | | 2b | `Adapty.activate(configuration = AdaptyConfig.Builder("KEY").build())` (`withCustomerUserId` なし) | アプリ起動時、ステップ1の後、カスタマーユーザーIDがない場合(または収集しない場合) | Adaptが匿名プロファイルを作成します。 | | 3 | `Adapty.setIntegrationIdentifier("appsflyer_id", uid)` (各MMPに対して) | ステップ2の後、ユーザーアクション呼び出しの前 | MMP IDが正しいプロファイルに紐付けられるために必要です。 | | 4 | `Adapty.identify("YOUR_USER_ID").onSuccess { ... }.onError { ... }` | ステップ3の後(MMPなしの場合はステップ2の後)、ステップ5の前 — 認証がある2bのパスのみ | ユーザーアクション呼び出しの前に `onSuccess` を待ってください。`identify` 中の並行呼び出しは匿名プロファイルに対して実行される可能性があります。 | | 5 | `getPaywall`、`getPaywallProducts`、`restorePurchases`、`makePurchase`、`updateAttribution`、`updateProfile` | `identify` を呼び出す場合はステップ4の後、そうでない場合はステップ3の後(MMPなしの場合はステップ2の後) | これらの呼び出しには安定したプロファイルが必要です。 | :::important これらのステップをスキップすると、既存ユーザーのプレミアムアクセスの消失、プロファイルへの `appsflyer_id` の欠落、誤ったオーディエンスに対するペイウォールの返却が発生します。 ::: ## Web2appおよびウェブファネルインストール \{#web2app-and-web-funnel-installs\} ユーザーがウェブチェックアウト(Stripe、Paddle)で購入し、後でネイティブアプリをインストールした場合、デバイスの最初の `activate()` によって新しい匿名プロファイルが作成されます。このプロファイルはウェブプロファイルとリンクされていません。認証フローやインストールリファラーからアプリ起動前にカスタマーユーザーIDを解決できる場合は、直接 `AdaptyConfig.Builder` に渡してください。そうしないと、`identify("YOUR_USER_ID")` を呼び出し、さらに `restorePurchases` を呼び出すまで、デバイスからウェブ購入が見えない状態になります。 各ウェブチェックアウトで送信するメタデータについては、以下を参照してください: - [Stripe](stripe) - [Paddle](paddle) --- # File: kmp-optimize-paywall-fetching --- --- title: "Kotlin Multiplatform SDKでペイウォール取得を最適化する" description: "Adapty ペイウォールを確実に取得: Kotlin Multiplatformのタイミング、キャッシュ、フォールバックパターン。" --- Kotlin Multiplatformでペイウォールを確実に取得するには、3つのことを行う必要があります: 高速にレンダリングする、オーディエンスに合わせたペイウォールを返す、ネットワークが遅いときでも適切にフォールバックする。以下のルールは、これを実現するためのタイミング、キャッシュ、フォールバックパターンをカバーしています。 :::tip このルールは、`Adapty.activate()` と `Adapty.identify()` がすでに完了していることを前提としています。[Kotlin Multiplatform SDKでのコール順序](kmp-sdk-call-order)を参照してください。 ::: ## ルールと注意点 \{#rules-and-pitfalls\} | 推奨 | 非推奨 | 理由 | |---|---|---| | 表示しようとしているプレースメントを取得する。 | 起動時にすべてのプレースメントを一括でプリフェッチする。 | 一括プリフェッチはメインスレッドをブロックし、バースト中にブラックスクリーンが発生する。 | | アトリビューションが解決される機会を与えた後(例: `activate` から1〜2秒後、または `setOnProfileUpdatedListener` が発火した後)に `getPaywall` を取得する。 | アプリ起動時に `getPaywall` を呼び出す。 | アトリビューションがまだ確定していない。ペイウォールがデフォルトのオーディエンスに対して解決され、セグメントやASAのパーソナライゼーションが無効になる。 | | `loadTimeout` を設定し、すべてのプレースメントに[フォールバックペイウォール](fallback-paywalls)を設定する。 | `getPaywall` を無期限に待ち続ける。 | タイムアウトがない場合、接続が悪いユーザーにはネットワークが解決されるまで(またはアプリを閉じるまで)空白の画面が表示される。 | `fetchPolicy` と `loadTimeout` パラメーターについては[ペイウォールとプロダクトの取得](fetch-paywalls-and-products-kmp)を、適切なプレースメントの選び方については[プレースメント](placements)を参照してください。 ## 接続が不安定な環境向けの調整 \{#tune-for-poor-connectivity\} 接続が継続的に不安定な市場(農村地帯、交通機関、ルーティングの影響を受ける地域)向け: - 最初の取得を除くすべての取得で `fetchPolicy = AdaptyPaywallFetchPolicy.ReturnCacheDataElseLoad` を設定する。 - Adapty ダッシュボードのすべてのプレースメントに[フォールバックペイウォール](fallback-paywalls)を設定する。 - `loadTimeout` を3〜5秒に設定し、タイムアウトが発生した場合はフォールバックを受け入れる。 - ペイウォールの表示を `Adapty.getProfile()` に依存させない。`getPaywall` を独立して呼び出し、プロファイルの遅延がUIをブロックしないようにする。 --- # File: kmp-test --- --- title: "Kotlin Multiplatform SDKでテストとリリース" description: "AdaptyでKotlin MultiplatformアプリのサブスクリプションステータスをチェックするKotlin Multiplatformでのテスト方法を学びます。" --- Kotlin MultiplatformアプリにAdapty SDKを実装済みであれば、すべてが正しく設定されており、購入が期待通りに動作することを確認したいはずです。これには、SDK連携のテストと、サンドボックス環境での実際の購入フローのテストが含まれます。 ## アプリのテスト \{#test-your-app\} アプリ内課金の包括的なテストについては、プラットフォーム固有のテストガイドを参照してください:[iOSテストガイド](test-purchases-in-sandbox)および[Androidテストガイド](testing-on-android)。 ## リリースの準備 \{#prepare-for-release\} アプリをストアに申請する前に、[リリースチェックリスト](release-checklist)に従って以下を確認してください: - ストア接続とサーバー通知が設定されている - 購入が完了し、Adaptyに報告されている - アクセスが正しくアンロックおよびリストアされる - プライバシーとレビューの要件を満たしている --- # File: kmp-best-practices --- --- title: "Best practices in Kotlin Multiplatform SDK" description: "Reference patterns for integrating Adapty SDK on Kotlin Multiplatform — call order, error handling, and other production-readiness rules." --- <CustomDocCardList /> --- # File: kmp-sdk-call-order --- --- title: "Kotlin Multiplatform SDKの呼び出し順序" description: "Adapty SDKのメソッドを正しい順序で呼び出すことで、プレミアムアクセスの消失、アトリビューションの欠落、断続的な有効化エラーを防ぎます。" --- `Adapty.activate()` は、他のAdapty SDKメソッドを呼び出す前に完了している必要があります。完了するまで、SDKには状態がありません。`activate()` の前または並行して発行された呼び出しは、有効化エラーで失敗します。[Kotlin Multiplatform SDKでのエラー処理](kmp-handle-errors)を参照してください。 アプリでユーザー認証を行い、起動後にカスタマーユーザーIDを取得する場合は、そのタイミングで `Adapty.identify()` を呼び出してください。`identify` が完了するまで、ユーザーアクションのメソッドを呼び出さないでください。`identify` と競合する呼び出しはエラーを返すか、有効化時に作成された匿名プロファイルに対して実行されます。これが発生すると、アトリビューション、`appsflyer_id` などのMMP IDやインストールの所有権が、識別済みプロファイルに必ずしも引き継がれません。アプリでユーザー認証を行わない場合は、`identify` をスキップして匿名プロファイルで作業を続けてください。 MMP・アナリティクスSDK(AppsFlyer、Adjust、Branch、PostHog)も同じルールに従います。まずそれらを初期化し、UID コールバックを受け取ってから `Adapty.activate` を呼び出してください。そうしないと、MMP IDが一時的な匿名プロファイルに紐付けられ、識別済みプロファイルに必ずしも引き継がれません。AppsFlyerの詳細については、[AppsFlyer](appsflyer)を参照してください。 ## 正しい呼び出し順序 \{#the-correct-order\} どのパスをたどるかは、カスタマーユーザーIDをいつ取得できるか、およびMMPやアナリティクスSDKを使用するかどうかによって異なります。 - **ステップ2と5**:すべてのアプリで必須です。SDKを有効化してから、SDKメソッドを呼び出します。 - **ステップ1と3**:MMPやアナリティクスSDK(AppsFlyer、Adjust、Branch、PostHog)を統合する場合のみ必要です。 - **ステップ4**:アプリでユーザー認証を行い、起動後にカスタマーユーザーIDを収集する場合のみ必要です。 アプリ起動時にカスタマーユーザーIDがわかっている場合は、`activate()` を呼び出す前(ステップ2a)に `AdaptyConfig.Builder` に渡してください。このパスでは匿名プロファイルが作成されないため、ステップ4は不要です。 | ステップ | 呼び出し | タイミング | 備考 | |------|---------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------| | 1 | MMPまたはアナリティクスSDKを初期化する(AppsFlyer、Adjust、PostHog、Branch) | アプリ起動時、最初に | MMPのUIDコールバック(例:`getAppsFlyerUID`)を待ってください。 | | 2a | `Adapty.activate(configuration = AdaptyConfig.Builder("KEY").withCustomerUserId(...).build())` | アプリ起動時、ステップ1の後、カスタマーユーザーIDがある場合 | 推奨。匿名プロファイルは一切作成されません。 | | 2b | `Adapty.activate(configuration = AdaptyConfig.Builder("KEY").build())` (`withCustomerUserId` なし) | アプリ起動時、ステップ1の後、カスタマーユーザーIDがない場合(または収集しない場合) | Adaptが匿名プロファイルを作成します。 | | 3 | `Adapty.setIntegrationIdentifier("appsflyer_id", uid)` (各MMPに対して) | ステップ2の後、ユーザーアクション呼び出しの前 | MMP IDが正しいプロファイルに紐付けられるために必要です。 | | 4 | `Adapty.identify("YOUR_USER_ID").onSuccess { ... }.onError { ... }` | ステップ3の後(MMPなしの場合はステップ2の後)、ステップ5の前 — 認証がある2bのパスのみ | ユーザーアクション呼び出しの前に `onSuccess` を待ってください。`identify` 中の並行呼び出しは匿名プロファイルに対して実行される可能性があります。 | | 5 | `getPaywall`、`getPaywallProducts`、`restorePurchases`、`makePurchase`、`updateAttribution`、`updateProfile` | `identify` を呼び出す場合はステップ4の後、そうでない場合はステップ3の後(MMPなしの場合はステップ2の後) | これらの呼び出しには安定したプロファイルが必要です。 | :::important これらのステップをスキップすると、既存ユーザーのプレミアムアクセスの消失、プロファイルへの `appsflyer_id` の欠落、誤ったオーディエンスに対するペイウォールの返却が発生します。 ::: ## Web2appおよびウェブファネルインストール \{#web2app-and-web-funnel-installs\} ユーザーがウェブチェックアウト(Stripe、Paddle)で購入し、後でネイティブアプリをインストールした場合、デバイスの最初の `activate()` によって新しい匿名プロファイルが作成されます。このプロファイルはウェブプロファイルとリンクされていません。認証フローやインストールリファラーからアプリ起動前にカスタマーユーザーIDを解決できる場合は、直接 `AdaptyConfig.Builder` に渡してください。そうしないと、`identify("YOUR_USER_ID")` を呼び出し、さらに `restorePurchases` を呼び出すまで、デバイスからウェブ購入が見えない状態になります。 各ウェブチェックアウトで送信するメタデータについては、以下を参照してください: - [Stripe](stripe) - [Paddle](paddle) --- # File: kmp-optimize-paywall-fetching --- --- title: "Kotlin Multiplatform SDKでペイウォール取得を最適化する" description: "Adapty ペイウォールを確実に取得: Kotlin Multiplatformのタイミング、キャッシュ、フォールバックパターン。" --- Kotlin Multiplatformでペイウォールを確実に取得するには、3つのことを行う必要があります: 高速にレンダリングする、オーディエンスに合わせたペイウォールを返す、ネットワークが遅いときでも適切にフォールバックする。以下のルールは、これを実現するためのタイミング、キャッシュ、フォールバックパターンをカバーしています。 :::tip このルールは、`Adapty.activate()` と `Adapty.identify()` がすでに完了していることを前提としています。[Kotlin Multiplatform SDKでのコール順序](kmp-sdk-call-order)を参照してください。 ::: ## ルールと注意点 \{#rules-and-pitfalls\} | 推奨 | 非推奨 | 理由 | |---|---|---| | 表示しようとしているプレースメントを取得する。 | 起動時にすべてのプレースメントを一括でプリフェッチする。 | 一括プリフェッチはメインスレッドをブロックし、バースト中にブラックスクリーンが発生する。 | | アトリビューションが解決される機会を与えた後(例: `activate` から1〜2秒後、または `setOnProfileUpdatedListener` が発火した後)に `getPaywall` を取得する。 | アプリ起動時に `getPaywall` を呼び出す。 | アトリビューションがまだ確定していない。ペイウォールがデフォルトのオーディエンスに対して解決され、セグメントやASAのパーソナライゼーションが無効になる。 | | `loadTimeout` を設定し、すべてのプレースメントに[フォールバックペイウォール](fallback-paywalls)を設定する。 | `getPaywall` を無期限に待ち続ける。 | タイムアウトがない場合、接続が悪いユーザーにはネットワークが解決されるまで(またはアプリを閉じるまで)空白の画面が表示される。 | `fetchPolicy` と `loadTimeout` パラメーターについては[ペイウォールとプロダクトの取得](fetch-paywalls-and-products-kmp)を、適切なプレースメントの選び方については[プレースメント](placements)を参照してください。 ## 接続が不安定な環境向けの調整 \{#tune-for-poor-connectivity\} 接続が継続的に不安定な市場(農村地帯、交通機関、ルーティングの影響を受ける地域)向け: - 最初の取得を除くすべての取得で `fetchPolicy = AdaptyPaywallFetchPolicy.ReturnCacheDataElseLoad` を設定する。 - Adapty ダッシュボードのすべてのプレースメントに[フォールバックペイウォール](fallback-paywalls)を設定する。 - `loadTimeout` を3〜5秒に設定し、タイムアウトが発生した場合はフォールバックを受け入れる。 - ペイウォールの表示を `Adapty.getProfile()` に依存させない。`getPaywall` を独立して呼び出し、プロファイルの遅延がUIをブロックしないようにする。 --- # File: kmp-test --- --- title: "Kotlin Multiplatform SDKでテストとリリース" description: "AdaptyでKotlin MultiplatformアプリのサブスクリプションステータスをチェックするKotlin Multiplatformでのテスト方法を学びます。" --- Kotlin MultiplatformアプリにAdapty SDKを実装済みであれば、すべてが正しく設定されており、購入が期待通りに動作することを確認したいはずです。これには、SDK連携のテストと、サンドボックス環境での実際の購入フローのテストが含まれます。 ## アプリのテスト \{#test-your-app\} アプリ内課金の包括的なテストについては、プラットフォーム固有のテストガイドを参照してください:[iOSテストガイド](test-purchases-in-sandbox)および[Androidテストガイド](testing-on-android)。 ## リリースの準備 \{#prepare-for-release\} アプリをストアに申請する前に、[リリースチェックリスト](release-checklist)に従って以下を確認してください: - ストア接続とサーバー通知が設定されている - 購入が完了し、Adaptyに報告されている - アクセスが正しくアンロックおよびリストアされる - プライバシーとレビューの要件を満たしている --- # File: kmp-reference --- --- title: "Reference for Kotlin Multiplatform SDK" description: "Reference documentation for Adapty Kotlin Multiplatform SDK." --- This page contains reference documentation for Adapty Kotlin Multiplatform SDK. Choose the topic you need: - **[SDK models](https://kmp.adapty.io/adapty/)** - Data models and structures used by the SDK - **[Handle errors](kmp-handle-errors)** - Error handling and troubleshooting --- # File: kmp-handle-errors --- --- title: "Handle errors in Kotlin Multiplatform SDK" description: "Learn how to handle errors in your Kotlin Multiplatform app with Adapty." --- This page covers error handling in the Adapty Kotlin Multiplatform SDK. ## Error handling basics All Adapty SDK methods return results that can be either success or error. Always handle both cases: <Tabs groupId="current-os" queryString> <TabItem value="kotlin" label="Kotlin" default> ```kotlin showLineNumbers Adapty.getProfile { result -> when (result) { is AdaptyResult.Success -> { val profile = result.value // Handle success } is AdaptyResult.Error -> { val error = result.error // Handle error Log.e("Adapty", "Error: ${error.message}") } } } ``` </TabItem> <TabItem value="java" label="Java" default> ```java showLineNumbers Adapty.getProfile(result -> { if (result instanceof AdaptyResult.Success) { AdaptyProfile profile = ((AdaptyResult.Success<AdaptyProfile>) result).getValue(); // Handle success } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); // Handle error Log.e("Adapty", "Error: " + error.getMessage()); } }); ``` </TabItem> </Tabs> ## Common error codes | Error Code | Description | Solution | |------------|-------------|----------| | 1000 | No product IDs found | Check product configuration in dashboard | | 1001 | Network error | Check internet connection | | 1002 | Invalid SDK key | Verify your SDK key | | 1003 | Can't make payments | Device doesn't support payments | | 1004 | Product not available | Product not configured in store | ## Handle specific errors ### Network errors <Tabs groupId="current-os" queryString> <TabItem value="kotlin" label="Kotlin" default> ```kotlin showLineNumbers Adapty.getPaywall("main") { result -> when (result) { is AdaptyResult.Success -> { val paywall = result.value // Use paywall } is AdaptyResult.Error -> { val error = result.error when (error.code) { 1001 -> { // Network error - show offline message showOfflineMessage() } else -> { // Other errors showErrorMessage(error.message) } } } } } ``` </TabItem> <TabItem value="java" label="Java" default> ```java showLineNumbers Adapty.getPaywall("main", result -> { if (result instanceof AdaptyResult.Success) { AdaptyPaywall paywall = ((AdaptyResult.Success<AdaptyPaywall>) result).getValue(); // Use paywall } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); switch (error.getCode()) { case 1001: // Network error - show offline message showOfflineMessage(); break; default: // Other errors showErrorMessage(error.getMessage()); break; } } }); ``` </TabItem> </Tabs> ### Purchase errors <Tabs groupId="current-os" queryString> <TabItem value="kotlin" label="Kotlin" default> ```kotlin showLineNumbers product.makePurchase { result -> when (result) { is AdaptyResult.Success -> { val purchase = result.value // Purchase successful showSuccessMessage() } is AdaptyResult.Error -> { val error = result.error when (error.code) { 1003 -> { // Can't make payments showPaymentNotAvailableMessage() } 1004 -> { // Product not available showProductNotAvailableMessage() } else -> { // Other purchase errors showPurchaseErrorMessage(error.message) } } } } } ``` </TabItem> <TabItem value="java" label="Java" default> ```java showLineNumbers product.makePurchase(result -> { if (result instanceof AdaptyResult.Success) { AdaptyPurchase purchase = ((AdaptyResult.Success<AdaptyPurchase>) result).getValue(); // Purchase successful showSuccessMessage(); } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); switch (error.getCode()) { case 1003: // Can't make payments showPaymentNotAvailableMessage(); break; case 1004: // Product not available showProductNotAvailableMessage(); break; default: // Other purchase errors showPurchaseErrorMessage(error.getMessage()); break; } } }); ``` </TabItem> </Tabs> ## Error recovery strategies ### Retry on network errors <Tabs groupId="current-os" queryString> <TabItem value="kotlin" label="Kotlin" default> ```kotlin showLineNumbers fun getPaywallWithRetry(placementId: String, maxRetries: Int = 3) { var retryCount = 0 fun attemptGetPaywall() { Adapty.getPaywall(placementId) { result -> when (result) { is AdaptyResult.Success -> { val paywall = result.value // Use paywall } is AdaptyResult.Error -> { val error = result.error if (error.code == 1001 && retryCount < maxRetries) { // Network error - retry retryCount++ Handler(Looper.getMainLooper()).postDelayed({ attemptGetPaywall() }, 1000 * retryCount) // Exponential backoff } else { // Max retries reached or other error showErrorMessage(error.message) } } } } } attemptGetPaywall() } ``` </TabItem> <TabItem value="java" label="Java" default> ```java showLineNumbers public void getPaywallWithRetry(String placementId, int maxRetries) { AtomicInteger retryCount = new AtomicInteger(0); Runnable attemptGetPaywall = new Runnable() { @Override public void run() { Adapty.getPaywall(placementId, result -> { if (result instanceof AdaptyResult.Success) { AdaptyPaywall paywall = ((AdaptyResult.Success<AdaptyPaywall>) result).getValue(); // Use paywall } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); if (error.getCode() == 1001 && retryCount.get() < maxRetries) { // Network error - retry retryCount.incrementAndGet(); new Handler(Looper.getMainLooper()).postDelayed(this, 1000 * retryCount.get()); } else { // Max retries reached or other error showErrorMessage(error.getMessage()); } } }); } }; attemptGetPaywall.run(); } ``` </TabItem> </Tabs> ### Fallback to cached data <Tabs groupId="current-os" queryString> <TabItem value="kotlin" label="Kotlin" default> ```kotlin showLineNumbers class PaywallManager { private var cachedPaywall: AdaptyPaywall? = null fun getPaywall(placementId: String) { Adapty.getPaywall(placementId) { result -> when (result) { is AdaptyResult.Success -> { val paywall = result.value cachedPaywall = paywall showPaywall(paywall) } is AdaptyResult.Error -> { val error = result.error if (error.code == 1001 && cachedPaywall != null) { // Network error - use cached paywall showPaywall(cachedPaywall!!) showOfflineIndicator() } else { // No cache available or other error showErrorMessage(error.message) } } } } } } ``` </TabItem> <TabItem value="java" label="Java" default> ```java showLineNumbers public class PaywallManager { private AdaptyPaywall cachedPaywall; public void getPaywall(String placementId) { Adapty.getPaywall(placementId, result -> { if (result instanceof AdaptyResult.Success) { AdaptyPaywall paywall = ((AdaptyResult.Success<AdaptyPaywall>) result).getValue(); cachedPaywall = paywall; showPaywall(paywall); } else if (result instanceof AdaptyResult.Error) { AdaptyError error = ((AdaptyResult.Error) result).getError(); if (error.getCode() == 1001 && cachedPaywall != null) { // Network error - use cached paywall showPaywall(cachedPaywall); showOfflineIndicator(); } else { // No cache available or other error showErrorMessage(error.getMessage()); } } }); } } ``` </TabItem> </Tabs> ## Next steps - [Fix for Code-1000 noProductIDsFound error](InvalidProductIdentifiers-kmp) - [Fix for Code-1003 cantMakePayments error](cantMakePayments-kmp) - [Complete API reference](https://android.adapty.io) - Full SDK documentation --- # File: InvalidProductIdentifiers-kmp --- --- title: "Kotlin Multiplatform SDK の Code-1000 noProductIDsFound エラーの修正" description: "Adapty でサブスクリプションを管理する際の無効なプロダクト識別子エラーを解決します。" --- 1000 コードのエラー `noProductIDsFound` は、ペイウォールでリクエストしたプロダクトが App Store に登録されているにもかかわらず、購入できる状態にないことを示しています。このエラーには `InvalidProductIdentifiers` 警告が伴う場合があります。警告のみでエラーが出ていない場合は、無視して問題ありません。 `noProductIDsFound` エラーが発生している場合は、次の手順で解決してください。 ## ステップ 1. バンドル ID を確認する \{#step-2-check-bundle-id\} --- no_index: true --- 1. [App Store Connect](https://appstoreconnect.apple.com/apps) を開きます。アプリを選択し、**General** → **App Information** セクションに進みます。 2. **General Information** サブセクションで **Bundle ID** をコピーします。 <Zoom> <img src="/docs/img/afd5012-bundle_id_apple.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> </Zoom> 3. Adapty のトップメニューから [**App settings** -> **iOS SDK** タブ](https://app.adapty.io/settings/ios-sdk) を開き、コピーした値を **Bundle ID** フィールドに貼り付けます。 <Zoom> <img src="/docs/img/2d64163-bundle_id.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> </Zoom> 4. App Store Connect の **App information** ページに戻り、**Apple ID** をコピーします。 5. Adapty ダッシュボードの [**App settings** -> **iOS SDK**](https://app.adapty.io/settings/ios-sdk) ページで、**Apple app ID** フィールドにその ID を貼り付けます。 ## ステップ 2. プロダクトを確認する \{#step-3-check-products\} 1. **App Store Connect** を開き、左側のメニューから [**Monetization** → **Subscriptions**](https://appstoreconnect.apple.com/apps/6477523342/distribution/subscriptions) に移動します。 <img src="/assets/shared/img/subscription_group_open.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. サブスクリプショングループ名をクリックすると、**Subscriptions** セクションにプロダクトの一覧が表示されます。 3. テスト中のプロダクトが **Ready to Submit** になっていることを確認します。なっていない場合は、[App Store のプロダクト](app-store-products)ページの手順に従ってください。 <img src="/assets/shared/img/ready-to-submit.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. テーブルのプロダクト ID と、Adapty ダッシュボードの [**Products**](https://app.adapty.io/products) タブに表示されているプロダクト ID を比較します。ID が一致しない場合は、テーブルからプロダクト ID をコピーして、Adapty ダッシュボードでそのプロダクト ID を使って[プロダクトを作成](create-product)してください。 <img src="/assets/shared/img/product-id-copy.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## ステップ 3. プロダクトの提供状況を確認する \{#step-4-check-product-availability\} 1. **App Store Connect** に戻り、同じ **Subscriptions** セクションを開きます。 <img src="/assets/shared/img/subscription_group_open.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. サブスクリプショングループ名をクリックしてプロダクト一覧を表示します。 3. テスト中のプロダクトを選択します。 <img src="/assets/shared/img/click-product.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **Availability** セクションまでスクロールし、必要な国や地域がすべて一覧に含まれていることを確認します。 <img src="/assets/shared/img/product-availability.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## ステップ 4. プロダクトの価格を確認する \{#step-5-check-product-prices\} 1. 再度 **App Store Connect** の **Monetization** → **Subscriptions** セクションに移動します。 <img src="/assets/shared/img/subscription_group_open.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. サブスクリプショングループ名をクリックします。 3. テスト中のプロダクトを選択します。 <img src="/assets/shared/img/click-product.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **Subscription Pricing** までスクロールし、**Current Pricing for New Subscribers** セクションを展開します。 <img src="/assets/shared/img/check-prices.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. 必要な価格がすべて一覧に含まれていることを確認します。 <img src="/assets/shared/img/product-pricing.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## ステップ 5. アプリの有料ステータス、銀行口座、税務フォームがアクティブであることを確認する \{#step-5-check-app-paid-status-bank-account-and-tax-forms-are-active\} 1. [**App Store Connect**](https://appstoreconnect.apple.com/) のホームページで **Business** をクリックします。 <img src="/assets/shared/img/business.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. 会社名を選択します。 <img src="/assets/shared/img/business-name.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. スクロールして、**Paid Apps Agreement**、**Bank Account**、**Tax forms** がすべて **Active** と表示されていることを確認します。 <img src="/assets/shared/img/appstore-connect-status.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> これらの手順を実施することで、`InvalidProductIdentifiers` 警告を解消し、プロダクトをストアで公開できるようになります。 ## ステップ 6. プロダクトが動かない場合は再作成する \{#step-6-recreate-the-product-if-its-stuck\} ステップ 1〜5 をすべてパスしても — `Approved` ステータス、バンドル ID の一致、有効な API キー — SDK が `1000 noProductIDsFound` を返し続ける場合があります。その場合、プロダクトが Apple のレジストリで動かなくなっている可能性があります。App Store Connect の UI 上にはプロダクトが存在しているように見えても、StoreKit のルックアップパスに公開されていない状態になることがあります。 App Store Connect でそのプロダクトを削除し、同じプロダクト ID で再作成してください。再作成後、反映されるまで最大 24 時間かかる場合があります。 --- # File: cantMakePayments-kmp --- --- title: "Kotlin Multiplatform SDKにおけるCode-1003 cantMakePaymentエラーの修正方法" description: "Adaptyでサブスクリプションを管理する際の支払い処理エラーを解決します。" --- 1003エラー(`cantMakePayments`)は、このデバイスでアプリ内課金ができないことを示しています。 `cantMakePayments`エラーが発生している場合、通常は以下のいずれかの原因が考えられます: - デバイスの制限:このエラーはAdaptyとは無関係です。以下の解決方法を参照してください。 - オブザーバーモードの設定:`makePurchase`メソッドとオブザーバーモードは同時に使用できません。以下のセクションを参照してください。 ## 問題:デバイスの制限 \{#issue-device-restrictions\} | 問題 | 解決方法 | |-----------------------------|---------------------------------------------------------| | スクリーンタイムの制限 | [スクリーンタイム](https://support.apple.com/en-us/102470)でアプリ内課金の制限を無効にする | | アカウントの停止 | Appleサポートに連絡してアカウントの問題を解決する | | 地域の制限 | 対応地域のApp Storeアカウントを使用する | ## 問題:オブザーバーモードとmakePurchaseの併用 \{#issue-using-both-observer-mode-and-makepurchase\} 購入処理に`makePurchase`を使用している場合、オブザーバーモードを使用する必要はありません。[オブザーバーモード](observer-vs-full-mode)が必要なのは、購入ロジックを自分で実装する場合のみです。 したがって、`makePurchase`を使用している場合は、SDK有効化コードからオブザーバーモードの有効化を安全に削除できます。 --- # File: kmp-sdk-migration-guides --- --- title: "Kotlin Multiplatform SDK Migration Guides" description: "Migration guides for Adapty Kotlin Multiplatform SDK versions." --- This page contains all migration guides for Adapty Kotlin Multiplatform SDK. Choose the version you want to migrate to for detailed instructions: - **[Migrate to v3.15](migration-to-kmp-315)** --- # File: migration-to-kmp-315 --- --- title: "Adapty Kotlin Multiplatform SDK 3.15.0 移行ガイド" description: "Adapty Kotlin Multiplatform SDK 3.15.0 の移行手順" --- Adapty Kotlin Multiplatform SDK 3.15.0 はメジャーリリースであり、新機能と改善が含まれています。ただし、一部の移行作業が必要になる場合があります。 1. オブザーバークラスとメソッド名を更新する。 2. フォールバックペイウォールのメソッド名を更新する。 3. イベントハンドリングメソッドのビュークラス名を更新する。 ## オブザーバークラスとメソッド名を更新する \{#update-observer-class-and-method-names\} オブザーバークラスとその登録メソッドの名前が変更されました: ```diff - import com.adapty.kmp.AdaptyUIObserver + import com.adapty.kmp.AdaptyUIPaywallsEventsObserver - import com.adapty.kmp.models.AdaptyUIView + import com.adapty.kmp.models.AdaptyUIPaywallView - class MyAdaptyUIObserver : AdaptyUIObserver { - override fun paywallViewDidPerformAction(view: AdaptyUIView, action: AdaptyUIAction) { + class MyAdaptyUIPaywallsEventsObserver : AdaptyUIPaywallsEventsObserver { + override fun paywallViewDidPerformAction(view: AdaptyUIPaywallView, action: AdaptyUIAction) { // handle actions } } // Set up the observer - AdaptyUI.setObserver(MyAdaptyUIObserver()) + AdaptyUI.setPaywallsEventsObserver(MyAdaptyUIPaywallsEventsObserver()) ``` ## フォールバックペイウォールのメソッド名を更新する \{#update-fallback-paywalls-method-name\} フォールバックペイウォールを設定するメソッド名が変更されました: ```diff showLineNumbers - Adapty.setFallbackPaywalls(assetId = "fallback.json") + Adapty.setFallback(assetId = "fallback.json") .onSuccess { // Fallback paywalls loaded successfully } .onError { error -> // Handle the error } ``` ## イベントハンドリングメソッドのビュークラス名を更新する \{#update-view-class-name-in-event-handling-methods\} すべてのイベントハンドリングメソッドで、`AdaptyUIView` の代わりに新しい `AdaptyUIPaywallView` クラスを使用するようになりました: ```diff - override fun paywallViewDidAppear(view: AdaptyUIView) { + override fun paywallViewDidAppear(view: AdaptyUIPaywallView) { // Handle paywall appearance } - override fun paywallViewDidDisappear(view: AdaptyUIView) { + override fun paywallViewDidDisappear(view: AdaptyUIPaywallView) { // Handle paywall disappearance } - override fun paywallViewDidSelectProduct(view: AdaptyUIPaywallView, productId: String) { + override fun paywallViewDidSelectProduct(view: AdaptyUIView, productId: String) { // Handle product selection } - override fun paywallViewDidStartPurchase(view: AdaptyUIView, product: AdaptyPaywallProduct) { + override fun paywallViewDidStartPurchase(view: AdaptyUIPaywallView, product: AdaptyPaywallProduct) { // Handle purchase start } - override fun paywallViewDidFinishPurchase(view: AdaptyUIView, product: AdaptyPaywallProduct, purchaseResult: AdaptyPurchaseResult) { + override fun paywallViewDidFinishPurchase(view: AdaptyUIPaywallView, product: AdaptyPaywallProduct, purchaseResult: AdaptyPurchaseResult) { // Handle purchase result } - override fun paywallViewDidFailPurchase(view: AdaptyUIView, product: AdaptyPaywallProduct, error: AdaptyError) { + override fun paywallViewDidFailPurchase(view: AdaptyUIPaywallView, product: AdaptyPaywallProduct, error: AdaptyError) { // Add your purchase failure handling logic here } - override fun paywallViewDidFinishRestore(view: AdaptyUIView, profile: AdaptyProfile) { + override fun paywallViewDidFinishRestore(view: AdaptyUIPaywallView, profile: AdaptyProfile) { // Add your successful restore handling logic here } - override fun paywallViewDidFailRestore(view: AdaptyUIView, error: AdaptyError) { + override fun paywallViewDidFailRestore(view: AdaptyUIPaywallView, error: AdaptyError) { // Add your restore failure handling logic here } - override fun paywallViewDidFinishWebPaymentNavigation(view: AdaptyUIView, product: AdaptyPaywallProduct?, error: AdaptyError?) { + override fun paywallViewDidFinishWebPaymentNavigation(view: AdaptyUIPaywallView, product: AdaptyPaywallProduct?, error: AdaptyError?) { // Handle web payment navigation result } - override fun paywallViewDidFailLoadingProducts(view: AdaptyUIView, error: AdaptyError) { + override fun paywallViewDidFailLoadingProducts(view: AdaptyUIPaywallView, error: AdaptyError) { // Add your product loading failure handling logic here } - override fun paywallViewDidFailRendering(view: AdaptyUIView, error: AdaptyError) { + override fun paywallViewDidFailRendering(view: AdaptyUIPaywallView, error: AdaptyError) { // Handle rendering error } ``` --- # End of Documentation _Generated on: 2026-06-24T14:36:28.584Z_ _Successfully processed: 50/50 files_ # REACT-NATIVE - Adapty Documentation (Full Content) This file contains the complete content of all documentation pages for this platform. Locale: ja Generated on: 2026-06-24T14:36:28.585Z Total files: 44 --- # File: sdk-installation-react-native-expo --- --- title: "ExpoプロジェクトにAdapty React Native SDKをインストール・設定する" description: "サブスクリプションアプリ向けに、ExpoプロジェクトでAdapty React Native SDKをインストールするステップバイステップガイド。" --- :::important このガイドは、**ExpoプロジェクトへのAdapty React Native SDKのインストールと設定**を説明します。 **純粋なReact Native(Expoなし)**を使用している場合は、代わりに[React Nativeインストールガイド](sdk-installation-react-native-pure)をご覧ください。 ::: Adapty SDKには、React Nativeアプリへのシームレスな統合に必要な2つの主要モジュールが含まれています: - **Core Adapty**:アプリでAdaptyを正しく動作させるために必要なモジュールです。 - **AdaptyUI**:クロスプラットフォームのペイウォールを簡単に作成できるノーコードツール[Adapty ペイウォールビルダー](adapty-paywall-builder)を使用する場合に必要なモジュールです。AdaptyUIはコアモジュールと同時に自動的に有効化されます。 React NativeアプリでIAPを実装する方法の完全なチュートリアルが必要な場合は、[こちら](https://adapty.io/blog/react-native-in-app-purchases-tutorial/)をご覧ください。 :::tip Adapty SDKがExpoアプリにどのように統合されているかの実際の例を見たい方は、サンプルアプリをご確認ください: - [Expo dev buildサンプル](https://github.com/adaptyteam/AdaptySDK-React-Native/tree/master/examples/FocusJournalExpo):実際の購入やペイウォールビルダーを含む全機能向け - [Expo Go & Webサンプル](https://github.com/adaptyteam/AdaptySDK-React-Native/tree/master/examples/ExpoGoWebMock):モックモードでのテスト向け ::: 完全な実装ウォークスルーは、以下の動画でも確認できます: <div style={{ textAlign: 'center' }}> <iframe width="560" height="315" src="https://www.youtube.com/embed/TtCJswpt2ms?si=FlFJGvpj-U33yoNK" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe> </div> ## 要件 \{#requirements\} Adapty React Native SDKはiOS 13.0以降をサポートしていますが、[Adapty ペイウォールビルダー](adapty-paywall-builder)で作成したペイウォールを使用するにはiOS 15.0以降が必要です。 :::info SDK v3.17以降、Adapty SDKはデフォルトでGoogle Play Billing Library v8.0.0を使用します。 ::: --- no_index: true --- import Callout from '../../../components/Callout.astro'; <Callout type="info"> SDKのインストールは、Adaptyセットアップのステップ5です。アプリ内で課金が機能するようにするには、アプリをストアに接続し、Adapty ダッシュボードでプロダクト、ペイウォール、プレースメントを作成する必要があります。[クイックスタートガイド](quickstart)では、必要なすべての手順を説明しています。 </Callout> ## Adapty SDKをインストールする \{#install-adapty-sdk\} [![Release](https://img.shields.io/github/v/release/adaptyteam/AdaptySDK-React-Native.svg?style=flat&logo=react)](https://github.com/adaptyteam/AdaptySDK-React-Native/releases) :::important ExpoプロジェクトでAdaptyを使用するには、[Expo Dev Client](https://docs.expo.dev/versions/latest/sdk/dev-client/)(カスタム開発ビルド)が必要です。 Expo Goはカスタムネイティブモジュールをサポートしていないため、UI/ロジックの開発には[**モックモード**](#set-up-mock-mode-for-expo-go--expo-web)でのみ使用できます(実際の購入やAdaptyUI/ペイウォールビルダーのレンダリングは不可)。 ::: 1. Adapty SDKをインストールします(`@adapty/core`も自動的にインストールされます): ```sh npx expo install react-native-adapty npx expo prebuild ``` 2. EASまたはローカルビルドを使用して開発用のアプリをビルドします: <Tabs> <TabItem value="eas" label="EAS build" default> ```sh # For iOS eas build --profile development --platform ios # For Android eas build --profile development --platform android ``` </TabItem> <TabItem value="local" label="Local build"> ```sh # For iOS npx expo run:ios # For Android npx expo run:android ``` </TabItem> </Tabs> 3. devサーバーを起動します: ```sh npx expo start --dev-client ``` ## Adapty SDKのAdaptyモジュールを有効化する \{#activate-adapty-module-of-adapty-sdk\} **Public SDK Key** を取得するには: 1. Adapty ダッシュボードを開き、[**App settings → General**](https://app.adapty.io/settings/general) に移動します。 2. **Api keys** セクションから **Public SDK Key**(Secret Key ではない方)をコピーします。 3. コード内の `"YOUR_PUBLIC_SDK_KEY"` を置き換えます。 :::important - Adapty の初期化には必ず **Public SDK key** を使用してください。**Secret key** は[サーバーサイド API](getting-started-with-server-side-api) 専用です。 - **SDK keys** はアプリごとに固有です。複数のアプリがある場合は、正しいキーを選択してください。 ::: Adaptyを有効化するために、以下のコードを`App.tsx`にコピーしてください: ```typescript showLineNumbers title="App.tsx" adapty.activate('YOUR_PUBLIC_SDK_KEY'); ``` :::important 他のAdapty SDKメソッドを呼び出す前に、`activate`の完了を待ってください。完全なシーケンスについては[React Native SDKの呼び出し順序](react-native-sdk-call-order)をご覧ください。 ::: 次に、アプリでペイウォールを設定します: - [Adapty ペイウォールビルダー](adapty-paywall-builder)を使用する場合は、[ペイウォールビルダーのクイックスタート](react-native-quickstart-paywalls)に従ってください。 - 独自のペイウォールUIを構築する場合は、[カスタムペイウォールのクイックスタート](react-native-quickstart-manual)をご覧ください。 :::tip 開発環境でのアクティベーションエラーを回避するには、[ヒント](#development-environment-tips)をご参照ください。 ::: ## Adapty SDKのAdaptyUIモジュールを有効化する \{#activate-adaptyui-module-of-adapty-sdk\} [ペイウォールビルダー](adapty-paywall-builder)を使用する場合は、AdaptyUIモジュールが必要です。コアモジュールを有効化すると自動的に有効化されるため、追加の設定は不要です。 ## オプション設定 \{#optional-setup\} ### ログ \{#logging\} #### ログシステムを設定する \{#set-up-the-logging-system\} Adaptyはエラーやその他の重要な情報をログに記録し、何が起きているかを把握できるようにします。以下のレベルが使用可能です: | レベル | 説明 | | ---------- | ------------------------------------------------------------ | | `error` | エラーのみログに記録されます | | `warn` | エラーと、重大なエラーは発生しないがSDKからの注意すべきメッセージがログに記録されます | | `info` | エラー、警告、および各種情報メッセージがログに記録されます | | `verbose` | 関数呼び出しやAPIクエリなど、デバッグ時に役立つ追加情報がすべてログに記録されます | ログレベルはAdaptyの設定前または設定中に設定できます: ```typescript showLineNumbers title="App.tsx" // Set log level before activation // 'verbose' is recommended for development and the first production release adapty.setLogLevel('verbose'); // Or set it during configuration adapty.activate('YOUR_PUBLIC_SDK_KEY', { logLevel: 'verbose', }); ``` ### データポリシー \{#data-policies\} Adaptyは明示的に送信しない限りユーザーの個人データを保存しませんが、ストアや国のガイドラインに準拠するための追加のデータセキュリティポリシーを実装できます。 #### IPアドレスの収集と共有を無効にする \{#disable-ip-address-collection-and-sharing\} Adaptyモジュールを有効化する際に、`ipAddressCollectionDisabled`を`true`に設定すると、ユーザーのIPアドレスの収集と共有を無効にできます。デフォルト値は`false`です。 このパラメータは、ユーザープライバシーの強化、地域のデータ保護規制(GDPRやCCPAなど)への準拠、またはIPベースの機能がアプリに不要な場合の不必要なデータ収集の削減に使用します。 ```typescript showLineNumbers title="App.tsx" adapty.activate('YOUR_PUBLIC_SDK_KEY', { ipAddressCollectionDisabled: true, }); ``` #### 広告IDの収集と共有を無効にする \{#disable-advertising-id-collection-and-sharing\} Adaptyモジュールを有効化する際に、`ios.idfaCollectionDisabled`(iOS)または`android.adIdCollectionDisabled`(Android)を`true`に設定すると、広告識別子の収集を無効にできます。デフォルト値は`false`です。 このパラメータは、App Store/Play Storeのポリシーへの準拠、アプリトラッキングの透明性プロンプトの回避、または広告IDに基づく広告アトリビューションや分析がアプリに不要な場合に使用します。 ```typescript showLineNumbers title="App.tsx" adapty.activate('YOUR_PUBLIC_SDK_KEY', { ios: { idfaCollectionDisabled: true, }, android: { adIdCollectionDisabled: true, }, }); ``` #### AdaptyUIのメディアキャッシュ設定をカスタマイズする \{#set-up-media-cache-configuration-for-adaptyui\} デフォルトでは、AdaptyUIはパフォーマンス向上とネットワーク使用量削減のためにメディア(画像や動画など)をキャッシュします。カスタム設定を指定してキャッシュ設定をカスタマイズできます。 `mediaCache`を使用してデフォルトのキャッシュ設定を上書きします: ```typescript adapty.activate('YOUR_PUBLIC_SDK_KEY', { mediaCache: { memoryStorageTotalCostLimit: 200 * 1024 * 1024, // Optional: memory cache size in bytes memoryStorageCountLimit: 2147483647, // Optional: max number of items in memory diskStorageSizeLimit: 200 * 1024 * 1024, // Optional: disk cache size in bytes }, }); ``` パラメータ: | パラメータ | 必須 | 説明 | |-----------|----------|-------------| | memoryStorageTotalCostLimit | 任意 | メモリ内のキャッシュ合計サイズ(バイト単位)。デフォルトはプラットフォーム固有の値。 | | memoryStorageCountLimit | 任意 | メモリストレージのアイテム数上限。デフォルトはプラットフォーム固有の値。 | | diskStorageSizeLimit | 任意 | ディスク上のファイルサイズ上限(バイト単位)。デフォルトはプラットフォーム固有の値。 | ### ローカルアクセスレベルを有効にする(Android) \{#enable-local-access-levels-android\} デフォルトでは、[ローカルアクセスレベル](local-access-levels)はiOSでは有効、Androidでは無効になっています。Androidでも有効にするには、`localAccessLevelAllowed`を`true`に設定します: ```typescript showLineNumbers title="App.tsx" adapty.activate('YOUR_PUBLIC_SDK_KEY', { android: { localAccessLevelAllowed: true, }, }); ``` ### バックアップ復元時にデータをクリアする \{#clear-data-on-backup-restore\} `clearDataOnBackup`を`true`に設定すると、SDKはアプリがiCloudバックアップから復元されたことを検知し、キャッシュされたプロファイル情報、プロダクト詳細、ペイウォールなど、ローカルに保存されているSDKデータをすべて削除します。その後SDKはクリーンな状態で初期化されます。デフォルト値は`false`です。 :::note 削除されるのはローカルSDKキャッシュのみです。Appleとのトランザクション履歴およびAdaptyサーバー上のユーザーデータは変更されません。 ::: ```typescript showLineNumbers title="App.tsx" adapty.activate('YOUR_PUBLIC_SDK_KEY', { ios: { clearDataOnBackup: true }, }); ``` ## 開発環境のヒント \{#development-environment-tips\} #### Expo Go / Expo Web向けにモックモードを設定する \{#set-up-mock-mode-for-expo-go--expo-web\} Expo GoおよびExpo Web環境では、Adaptyのネイティブモジュールにアクセスできません。ランタイムエラーを回避しながら、アプリのUIとペイウォールロジックのビルド・テストを続けられるよう、Adaptyは**モックモード**を提供しています。 ::::important モックモードは実際の購入をテストするためのツールでは**ありません**: - App Store / Google Playの購入フローを**開きません**し、実際のトランザクションを**作成しません**。 - **Adapty ペイウォールビルダー(AdaptyUI)**で作成したペイウォール/オンボーディングを**レンダリングしません**。 - Adaptyのネイティブモジュールは**完全にバイパス**されるため、Xcode/AndroidビルドにネイティブSDKファイルが存在しない場合や無効なAPIキーを使用しても、エラーは発生しません。 実際の購入とペイウォールビルダーのペイウォールをテストするには、モックモードが自動的に無効になるExpo Dev Client / プロダクションビルドを使用してください。 :::: **デフォルトでは**、SDKはExpo GoおよびWeb環境を自動的に検出してモックモードを有効にします。モックデータをカスタマイズしたい場合を除き、何も設定する必要はありません。 モックモードが有効な場合: - すべてのAdaptyメソッドはAdaptyサーバーへのネットワークリクエストを行わずにモックデータを返します。 - デフォルトでは、初期モックプロファイルにアクティブなサブスクリプションはありません。 - デフォルトでは、`makePurchase(...)`は購入成功をシミュレートし、プレミアムアクセスを付与します。 有効化時に`mockConfig`を使用してモックデータをカスタマイズできます。設定フォーマットとサポートされるパラメータは[こちら](https://react-native.adapty.io/interfaces/adaptymockconfig)でご確認ください。 ```typescript showLineNumbers title="App.tsx" try { await adapty.activate('YOUR_PUBLIC_SDK_KEY', { mockConfig: { // Customize the initial mock profile (optional) }, }); } catch (error) { console.error('Failed to activate Adapty SDK:', error); } ``` 有効化前にSDKメソッドを呼び出す必要がある場合(`isActivated()`や`setLogLevel()`など)は、`activate()`の前に`enableMock()`を使用してください。ブリッジがすでに初期化されている場合、このメソッドは何もしません。 ```typescript showLineNumbers title="App.tsx" adapty.enableMock(); // Optional: pass mockConfig to customize mock data // Now you can call methods before activation await adapty.activate('YOUR_PUBLIC_SDK_KEY'); ``` #### 開発目的でSDKの有効化を遅延させる \{#delay-sdk-activation-for-development-purposes\} AdaptyはSDK有効化時に必要なユーザーデータをすべて事前取得し、最新データへの高速アクセスを可能にします。 ただし、これはiOSシミュレーターで問題になる場合があります。iOSシミュレーターは開発中に頻繁に認証を求めることがあります。AdaptyはStoreKitの認証フローを制御できませんが、SDKが最新のユーザーデータを取得するためのリクエストを遅延させることができます。 `__debugDeferActivation`プロパティを有効にすると、次のAdapty SDKの呼び出しが行われるまでactivateの呼び出しが保留されます。これにより、認証データが不要な場合に不必要な認証プロンプトを防止できます。 **この機能は開発専用**であることに注意してください。すべての潜在的なユーザーシナリオをカバーするものではありません。本番環境では、実際のデバイスは通常認証データを記憶しており、繰り返し認証情報を求めることはないため、有効化を遅延させるべきではありません。 推奨される使用方法は以下の通りです: ```typescript showLineNumbers title="Typescript" try { adapty.activate('PUBLIC_SDK_KEY', { __debugDeferActivation: isSimulator(), // 'isSimulator' from any 3rd party library }); } catch (error) { console.error('Failed to activate Adapty SDK:', error); // Handle the error appropriately for your app } ``` #### React NativeのFast RefreshでのSDK有効化エラーのトラブルシューティング \{#troubleshoot-sdk-activation-errors-on-react-natives-fast-refresh\} React NativeでAdapty SDKを使って開発中に、次のエラーが発生することがあります:`Adapty can only be activated once. Ensure that the SDK activation call is not made more than once.` これは、React NativeのFast Refresh機能が開発中に複数回の有効化呼び出しをトリガーするために発生します。これを防ぐには、`__ignoreActivationOnFastRefresh`オプションを`__DEV__`(React Nativeの開発モードフラグ)に設定してください。 ```typescript showLineNumbers title="Typescript" try { adapty.activate('PUBLIC_SDK_KEY', { __ignoreActivationOnFastRefresh: __DEV__, }); } catch (error) { console.error('Failed to activate Adapty SDK:', error); // Handle the error appropriately for your app } ``` ## トラブルシューティング \{#troubleshooting\} #### iOSの最小バージョンエラー \{#minimum-ios-version-error\} iOSのビルド時に、**iOSの最小バージョン**またはデプロイメントターゲットに関するエラーが表示されることがあります。特に、**iOS 15.0以降**が必要な[Adapty ペイウォールビルダー](adapty-paywall-builder)で作成したペイウォールを使用する場合に発生します。 Expoは`expo prebuild`中にiOSプロジェクト(`Podfile`を含む)を生成するため、**`Podfile`を直接編集すべきではありません**。代わりに、`expo-build-properties`設定プラグインを使用してデプロイメントターゲットを設定してください。 1. プラグインをインストールします: ```sh npx expo install expo-build-properties ``` 2. Expo設定(`app.json`または`app.config.js`)を更新してiOSデプロイメントターゲットを設定します: ``` { "expo": { // ...other Expo config... "plugins": [ [ "expo-build-properties", { "ios": { // Use "13.0" for core Adapty features only, // or "15.0" if you use paywalls created in the paywall builder. "deploymentTarget": "15.0" } } ], ] } } ``` 3. ネイティブiOSプロジェクトを再生成してリビルドします: ``` npx expo prebuild --clean npx expo run:ios # or `eas build -p ios` on your CI ``` #### Android Auto Backupマニフェストの競合 \{#android-auto-backup-manifest-conflict\} ExpoでAndroid Auto Backupを設定する複数のSDK(Adapty、AppsFlyer、expo-secure-storeなど)を使用している場合、マニフェストマージの競合が発生することがあります。 典型的なエラーは次のようになります:`Manifest merger failed : Attribute application@fullBackupContent value=(@xml/secure_store_backup_rules) from AndroidManifest.xml:24:248-306 is also present at [io.adapty:android-sdk:3.12.0] AndroidManifest.xml:9:18-70 value=(@xml/adapty_backup_rules).` この競合を解決するには、AdaptyプラグインにAndroidバックアップ設定を管理させる必要があります。 プロジェクトで`expo-secure-store`も使用している場合は、重複を避けるためにそのバックアップ設定を無効にしてください。 `app.json`の設定方法は以下の通りです: ```json title="app.json" { "expo": { "plugins": [ ["react-native-adapty", { "replaceAndroidBackupConfig": true }], ["expo-secure-store", { "configureAndroidBackup": false }] ] } } ``` `replaceAndroidBackupConfig`オプションはデフォルトで`false`です。有効にすると、AdaptyプラグインがAndroidバックアップルールを管理します。 `expo-secure-store`を使用している場合は`"configureAndroidBackup": false`を含めて警告を防いでください。SecureStoreのバックアップ設定はAdaptyによって処理されます。 :::important この設定はAdapty、AppsFlyer、expo-secure-storeのバックアップ要件のみを対象としています。 プロジェクト内の他のライブラリがカスタムバックアップルールを定義している場合は、それらを手動で設定する必要があります。 ::: --- # File: sdk-installation-react-native-pure --- --- title: "純粋な React Native プロジェクトへの Adapty SDK のインストールと設定" description: "サブスクリプションアプリ向けに React Native で Adapty SDK をインストールするステップバイステップガイド。" --- :::important このガイドは**純粋な React Native(非 Expo)プロジェクト**にのみ適用されます。 **Expo** を使用している場合は、代わりに [Expo インストールガイド](sdk-installation-react-native-expo)に従ってください。 ::: Adapty SDK には、React Native アプリにシームレスに統合するための 2 つの主要モジュールが含まれています。 - **Core Adapty**: Adapty をアプリで正常に動作させるために必要なモジュールです。 - **AdaptyUI**: クロスプラットフォームのペイウォールを簡単に作成できるノーコードツール [Adapty Paywall Builder](adapty-paywall-builder) を使用する場合に必要なモジュールです。AdaptyUI はコアモジュールと同時に自動的に有効化されます。 :::tip Adapty SDK がモバイルアプリにどのように統合されているかの実例を見たいですか?ペイウォールの表示、購入、その他の基本機能を含む完全なセットアップを示す[サンプルアプリ](https://github.com/adaptyteam/AdaptySDK-React-Native/tree/master/examples)をご確認ください。 ::: ## 要件 \{#requirements\} Adapty React Native SDK は iOS 13.0 以降をサポートしていますが、[Adapty ペイウォールビルダー](adapty-paywall-builder)で作成したペイウォールを使用するには iOS 15.0 以降が必要です。 :::info SDK v3.17 以降、Adapty SDK はデフォルトで Google Play Billing Library v8.0.0 を使用します。 ::: --- no_index: true --- import Callout from '../../../components/Callout.astro'; <Callout type="info"> SDKのインストールは、Adaptyセットアップのステップ5です。アプリ内で課金が機能するようにするには、アプリをストアに接続し、Adapty ダッシュボードでプロダクト、ペイウォール、プレースメントを作成する必要があります。[クイックスタートガイド](quickstart)では、必要なすべての手順を説明しています。 </Callout> ## Adapty SDK のインストール \{#install-adapty-sdk\} [![Release](https://img.shields.io/github/v/release/adaptyteam/AdaptySDK-React-Native.svg?style=flat&logo=react)](https://github.com/adaptyteam/AdaptySDK-React-Native/releases) 1. Adapty SDK をインストールします(`@adapty/core` も自動的にインストールされます): ```sh showLineNumbers title="Shell" # using npm npm install react-native-adapty # or using yarn yarn add react-native-adapty ``` 2. iOS の場合、pods をインストールします: ```sh showLineNumbers title="Shell" cd ios && pod install ``` <details> <summary>Android で React Native のバージョンが 0.73.0 より古い場合(クリックして展開)</summary> `/android/build.gradle` ファイルを更新してください。`kotlin-gradle-plugin:1.8.0` 以降の依存関係があることを確認してください。 ```groovy showLineNumbers title="/android/build.gradle" ... buildscript { ... dependencies { ... classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.0" } } ... ``` </details> ## Adapty SDK の Adapty モジュールを有効化する \{#activate-adapty-module-of-adapty-sdk\} **Public SDK Key** を取得するには: 1. Adapty ダッシュボードを開き、[**App settings → General**](https://app.adapty.io/settings/general) に移動します。 2. **Api keys** セクションから **Public SDK Key**(Secret Key ではない方)をコピーします。 3. コード内の `"YOUR_PUBLIC_SDK_KEY"` を置き換えます。 :::important - Adapty の初期化には必ず **Public SDK key** を使用してください。**Secret key** は[サーバーサイド API](getting-started-with-server-side-api) 専用です。 - **SDK keys** はアプリごとに固有です。複数のアプリがある場合は、正しいキーを選択してください。 ::: Adapty を有効化するには、以下のコードを `App.tsx` にコピーしてください。 ```typescript showLineNumbers title="App.tsx" adapty.activate('YOUR_PUBLIC_SDK_KEY'); ``` :::important 他の Adapty SDK メソッドを呼び出す前に、`activate` が完了するまで待機してください。完全なシーケンスについては、[React Native SDK の呼び出し順序](react-native-sdk-call-order)を参照してください。 ::: 次にアプリにペイウォールを設定します。 - [Adapty Paywall Builder](adapty-paywall-builder) を使用する場合は、[ペイウォールビルダーのクイックスタート](react-native-quickstart-paywalls)に従ってください。 - 独自のペイウォール UI を構築する場合は、[カスタムペイウォールのクイックスタート](react-native-quickstart-manual)を参照してください。 :::tip 開発環境での有効化エラーを回避するには、[ヒント](#development-environment-tips)を参照してください。 ::: ## Adapty SDK の AdaptyUI モジュールを有効化する \{#activate-adaptyui-module-of-adapty-sdk\} [ペイウォールビルダー](adapty-paywall-builder)を使用する予定がある場合は、AdaptyUI モジュールが必要です。コアモジュールを有効化すると自動的に有効化されるため、追加の操作は必要ありません。 ## オプションの設定 \{#optional-setup\} ### ロギング \{#logging\} #### ロギングシステムのセットアップ \{#set-up-the-logging-system\} Adapty はエラーやその他の重要な情報をログに記録し、状況を把握するのに役立てます。以下のログレベルが利用可能です。 | レベル | 説明 | | ---------- | ------------------------------------------------------------ | | `error` | エラーのみがログに記録されます | | `warn` | エラーと、致命的なエラーを引き起こさないものの注意が必要な SDK からのメッセージがログに記録されます | | `info` | エラー、警告、各種情報メッセージがログに記録されます | | `verbose` | 関数呼び出し、API クエリなど、デバッグに役立つ追加情報がログに記録されます | Adapty の設定前または設定中にアプリでログレベルを設定できます。 ```typescript showLineNumbers title="App.tsx" // Set log level before activation // 'verbose' is recommended for development and the first production release adapty.setLogLevel('verbose'); // Or set it during configuration adapty.activate('YOUR_PUBLIC_SDK_KEY', { logLevel: 'verbose', }); ``` ### データポリシー \{#data-policies\} Adapty は明示的に送信しない限りユーザーの個人データを保存しませんが、ストアや国のガイドラインに準拠するために追加のデータセキュリティポリシーを実装できます。 #### IP アドレスの収集と共有を無効にする \{#disable-ip-address-collection-and-sharing\} Adapty モジュールを有効化する際に、`ipAddressCollectionDisabled` を `true` に設定することで、ユーザーの IP アドレスの収集と共有を無効にできます。デフォルト値は `false` です。 このパラメーターは、ユーザープライバシーの強化、地域のデータ保護規制(GDPR や CCPA など)への準拠、または IP ベースの機能がアプリに必要ない場合の不要なデータ収集の削減に使用してください。 ```typescript showLineNumbers title="App.tsx" adapty.activate('YOUR_PUBLIC_SDK_KEY', { ipAddressCollectionDisabled: true, }); ``` #### 広告 ID の収集と共有を無効にする \{#disable-advertising-id-collection-and-sharing\} Adapty モジュールを有効化する際に、`ios.idfaCollectionDisabled`(iOS)または `android.adIdCollectionDisabled`(Android)を `true` に設定することで、広告識別子の収集を無効にできます。デフォルト値は `false` です。 App Store/Play Store のポリシーに準拠する場合、App Tracking Transparency のプロンプトをトリガーしないようにする場合、またはアプリが広告 ID に基づくアトリビューションやアナリティクスを必要としない場合に、このパラメーターを使用してください。 ```typescript showLineNumbers title="App.tsx" adapty.activate('YOUR_PUBLIC_SDK_KEY', { ios: { idfaCollectionDisabled: true, }, android: { adIdCollectionDisabled: true, }, }); ``` #### AdaptyUI のメディアキャッシュ設定をセットアップする \{#set-up-media-cache-configuration-for-adaptyui\} デフォルトでは、AdaptyUI はパフォーマンス向上とネットワーク使用量の削減のためにメディア(画像や動画など)をキャッシュします。カスタム設定を指定することでキャッシュ設定をカスタマイズできます。 `mediaCache` を使用してデフォルトのキャッシュ設定を上書きします。 ```typescript adapty.activate('YOUR_PUBLIC_SDK_KEY', { mediaCache: { memoryStorageTotalCostLimit: 200 * 1024 * 1024, // Optional: memory cache size in bytes memoryStorageCountLimit: 2147483647, // Optional: max number of items in memory diskStorageSizeLimit: 200 * 1024 * 1024, // Optional: disk cache size in bytes }, }); ``` パラメーター: | パラメーター | 必須 | 説明 | |-----------|----------|-------------| | memoryStorageTotalCostLimit | オプション | メモリ内のキャッシュの合計サイズ(バイト単位)。デフォルトはプラットフォーム固有の値です。 | | memoryStorageCountLimit | オプション | メモリストレージのアイテム数の上限。デフォルトはプラットフォーム固有の値です。 | | diskStorageSizeLimit | オプション | ディスク上のファイルサイズ制限(バイト単位)。デフォルトはプラットフォーム固有の値です。 | ### ローカルアクセスレベルを有効にする(Android) \{#enable-local-access-levels-android\} デフォルトでは、[ローカルアクセスレベル](local-access-levels)は iOS で有効、Android で無効になっています。Android でも有効にするには、`localAccessLevelAllowed` を `true` に設定します。 ```typescript showLineNumbers title="App.tsx" adapty.activate('YOUR_PUBLIC_SDK_KEY', { android: { localAccessLevelAllowed: true, }, }); ``` ### バックアップ復元時のデータクリア \{#clear-data-on-backup-restore\} `clearDataOnBackup` を `true` に設定すると、SDK はアプリが iCloud バックアップから復元されたことを検出し、キャッシュされたプロファイル情報、プロダクト詳細、ペイウォールなど、ローカルに保存されているすべての SDK データを削除します。その後、SDK はクリーンな状態で初期化されます。デフォルト値は `false` です。 :::note 削除されるのはローカルの SDK キャッシュのみです。Apple とのトランザクション履歴および Adapty サーバー上のユーザーデータは変更されません。 ::: ```typescript showLineNumbers title="App.tsx" adapty.activate('YOUR_PUBLIC_SDK_KEY', { ios: { clearDataOnBackup: true }, }); ``` ## 開発環境のヒント \{#development-environment-tips\} #### 開発目的で SDK の有効化を遅延させる \{#delay-sdk-activation-for-development-purposes\} Adapty は SDK 有効化時に必要なユーザーデータをすべて事前取得し、新鮮なデータへの迅速なアクセスを可能にします。 ただし、これは開発中に頻繁に認証を求める iOS シミュレーターで問題を引き起こす可能性があります。Adapty は StoreKit の認証フローを制御できませんが、新鮮なユーザーデータを取得するための SDK リクエストを遅延させることができます。 `__debugDeferActivation` プロパティを有効にすると、次の Adapty SDK 呼び出しが行われるまで activate 呼び出しが保留されます。これにより、認証データが不要な場合の不要な認証プロンプトを防止できます。 **この機能は開発専用**であり、すべての潜在的なユーザーシナリオをカバーするわけではないことに注意してください。本番環境では有効化を遅延させるべきではありません。実際のデバイスは通常、認証データを記憶しており、繰り返し認証情報を求めることはありません。 推奨される使用方法は以下のとおりです。 ```typescript showLineNumbers title="Typescript" try { adapty.activate('PUBLIC_SDK_KEY', { __debugDeferActivation: isSimulator(), // 'isSimulator' from any 3rd party library }); } catch (error) { console.error('Failed to activate Adapty SDK:', error); // Handle the error appropriately for your app } ``` #### React Native の Fast Refresh での SDK 有効化エラーのトラブルシューティング \{#troubleshoot-sdk-activation-errors-on-react-natives-fast-refresh\} React Native で Adapty SDK を使用して開発していると、次のエラーが発生する場合があります: `Adapty can only be activated once. Ensure that the SDK activation call is not made more than once.` これは、React Native の fast refresh 機能が開発中に複数の有効化呼び出しをトリガーするために発生します。これを防ぐには、`__ignoreActivationOnFastRefresh` オプションを `__DEV__`(React Native の開発モードフラグ)に設定します。 ```typescript showLineNumbers title="Typescript" try { adapty.activate('PUBLIC_SDK_KEY', { __ignoreActivationOnFastRefresh: __DEV__, }); } catch (error) { console.error('Failed to activate Adapty SDK:', error); // Handle the error appropriately for your app } ``` #### ローカルテスト用のモックモードをセットアップする \{#set-up-mock-mode-for-local-testing\} ローカルの開発およびテストでは、サンドボックスの App Store/Google Play アカウントを必要とせずにイテレーションを高速化するためにモックモードを有効にできます。モックモードは Adapty のネイティブモジュールを完全にバイパスし、シミュレートされたデータを返します。 :::important モックモードは実際の購入をテストするためのツールでは**ありません**。 - App Store / Google Play の購入フローを**開きません**。また、実際のトランザクションを**作成しません**。 - **Adapty Paywall Builder(AdaptyUI)**で作成したペイウォール/オンボーディングを**レンダリングしません**。 - Adapty のネイティブモジュールは**完全にバイパス**されます。Xcode/Android ビルドにネイティブ SDK ファイルがなくても、無効な API キーでもエラーは発生しません。 - Adapty のサーバーにデータは送信されません。 実際の購入とペイウォールビルダーのペイウォールをテストするには、モックモードを無効にしてサンドボックスアカウントを使用してください。 ::: モックモードを有効にするには、`enableMock` を `true` に設定します。 ```typescript showLineNumbers title="App.tsx" adapty.activate('YOUR_PUBLIC_SDK_KEY', { enableMock: true, }); ``` モックモードが有効な場合: - すべての Adapty メソッドは、Adapty のサーバーへのネットワークリクエストを行わずにモックデータを返します。 - デフォルトでは、初期モックプロファイルにはアクティブなサブスクリプションがありません。 - デフォルトでは、`makePurchase(...)` は成功した購入をシミュレートし、プレミアムアクセスを付与します。 有効化時に `mockConfig` を使用してモックデータをカスタマイズできます。設定フォーマットとサポートされているパラメーターは[こちら](https://react-native.adapty.io/interfaces/adaptymockconfig)を参照してください。 ```typescript showLineNumbers title="App.tsx" try { await adapty.activate('YOUR_PUBLIC_SDK_KEY', { mockConfig: { // Customize the initial mock profile (optional) }, }); } catch (error) { console.error('Failed to activate Adapty SDK:', error); } ``` 有効化前に SDK メソッドを呼び出す必要がある場合(`isActivated()` や `setLogLevel()` など)、`activate()` の前に `enableMock()` を使用します。ブリッジがすでに初期化されている場合、このメソッドは何もしません。 ```typescript showLineNumbers title="App.tsx" adapty.enableMock(); // Optional: pass mockConfig to customize mock data // Now you can call methods before activation await adapty.activate('YOUR_PUBLIC_SDK_KEY'); ``` ## トラブルシューティング \{#troubleshooting\} #### iOS の最小バージョンエラー \{#minimum-ios-version-error\} iOS の最小バージョンエラーが発生した場合は、Podfile を更新してください。 ```diff -platform :ios, min_ios_version_supported +platform :ios, '13.0' # For core features only # OR +platform :ios, '15.0' # If using paywalls created in the paywall builder ``` #### Android Auto Backup マニフェストの競合 \{#android-auto-backup-manifest-conflict\} 一部のSDK(Adaptyを含む)には、独自のAndroid Auto Backup設定が含まれています。バックアップルールを定義する複数のSDKを使用している場合、Androidのマニフェストマージャーが `android:fullBackupContent`、`android:dataExtractionRules`、または `android:allowBackup` に関するエラーで失敗することがあります。 よくあるエラーの症状: `Manifest merger failed: Attribute application@dataExtractionRules value=(@xml/your_data_extraction_rules) is also present at [com.other.sdk:library:1.0.0] value=(@xml/other_sdk_data_extraction_rules)` :::note これらの変更は、Androidプラットフォームのディレクトリ(通常はプロジェクトの `android/` フォルダー内)で行う必要があります。 ::: この問題を解決するには、以下が必要です: - バックアップ関連の属性に対して、アプリの値を使用するようマニフェストマージャーに指示する。 - AdaptyのルールとほかのSDKのルールをマージしたバックアップルールファイルを作成する。 #### 1. マニフェストに `tools` 名前空間を追加する \{#1-add-the-tools-namespace-to-your-manifest\} `AndroidManifest.xml` ファイルのルートの `<manifest>` タグに tools が含まれていることを確認してください: ```xml <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="com.example.app"> ... </manifest> ``` #### 2. `<application>` でバックアップ属性を上書きする \{#2-override-backup-attributes-in-application\} 同じ `AndroidManifest.xml` ファイルで、`<application>` タグを更新して、アプリが最終的な値を提供し、マニフェストマージャーにライブラリの値を置き換えるよう指示します: ```xml <application android:name=".App" android:allowBackup="true" android:fullBackupContent="@xml/sample_backup_rules" android:dataExtractionRules="@xml/sample_data_extraction_rules" tools:replace="android:fullBackupContent,android:dataExtractionRules"> ... </application> ``` いずれかのSDKが `android:allowBackup` も設定している場合は、`tools:replace` に含めてください: ```xml tools:replace="android:allowBackup,android:fullBackupContent,android:dataExtractionRules" ``` #### 3. マージしたバックアップルールファイルを作成する \{#3-create-merged-backup-rules-files\} AndroidプロジェクトのAdaptyのルールとほかのSDKのルールを組み合わせた `res/xml/` ディレクトリにXMLファイルを作成します。AndroidはOSのバージョンによって異なるバックアップルール形式を使用するため、両方のファイルを作成することで、アプリがサポートするすべてのAndroidバージョンとの互換性が確保されます。 :::note 以下の例では、サンプルのサードパーティSDKとしてAppsFlyerを使用しています。アプリで使用しているほかのSDKのルールに置き換えるか、追加してください。 ::: **Android 12以降**(新しいデータ抽出ルール形式を使用): ```xml title="sample_data_extraction_rules.xml" <?xml version="1.0" encoding="utf-8"?> <data-extraction-rules> <cloud-backup> <exclude domain="sharedpref" path="appsflyer-data"/> <exclude domain="sharedpref" path="appsflyer-purchase-data"/> <exclude domain="database" path="afpurchases.db"/> <exclude domain="sharedpref" path="AdaptySDKPrefs.xml"/> </cloud-backup> <device-transfer> <exclude domain="sharedpref" path="appsflyer-data"/> <exclude domain="sharedpref" path="appsflyer-purchase-data"/> <exclude domain="database" path="afpurchases.db"/> <exclude domain="sharedpref" path="AdaptySDKPrefs.xml"/> </device-transfer> </data-extraction-rules> ``` **Android 11以前**(従来のフルバックアップコンテンツ形式を使用): ```xml title="sample_backup_rules.xml" <?xml version="1.0" encoding="utf-8"?> <full-backup-content> <exclude domain="sharedpref" path="appsflyer-data"/> <exclude domain="sharedpref" path="AdaptySDKPrefs.xml"/> #### Android で別のアプリから戻った後に購入が失敗する \{#purchases-fail-after-returning-from-another-app-in-android\} 購入フローを開始する Activity がデフォルト以外の `launchMode` を使用している場合、Google Play、銀行アプリ、またはブラウザからユーザーが戻ったときに Android が Activity を誤って再作成または再利用することがあります。これにより、購入結果が失われたり、キャンセルとして処理されたりする可能性があります。 購入が正しく機能するようにするには、購入フローを開始する Activity に `standard` または `singleTop` の起動モードのみを使用し、その他のモードを避けてください。 `AndroidManifest.xml` で、購入フローを開始する Activity が `standard` または `singleTop` に設定されていることを確認してください。 ```xml <activity android:name=".MainActivity" android:launchMode="standard" /> ``` #### Podfile の SWIFT_VERSION オーバーライドによる Swift 6 ビルドエラー \{#swift-6-build-errors-caused-by-podfile-swift_version-override\} iOS 向けに React Native アプリをビルドすると、Adapty pod ターゲットで Swift 6 のコンパイルエラーが表示される場合があります。典型的な症状としては、`AdaptyUIBuilderLogic` での `@Sendable` の不一致、Adapty 型での `Sendable` 適合の欠如、またはアクター分離エラーがあります。 Adapty pod は `s.swift_version = '6.0'` を宣言しており、Swift 6 でビルドする必要があります。アプリ自体のコードは Swift 5 のままで問題ありません。Adapty pod ターゲット(`Adapty`、`AdaptyUI`、`AdaptyUIBuilder`、`AdaptyLogger`、`AdaptyPlugin`)のみが Swift 6 でビルドされる必要があります。 最も一般的な原因は、すべての pod ターゲットに対して `SWIFT_VERSION` を書き換える `ios/Podfile` の `post_install` フックです。 ```ruby showLineNumbers title="ios/Podfile" post_install do |installer| installer.pods_project.targets.each do |target| target.build_configurations.each do |config| config.build_settings['SWIFT_VERSION'] = '5.9' end end end ``` **修正方法**: Adapty pod ターゲットをオーバーライドから除外します。 ```ruby showLineNumbers title="ios/Podfile" post_install do |installer| installer.pods_project.targets.each do |target| next if %w[Adapty AdaptyUI AdaptyUIBuilder AdaptyLogger AdaptyPlugin].include?(target.name) target.build_configurations.each do |config| config.build_settings['SWIFT_VERSION'] = '5.9' end end end ``` 次に `ios/` ディレクトリから `pod install` を実行し、再ビルドしてください。 確認するには、`ios/Pods/Pods.xcodeproj` を開き、`Adapty` pod ターゲット → **Build Settings** → **Swift Language Version** を選択してください。**Swift 6** になっているはずです。 --- # File: react-native-quickstart-paywalls --- --- title: "React Native SDKでペイウォールを使ってアプリ内課金を有効にする" description: "Adapty SDKを使ってReact NativeアプリでペイウォールをPresentする方法を学びましょう。" --- アプリ内課金を有効にするには、3つの重要な概念を理解する必要があります。 - [**プロダクト**](product) – ユーザーが購入できるもの(サブスクリプション、消耗型アイテム、永続アクセスなど) - [**ペイウォール**](paywalls) – 提供するプロダクトを定義する設定です。Adaptyでは、プロダクトを取得する唯一の方法がペイウォールですが、この設計によりアプリのコードを変更せずに、提供内容・価格・プロダクトの組み合わせを変更できます。 - [**プレースメント**](placements) – アプリ内でペイウォールを表示する場所とタイミング(`main`、`onboarding`、`settings` など)。ダッシュボードでプレースメントにペイウォールを設定し、コードではプレースメントIDを使って取得します。これにより、A/B テストの実施や、ユーザーごとに異なるペイウォールの表示が簡単にできます。 Adaptyでは、アプリ内課金を有効にする方法を3つ提供しています。アプリの要件に応じて選択してください。 | 実装方法 | 複雑さ | 使用ケース | |-------------------------------|------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Adapty ペイウォールビルダー | ✅ 簡単 | [ノーコードビルダーで完全な購入対応ペイウォールを作成](quickstart-paywalls)します。Adaptyが自動でレンダリングし、複雑な購入フロー・レシート検証・サブスクリプション管理をすべて裏側で処理します。 | | 手動作成のペイウォール | 🟡 中程度 | ペイウォールのUIはアプリのコードで実装しますが、プロダクト提供の柔軟性を維持するためにAdaptyからペイウォールオブジェクトを取得します。[ガイド](react-native-quickstart-manual)を参照してください。 | | オブザーバーモード | 🔴 難しい | 独自の購入処理インフラがすでにあり、それを引き続き使いたい場合。オブザーバーモードにはAdaptyでの制限があります。[記事](observer-vs-full-mode)を参照してください。 | :::important **以下の手順は、Adaptyペイウォールビルダーで作成したペイウォールの実装方法を示しています。** ペイウォールビルダーを使用しない場合は、[手動作成ペイウォールでの購入処理ガイド](react-native-making-purchases)を参照してください。 ::: Adaptyペイウォールビルダーで作成したペイウォールを表示するには、アプリのコードで以下の手順を実施するだけです。 1. **ペイウォールを取得する**: AdaptyからペイウォールオブジェクトをGetします。 2. **ペイウォールを表示してAdaptyに購入を処理させる**: 取得したペイウォールコンテナをアプリに表示します。 3. **ボタン操作を処理する**: ペイウォール上のユーザー操作とアプリの応答を関連付けます。例えば、ユーザーがボタンをクリックしたときにリンクを開いたりペイウォールを閉じたりします。 ## 始める前に \{#before-you-start\} 始める前に、以下の手順を完了してください。 1. Adapty ダッシュボードで[App Store](initial_ios)および/または[Google Play](initial-android)にアプリを接続します。 2. Adaptyで[プロダクトを作成](create-product)します。 3. [ペイウォールを作成してプロダクトを追加](create-paywall)します。 4. [プレースメントを作成してペイウォールを追加](create-placement)します。 5. アプリコードに[Adapty SDKをインストールして有効化](sdk-installation-reactnative)します。 :::tip これらの手順を最速で完了するには、[クイックスタートガイド](quickstart)に従うか、[Developer CLI](developer-cli-quickstart)を使ってペイウォールとプレースメントを作成してください。 ::: ## 1. ペイウォールを取得する \{#1-get-the-paywall\} ペイウォールは、ダッシュボードで設定したプレースメントに関連付けられています。プレースメントを使うと、異なるオーディエンスに別々のペイウォールを表示したり、[A/B テスト](ab-tests)を実施したりできます。 Adaptyペイウォールビルダーで作成したペイウォールを取得するには、以下の手順を実施します。 1. `getPaywall`メソッドを使って[プレースメント](placements)IDで`paywall`オブジェクトを取得し、`hasViewConfiguration`プロパティでビルダーで作成したペイウォールかどうかを確認します。 2. `createPaywallView`メソッドを使ってペイウォールビューを作成します。このビューには、ペイウォールを表示するためのUI要素とスタイリングが含まれています。 :::important ビュー設定を取得するには、ペイウォールビルダーで **Show on device** トグルをオンにする必要があります。オフの場合、空のビュー設定が返され、ペイウォールが表示されません。 ::: ```typescript showLineNumbers title="React Native" try { const placementId = 'YOUR_PLACEMENT_ID'; const paywall = await adapty.getPaywall(placementId); // the requested paywall } catch (error) { // handle the error } if (paywall.hasViewConfiguration) { try { const view = await createPaywallView(paywall); } catch (error) { // handle the error } } else { //use your custom logic } ``` ## 2. ペイウォールを表示する \{#2-display-the-paywall\} ペイウォールの設定を取得したら、数行のコードを追加するだけでペイウォールを表示できます。 <Tabs groupId="presentation-method" queryString> <TabItem value="platform" label="React component" default> 既存のコンポーネントツリーにペイウォールを埋め込むには、React Nativeコンポーネント階層に`AdaptyPaywallView`コンポーネントを直接使用します。 ```typescript showLineNumbers title="React Native (TSX)" function MyPaywall({ paywall }) { const onCloseButtonPress = useCallback<EventHandlers['onCloseButtonPress']>(() => {}, []); const onUrlPress = useCallback<EventHandlers['onUrlPress']>((url) => { Linking.openURL(url); }, []); return ( <AdaptyPaywallView paywall={paywall} style={styles.container} onCloseButtonPress={onCloseButtonPress} onUrlPress={onUrlPress} /> ); } ``` </TabItem> <TabItem value="standalone" label="Modal presentation"> ペイウォールをスタンドアロンスクリーンとして表示するには、`createPaywallView`メソッドで作成した`view`の`view.present()`メソッドを使用します。各`view`は一度しか使用できません。再度ペイウォールを表示する必要がある場合は、`createPaywallView`をもう一度呼び出して新しい`view`インスタンスを作成してください。 ```typescript showLineNumbers title="React Native" try { await view.present(); } catch (error) { // handle the error } ``` </TabItem> </Tabs> :::tip ペイウォールの表示方法の詳細については、[ガイド](react-native-present-paywalls)を参照してください。 ::: ## 3. ボタン操作を処理する \{#3-handle-button-actions\} ユーザーがペイウォール内のボタンをクリックすると、React Native SDKは購入・リストア・ペイウォールのクローズ・URLのオープンを自動で処理します。 ただし、カスタムまたは事前定義済みのIDを持つボタンについては、アプリのコードでアクションを処理する必要があります。また、デフォルトの動作をオーバーライドしたい場合もあります。 例えば、以下はクローズボタンのデフォルト動作です。コードに追加する必要はありませんが、必要な場合の実装方法を確認できます。 <Tabs groupId="presentation-method" queryString> <TabItem value="platform" label="React component" default> Reactコンポーネントの場合、`AdaptyPaywallView`コンポーネント内でアクションを直接処理します。 ```typescript showLineNumbers title="React Native (TSX)" function MyPaywall({ paywall }) { const onUrlPress = useCallback<EventHandlers['onUrlPress']>((url) => { Linking.openURL(url); }, []); const onCloseButtonPress = useCallback<EventHandlers['onCloseButtonPress']>(() => {}, []); const onCustomAction = useCallback<EventHandlers['onCustomAction']>((actionId) => {}, []); return ( <AdaptyPaywallView paywall={paywall} style={styles.container} onUrlPress={onUrlPress} onCloseButtonPress={onCloseButtonPress} onCustomAction={onCustomAction} /> ); } ``` </TabItem> <TabItem value="standalone" label="Modal presentation"> モーダル表示の場合、`setEventHandlers`を使ってイベントハンドラーを実装します。 ```typescript showLineNumbers title="React Native" const unsubscribe = view.setEventHandlers({ onCloseButtonPress() { return true; // allow paywall closing } }); ``` </TabItem> </Tabs> :::tip ボタンの[アクション](react-native-handle-paywall-actions)と[イベント](react-native-handling-events-1)の処理方法については、各ガイドを参照してください。 ::: ## 次のステップ \{#next-steps\} --- no_index: true --- import Callout from '../../../components/Callout.astro'; <Callout type="tip"> ご質問やお困りのことがあれば、[サポートフォーラム](https://adapty.featurebase.app/)をご覧ください。よくある質問への回答を見つけたり、ご自身の質問を投稿することができます。チームとコミュニティがサポートいたします! </Callout> これでアプリにペイウォールを表示する準備が整いました。[App Store サンドボックス](test-purchases-in-sandbox)または[Google Play Store](testing-on-android)でテスト購入を行い、ペイウォールからテスト購入を完了できることを確認してください。 次に、適切なユーザーにペイウォールを表示したり有料機能へのアクセスを付与したりするために、[ユーザーのアクセスレベルを確認](react-native-check-subscription-status)する必要があります。 ## 完全なサンプル \{#full-example\} すべての手順をアプリに統合した例を以下に示します。 <Tabs groupId="presentation-method" queryString> <TabItem value="platform" label="React component" default> ```javascript showLineNumbers title="React Native (TSX)" export default function PaywallScreen() { const [paywall, setPaywall] = useState(null); const loadPaywall = async () => { try { const paywallData = await adapty.getPaywall('YOUR_PLACEMENT_ID'); if (paywallData.hasViewConfiguration) { setPaywall(paywallData); } } catch (error) { console.warn('Error loading paywall:', error); } }; const onUrlPress = useCallback<EventHandlers['onUrlPress']>((url) => { Linking.openURL(url); }, []); const onCloseButtonPress = useCallback<EventHandlers['onCloseButtonPress']>(() => { // Handle close button press }, []); useEffect(() => { loadPaywall(); }, []); return ( <View style={{ flex: 1 }}> {paywall ? ( <AdaptyPaywallView paywall={paywall} style={{ flex: 1 }} onUrlPress={onUrlPress} onCloseButtonPress={onCloseButtonPress} /> ) : ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Button title="Load Paywall" onPress={loadPaywall} /> </View> )} </View> ); } ``` </TabItem> <TabItem value="standalone" label="Modal presentation"> ```javascript showLineNumbers title="React Native" export default function PaywallScreen() { const showPaywall = async () => { try { const paywall = await adapty.getPaywall('YOUR_PLACEMENT_ID'); if (!paywall.hasViewConfiguration) { // use your custom logic return; } const view = await createPaywallView(paywall); view.setEventHandlers({ onCloseButtonPress() { return true; }, }); await view.present(); } catch (error) { // handle any error that may occur during the process console.warn('Error showing paywall:', error); } }; // you can add a button to manually trigger the paywall for testing purposes return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Button title="Show Paywall" onPress={showPaywall} /> </View> ); } ``` </TabItem> </Tabs> --- # File: react-native-check-subscription-status --- --- title: "React Native SDKでサブスクリプションステータスを確認する" description: "AdaptyでReact Nativeアプリのサブスクリプションステータスを確認する方法を学びましょう。" --- ユーザーが有料コンテンツにアクセスできるか、またはペイウォールを表示すべきかを判断するには、プロファイルの[アクセスレベル](access-level)を確認する必要があります。 この記事では、プロファイルの状態にアクセスして、ユーザーにペイウォールを表示するか有料機能へのアクセスを許可するかを判断する方法を説明します。 ## サブスクリプションステータスを取得する \{#get-subscription-status\} ペイウォールを表示するか有料コンテンツを表示するかを決める際は、プロファイル内のユーザーの[アクセスレベル](access-level)を確認します。2つの方法があります: - 最新のプロファイルデータがすぐに必要な場合(アプリ起動時など)や強制的に更新したい場合は、`getProfile` を呼び出す。 - **自動プロファイル更新**を設定して、サブスクリプションステータスが変わるたびに自動で更新されるローカルコピーを保持する。 ### プロファイルを取得する \{#get-profile\} サブスクリプションステータスを取得する最も簡単な方法は、`getProfile` メソッドでプロファイルにアクセスすることです: ```typescript showLineNumbers try { const profile = await adapty.getProfile(); } catch (error) { // handle the error } ``` ### サブスクリプション更新を購読する \{#listen-to-subscription-updates\} アプリでプロファイルの更新を自動的に受け取るには: 1. `adapty.addEventListener('onLatestProfileLoad')` を使ってプロファイルの変更を監視します。ユーザーのサブスクリプションステータスが変わるたびに、Adaptyが自動的にこのメソッドを呼び出します。 2. このメソッドが呼び出されたときに更新されたプロファイルデータを保存しておくと、追加のネットワークリクエストなしにアプリ全体で利用できます。 ```javascript class SubscriptionManager { private currentProfile: any = null; constructor() { // Listen for profile updates adapty.addEventListener('onLatestProfileLoad', (profile) => { this.currentProfile = profile; // Update UI, unlock content, etc. }); } // Use stored profile instead of calling getProfile() hasAccess(): boolean { return this.currentProfile?.accessLevels?.['premium']?.isActive ?? false; } } ``` :::note Adaptyはアプリ起動時に `onLatestProfileLoad` イベントリスナーを自動的に呼び出し、デバイスがオフラインの場合でもキャッシュされたサブスクリプションデータを提供します。 ::: ## プロファイルとペイウォールのロジックを連携させる \{#connect-profile-with-paywall-logic\} ペイウォールの表示や有料機能へのアクセス許可をすぐに判断する必要がある場合は、ユーザーのプロファイルを直接確認できます。この方法は、アプリ起動時、プレミアムセクションへの移動時、特定コンテンツの表示前などのシナリオで役立ちます。 ```javascript const checkAccessLevel = async () => { try { const profile = await adapty.getProfile(); return profile.accessLevels['YOUR_ACCESS_LEVEL']?.isActive === true; } catch (error) { console.warn('Error checking access level:', error); return false; // Show paywall if access check fails } }; const initializePaywall = async () => { try { await loadPaywall(); const hasAccess = await checkAccessLevel(); if (!hasAccess) { // Show paywall if no access } } catch (error) { console.warn('Error initializing paywall:', error); } }; ``` ## 次のステップ \{#next-steps\} サブスクリプションステータスの追跡方法がわかったら、ユーザーが支払済みのコンテンツにアクセスできるよう[ユーザープロファイルの操作](react-native-quickstart-identify)について学びましょう。 --- # File: react-native-quickstart-identify --- --- title: "React Native SDKでユーザーを識別する" description: "React NativeでAdaptyを使ったアプリ内サブスクリプション管理のクイックスタートガイド。" --- :::important このガイドは、独自の認証システムを持っている方向けです。ここでは、Adaptyでユーザープロファイルを管理し、既存の認証システムと連携させる方法を説明します。 ::: ユーザーの購入をどのように管理するかは、アプリの認証モデルによって異なります。 - アプリがバックエンド認証を使用せず、ユーザーデータを保存しない場合は、[匿名ユーザーのセクション](#anonymous-users)を参照してください。 - アプリにバックエンド認証がある(または導入予定の)場合は、[識別済みユーザーのセクション](#identified-users)を参照してください。 **主要な概念**: - **プロファイル**はSDKが動作するために必要なエンティティで、Adaptyが自動的に作成します。 - プロファイルは匿名**(カスタマーユーザーIDなし)**または識別済み**(カスタマーユーザーIDあり)**のいずれかです。 - **カスタマーユーザーID**を提供することで、AdaptyのプロファイルとあなたのシステムのIDを紐付けられます。 匿名ユーザーと識別済みユーザーの違いは以下の通りです: | | 匿名ユーザー | 識別済みユーザー | |-------------------------|---------------------------------------------------|-------------------------------------------------------------------------| | **購入管理** | ストアレベルの購入復元 | カスタマーユーザーIDを通じてデバイスをまたいで購入履歴を維持 | | **プロファイル管理** | 再インストールのたびに新しいプロファイルが作成される | セッションやデバイスをまたいで同じプロファイルを使用 | | **データの永続性** | 匿名ユーザーのデータはアプリのインストールに紐付く | 識別済みユーザーのデータはアプリのインストールをまたいで保持される | ## 匿名ユーザー \{#anonymous-users\} バックエンド認証がない場合、**アプリのコードで認証処理を行う必要はありません**: 1. アプリの初回起動時にSDKが有効化されると、AdaptyはそのユーザーのためにNew プロファイルを**作成**します。 2. ユーザーがアプリ内で何か購入すると、その購入は**Adaptyプロファイルとストアアカウントに紐付けられます**。 3. ユーザーがアプリを**再インストール**したり、**新しいデバイス**にインストールしたりすると、Adaptyは有効化時に**新しい匿名プロファイルを作成**します。 4. ユーザーがそれ以前にアプリで購入していた場合、デフォルトではSDK有効化時にApp Storeから購入履歴が自動的に同期されます。 匿名ユーザーの場合、インストールのたびに新しいプロファイルが作成されますが、Adaptyアナリティクスでは[新規インストールとみなす基準を設定](general#4-installs-definition-for-analytics)できるため、問題にはなりません。 :::note バックアップからの復元は、再インストールとは異なる動作をします。デフォルトでは、ユーザーがバックアップから復元する際、SDKはキャッシュされたデータを保持し、新しいプロファイルを作成しません。この動作は`clearDataOnBackup`設定で変更できます。[詳細を確認する](sdk-installation-react-native-pure#clear-data-on-backup-restore)。 ::: 匿名ユーザーの場合、**デバイスID**に基づいてインストール数をカウントします。この場合、再インストールを含め、デバイス上のアプリインストールがそれぞれ1回のインストールとしてカウントされます。 ## 識別済みユーザー \{#identified-users\} ユーザーを識別する方法は2つあります: - [**ログイン/サインアップ時:**](#during-loginsignup) アプリ起動後にユーザーがサインインする場合、認証時に`identify()`をカスタマーユーザーIDと共に呼び出します。 - [**SDKの有効化時:**](#during-the-sdk-activation) アプリ起動時にカスタマーユーザーIDがすでに保存されている場合、`activate()`呼び出し時にそれを渡します。 :::important デフォルトでは、あるカスタマーユーザーIDから購入が発生した際、そのIDが別のカスタマーユーザーIDに紐付いていても、アクセスレベルは共有されます。つまり、両方のプロファイルが有料アクセスを持ちます。この設定を変更して、一方のプロファイルから他方へアクセスを移譲したり、共有を無効にしたりすることもできます。詳細は[こちらの記事](general#6-sharing-paid-access-between-user-accounts)を参照してください。 ::: <img src="/assets/shared/img/identify-diagram.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### ログイン/サインアップ時 \{#during-loginsignup\} アプリ起動後にユーザーを識別する場合(例:ログインやサインアップ後)、`identify`メソッドを使ってカスタマーユーザーIDを設定します。 - **このカスタマーユーザーIDを初めて使う場合**、Adaptyは自動的に現在のプロファイルに紐付けます。 - **以前にこのカスタマーユーザーIDでユーザーを識別したことがある場合**、Adaptyはそのカスタマーユーザーに紐付いたプロファイルへ切り替えます。 :::important カスタマーユーザーIDはユーザーごとに一意である必要があります。パラメータの値をハードコードすると、すべてのユーザーが同一人物とみなされます。 ::: 他のSDKメソッドを呼び出す前に、必ず`identify`を`await`してください。並列呼び出しを行うと`#3006 profileWasChanged`が発生したり、匿名プロファイルに対して操作が行われる場合があります。詳しくは[React Native SDKの呼び出し順序](react-native-sdk-call-order)を参照してください。 ```typescript showLineNumbers try { await adapty.identify("YOUR_USER_ID"); // Unique for each user // successfully identified } catch (error) { // handle the error } ``` ### SDKの有効化時 \{#during-the-sdk-activation\} SDKを有効化する時点でカスタマーユーザーIDが既にわかっている場合、`identify`を別途呼び出さずに`activate`メソッドに渡すことができます。 カスタマーユーザーIDがわかっているにもかかわらず、有効化後にのみ設定した場合、有効化時にAdaptyは新しい匿名プロファイルを作成し、`identify`を呼び出した後にのみ既存のプロファイルに切り替わります。 既存のカスタマーユーザーID(以前に使用したもの)または新しいものを渡すことができます。新しいものを渡した場合、有効化時に作成される新しいプロファイルが自動的にそのカスタマーユーザーIDに紐付けられます。 :::note デフォルトでは、匿名プロファイルの作成はアナリティクスダッシュボードに影響しません。インストールはデバイスIDに基づいてカウントされるためです。 デバイスIDはストアからデバイスへのアプリの1回のインストールを表し、アプリの再インストール後にのみ再生成されます。 初回インストールか再インストールかや、既存のカスタマーユーザーIDを使用するかどうかには依存しません。 プロファイルの作成(SDK有効化時またはログアウト時)、ログイン、または再インストールなしのアプリアップグレードでは、追加のインストールイベントは発生しません。 インストールをデバイスではなく一意のユーザーに基づいてカウントしたい場合は、**App settings**で[**Installs definition for analytics**](general#4-installs-definition-for-analytics)を設定してください。 ::: ```typescript showLineNumbers adapty.activate("PUBLIC_SDK_KEY", { customerUserId: "YOUR_USER_ID" // Customer user IDs must be unique for each user. If you hardcode the parameter value, all users will be considered as one. }); ``` ### ユーザーをログアウトさせる \{#log-users-out\} ユーザーのログアウトボタンがある場合は、`logout`メソッドを使用します。 :::important ユーザーのログアウト時に、新しい匿名プロファイルが作成されます。 ::: ```typescript showLineNumbers try { await adapty.logout(); // successful logout } catch (error) { // handle the error } ``` :::info ユーザーをアプリに再度ログインさせるには、`identify`メソッドを使用してください。 ::: ### ログインなしで購入を許可する \{#allow-purchases-without-login\} ユーザーがログイン前後の両方で購入できる場合、ログイン後もアクセスが維持されるよう対応が必要です: 1. ログアウト状態のユーザーが購入を行うと、AdaptyはそれをそのユーザーのプロファイルIDに紐付けます。 2. ユーザーがアカウントにログインすると、Adaptyは識別済みプロファイルに切り替えます。 - 新しいカスタマーユーザーID(例:登録前に購入が行われた場合)の場合、Adaptyはそのカスタマーユーザーを現在のプロファイルに割り当て、購入履歴が引き継がれます。 - 既存のカスタマーユーザーID(すでにプロファイルに紐付いている)の場合、プロファイル切り替え後に実際のアクセスレベルを取得する必要があります。識別後すぐに[`getProfile`](react-native-check-subscription-status)を呼び出すか、[プロファイルの更新をリッスン](react-native-check-subscription-status)してデータを自動的に同期させてください。 ## 次のステップ \{#next-steps\} おめでとうございます!アプリにアプリ内課金のロジックを実装できました。アプリの収益化を成功させてください! Adaptyをさらに活用するために、以下のトピックもご確認ください: - [**テスト**](troubleshooting-test-purchases):すべてが期待通りに動作することを確認する - [**オンボーディング**](react-native-onboardings):オンボーディングでユーザーを引き付けてリテンションを向上させる - [**インテグレーション**](configuration):マーケティングアトリビューションや分析サービスをわずか1行のコードで連携する - [**カスタムプロファイル属性の設定**](react-native-setting-user-attributes):ユーザープロファイルにカスタム属性を追加してセグメントを作成し、A/Bテストを実施したり、ユーザーごとに異なるペイウォールを表示したりする --- # File: adapty-sdk-integration-skill-react-native --- --- title: "SDKインテグレーションスキルを使ってAdaptyをReact Nativeアプリに統合する" description: "adapty-sdk-integrationスキルを使用して、AIコーディングツールでAdapty SDKをReact Nativeアプリにエンドツーエンドで統合します。" --- :::important このスキルはベータ版です。処理が止まったり予期しない動作が発生した場合は、代わりに[ステップバイステップの統合ガイド](adapty-cursor-react-native)を参照してください。AIツールを各ステージで適切なドキュメントに沿って案内します。 ::: --- no_index: true --- [adapty-sdk-integration スキル](https://github.com/adaptyteam/adapty-sdk-integration-skill)は、Adapty のインテグレーションをエンドツーエンドで自動化します。ダッシュボードのセットアップ、SDK のインストール、ペイウォール、各ステージの検証まで対応しています。プラットフォームを自動検出し、各ステージで関連する Adapty ドキュメントを取得します。 **対応ツール**: Claude Code、GitHub Copilot CLI、OpenAI Codex、Gemini CLI。 インストールするには、お使いのツール向けのフォームを選択してください。完全なリストは[スキルの README](https://github.com/adaptyteam/adapty-sdk-integration-skill) をご覧ください。 **Claude Code** ``` claude plugin marketplace add adaptyteam/adapty-sdk-integration-skill claude plugin install adapty-sdk-integration@adapty ``` **GitHub Copilot CLI** ``` gh skill install adaptyteam/adapty-sdk-integration-skill ``` **Gemini CLI** ``` gemini skills install https://github.com/adaptyteam/adapty-sdk-integration-skill ``` **OpenAI Codex またはその他のツール**: リポジトリをクローンし、`plugins/adapty-sdk-integration/skills/adapty-sdk-integration/` をツールのスキルディレクトリにコピーしてください。 インストール後、プロジェクト内でスキルを実行します: ``` /adapty-sdk-integration ``` スキルがいくつかのセットアップ質問を行い、その後ダッシュボードのセットアップ、SDK のインストール、ペイウォール、検証の手順を案内します。 --- # File: adapty-cursor-react-native --- --- title: "AIアシスタントを使ってAdaptyをReact Nativeアプリに統合する" description: "Cursor、Context7、ChatGPT、Claude、その他のAIツールを使って、AdaptyをReact Nativeアプリに統合するためのステップバイステップガイド。" --- このガイドでは、AIコーディングツールを使いながら、AdaptyをReact Nativeアプリに順を追って統合していきます。必要なAdaptyのドキュメントを正しい順番でAIに渡してください。 For a fully automated integration, use the [adapty-sdk-integration skill](https://github.com/adaptyteam/adapty-sdk-integration-skill): it runs the whole integration from your AI coding tool in one command. ## 始める前に:ダッシュボードの設定 \{#before-you-start-dashboard-setup\} AdaptyでSDKのコードを書く前に、ダッシュボードでいくつかの設定が必要です。インタラクティブなLLMスキルを使うか、ダッシュボードから手動で行うかを選べます。 ### スキルを使う方法(推奨)\{#skill-approach-recommended\} Adapty CLIスキルを使うと、LLMがダッシュボードを開かずに、アプリ・プロダクト・アクセスレベル・ペイウォール・プレースメントを直接設定できます。必要なのは、ダッシュボードで[ストアを連携する](integrate-payments)ことだけです。 ``` npx skills add adaptyteam/adapty-cli --skill adapty-cli ``` スキルを追加したら、エージェントで `/adapty-cli` を実行してください。ストアの連携でダッシュボードを開くタイミングも含め、各ステップをガイドしてくれます。 ### ダッシュボードを使う方法 \{#dashboard-approach\} 手動で設定したい場合は、コードを書く前に以下の準備が必要です。LLMはダッシュボードの値を自動で取得できないため、自分で用意する必要があります。 1. **ストアを連携する**:Adapty ダッシュボードで **App settings → General** を開き、両プラットフォームを対象とする場合はApp StoreとGoogle Playの両方を連携してください。課金を機能させるために必須です。 [ストアを連携する](integrate-payments) 2. **Public SDKキーをコピーする**:Adapty ダッシュボードで **App settings → General** を開き、**API keys** セクションを確認します。コード内では、`adapty.activate("YOUR_PUBLIC_SDK_KEY")` に渡す文字列です。 3. **プロダクトを1つ以上作成する**:Adapty ダッシュボードで **Products** ページを開いてください。コード内でプロダクトを直接参照することはありません — Adaptはペイウォールを通じてプロダクトを提供します。 [プロダクトを追加する](quickstart-products) 4. **ペイウォールとプレースメントを作成する**:Adapty ダッシュボードで **Paywalls** ページにペイウォールを作成し、**Placements** ページでプレースメントに割り当ててください。コード内では、`adapty.getPaywall("YOUR_PLACEMENT_ID")` に渡すプレースメントIDを使います。 [ペイウォールを作成する](quickstart-paywalls) 5. **アクセスレベルを設定する**:Adapty ダッシュボードで **Products** ページの各プロダクトに設定します。コード内では `profile.accessLevels['premium']?.isActive` で確認する文字列です。デフォルトの `premium` アクセスレベルはほとんどのアプリで問題ありません。プロダクトによって異なる機能(例:`basic` プランと `pro` プラン)をユーザーに提供する場合は、コーディングを始める前に[追加のアクセスレベルを作成](assigning-access-level-to-a-product)してください。 :::tip 5つの準備が整ったら、コードを書き始められます。「Public SDKキーはXで、プレースメントIDはY」とLLMに伝えると、正しい初期化コードとペイウォール取得コードを生成してもらえます。 ::: ### 準備ができたら設定するもの \{#set-up-when-ready\} コーディングを始める前に必須ではありませんが、統合が進むにつれて必要になります: - **A/B テスト**:**Placements** ページで設定します。コードの変更は不要です。 [A/B テスト](ab-tests) - **追加のペイウォールとプレースメント**:異なるプレースメントIDで `getPaywall` の呼び出しを追加します。 - **アナリティクス連携**:**Integrations** ページで設定します。設定方法は連携先によって異なります。[アナリティクス連携](analytics-integration)と[アトリビューション連携](attribution-integration)を参照してください。 ## LLMにAdaptyのドキュメントを渡す \{#feed-adapty-docs-to-your-llm\} ### Context7を使う方法(推奨)\{#use-context7-recommended\} [Context7](https://context7.com)は、LLMが最新のAdaptyドキュメントに直接アクセスできるMCPサーバーです。質問内容に応じて適切なドキュメントを自動で取得するため、URLを手動で貼り付ける必要がありません。 Context7は**Cursor**、**Claude Code**、**Windsurf**、その他のMCP対応ツールで動作します。セットアップするには以下を実行してください: ``` npx ctx7 setup ``` エディタを自動検出してContext7サーバーを設定します。手動セットアップの方法は[Context7のGitHubリポジトリ](https://github.com/upstash/context7)を参照してください。 設定が完了したら、プロンプト内でAdaptyライブラリを参照します: ``` Use the adaptyteam/adapty-docs library to look up how to install the React Native SDK ``` :::warning Context7を使えばドキュメントのURLを手動で貼り付ける必要はなくなりますが、実装の順序は重要です。すべてが正しく動作するよう、以下の[実装ウォークスルー](#implementation-walkthrough)をステップごとに進めてください。 ::: ### プレーンテキストのドキュメントを使う方法 \{#use-plain-text-docs\} AdaptyのドキュメントはプレーンテキストのMarkdownとして取得できます。URLの末尾に `.md` を追加するか、記事タイトルの下にある **Copy for LLM** をクリックしてください。例:[adapty-cursor-react-native.md](https://adapty.io/docs/ja/adapty-cursor-react-native.md) 以下の[実装ウォークスルー](#implementation-walkthrough)の各ステップには、貼り付け用の `.md` リンクが入った「LLMに送るプロンプト」ブロックが含まれています。 より多くのドキュメントを一度に渡したい場合は、以下の[インデックスファイルとプラットフォーム別サブセット](#plain-text-doc-index-files)を参照してください。 ## 実装ウォークスルー \{#implementation-walkthrough\} ここからは、Adaptyの統合を実装順に進めていきます。各ステップには、LLMに渡すドキュメント、完了時の確認事項、よくある問題が記載されています。 ### 統合の計画を立てる \{#plan-your-integration\} コードを書く前に、LLMにプロジェクトを分析させて実装計画を作成させてください。AIツールがプランニングモード(CursorやClaude Codeのプランモードなど)をサポートしている場合は、コードを書く前にLLMがプロジェクト構成とAdaptyのドキュメントの両方を読めるよう、そのモードを使用してください。 購入の処理方法をLLMに伝えてください — これによって参照すべきガイドが変わります: - [**Adapty ペイウォールビルダー**](adapty-paywall-builder):Adaptyのノーコードビルダーでペイウォールを作成し、SDKが自動でレンダリングします。 - [**手動で作成したペイウォール**](react-native-making-purchases):コードで独自のペイウォールUIを構築しつつ、プロダクトの取得と購入処理にAdaptyを使います。 - [**オブザーバーモード**](observer-vs-full-mode):既存の購入インフラをそのまま使い、Adaptyはアナリティクスと連携にのみ使用します。 どれを選ぶか迷ったら、[クイックスタートの比較表](react-native-quickstart-paywalls)を参照してください。 ### SDKのインストールと設定 \{#install-and-configure-the-sdk\} npm(またはyarn)でAdapty SDKの依存関係を追加し、Public SDKキーで有効化します。これが基盤となるため、ここが機能しないと他のすべてが動作しません。 ExpoとベアのReact Nativeプロジェクトでは別々のインストールガイドがあります — 自分のセットアップに合ったものを選んでください。 **ガイド:** - [Expoでインストールする](sdk-installation-react-native-expo) - [ベアReact Nativeでインストールする](sdk-installation-react-native-pure) LLMに送るプロンプト(セットアップに合ったものを選ぶか、両方送ってください): ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/sdk-installation-react-native-expo.md - https://adapty.io/docs/ja/sdk-installation-react-native-pure.md ``` :::tip[チェックポイント] - **確認事項:** アプリがiOSとAndroidの両方でビルドおよび実行できること。Metroバンドラーのログにアクティベーションログが表示されること。 - **注意点:** 「Public API key is missing」が表示される場合 → プレースホルダーをApp settingsの実際のキーに置き換えたか確認してください。 ::: ### ペイウォールの表示と購入処理 \{#show-paywalls-and-handle-purchases\} プレースメントIDでペイウォールを取得し、表示して、購入イベントを処理します。必要なガイドは購入の処理方法によって異なります。 進めながらサンドボックスで各購入をテストしてください — 最後まで待たずに行うことをお勧めします。設定方法は[サンドボックスで購入をテストする](test-purchases-in-sandbox)を参照してください。 <Tabs groupId="paywall-approach"> <TabItem value="builder" label="Paywall Builder" default> **ガイド:** - [ペイウォールを使って購入を有効にする(クイックスタート)](react-native-quickstart-paywalls) - [ペイウォールビルダーのペイウォールと設定を取得する](react-native-get-pb-paywalls) - [ペイウォールを表示する](react-native-present-paywalls) - [ペイウォールのイベントを処理する](react-native-handling-events-1) - [ボタンアクションに応答する](react-native-handle-paywall-actions) LLMに送るプロンプト: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/react-native-quickstart-paywalls.md - https://adapty.io/docs/ja/react-native-get-pb-paywalls.md - https://adapty.io/docs/ja/react-native-present-paywalls.md - https://adapty.io/docs/ja/react-native-handling-events-1.md - https://adapty.io/docs/ja/react-native-handle-paywall-actions.md ``` :::tip[チェックポイント] - **確認事項:** 設定したプロダクトとともにペイウォールが表示されること。プロダクトをタップするとサンドボックス購入ダイアログが表示されること。 - **注意点:** ペイウォールが空、または `getPaywall` エラーが出る場合 → プレースメントIDがダッシュボードと完全に一致しているか、プレースメントにオーディエンスが割り当てられているかを確認してください。 ::: </TabItem> <TabItem value="manual" label="Manual paywalls"> **ガイド:** - [カスタムペイウォールで購入を有効にする(クイックスタート)](react-native-quickstart-manual) - [ペイウォールとプロダクトを取得する](fetch-paywalls-and-products-react-native) - [リモートコンフィグで設計したペイウォールをレンダリングする](present-remote-config-paywalls-react-native) - [購入を処理する](react-native-making-purchases) - [購入を復元する](react-native-restore-purchase) LLMに送るプロンプト: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/react-native-quickstart-manual.md - https://adapty.io/docs/ja/fetch-paywalls-and-products-react-native.md - https://adapty.io/docs/ja/present-remote-config-paywalls-react-native.md - https://adapty.io/docs/ja/react-native-making-purchases.md - https://adapty.io/docs/ja/react-native-restore-purchase.md ``` :::tip[チェックポイント] - **確認事項:** カスタムペイウォールにAdaptyから取得したプロダクトが表示されること。プロダクトをタップするとサンドボックス購入ダイアログが表示されること。 - **注意点:** プロダクト配列が空の場合 → ダッシュボードでペイウォールにプロダクトが割り当てられているか、プレースメントにオーディエンスが設定されているかを確認してください。 ::: </TabItem> <TabItem value="observer" label="Observer mode"> **ガイド:** - [オブザーバーモードの概要](observer-vs-full-mode) - [オブザーバーモードを実装する](implement-observer-mode-react-native) - [オブザーバーモードでトランザクションを報告する](report-transactions-observer-mode-react-native) LLMに送るプロンプト: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/observer-vs-full-mode.md - https://adapty.io/docs/ja/implement-observer-mode-react-native.md - https://adapty.io/docs/ja/report-transactions-observer-mode-react-native.md ``` :::tip[チェックポイント] - **確認事項:** 既存の購入フローでサンドボックス購入を行った後、Adapty ダッシュボードの **Event Feed** にトランザクションが表示されること。 - **注意点:** イベントが表示されない場合 → Adaptyにトランザクションを報告しているか、両方のストアでサーバー通知が設定されているかを確認してください。 ::: </TabItem> </Tabs> ### サブスクリプション状態を確認する \{#check-subscription-status\} 購入後、ユーザープロファイルのアクセスレベルがアクティブかどうかを確認してプレミアムコンテンツの表示を制限します。 **ガイド:** [サブスクリプション状態を確認する](react-native-check-subscription-status) LLMに送るプロンプト: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/react-native-check-subscription-status.md ``` :::tip[チェックポイント] - **確認事項:** サンドボックス購入後、`profile.accessLevels['premium']?.isActive` が `true` を返すこと。 - **注意点:** 購入後に `accessLevels` が空の場合 → ダッシュボードでプロダクトにアクセスレベルが割り当てられているかを確認してください。 ::: ### ユーザーを識別する \{#identify-users\} アプリのユーザーアカウントをAdaptyのプロファイルに紐づけて、複数のデバイスをまたいで購入を継続させます。 :::important アプリに認証機能がない場合は、このステップをスキップしてください。 ::: **ガイド:** [ユーザーを識別する](react-native-quickstart-identify) LLMに送るプロンプト: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/react-native-quickstart-identify.md ``` :::tip[チェックポイント] - **確認事項:** `adapty.identify("your-user-id")` を呼び出した後、ダッシュボードの **Profiles** セクションにカスタムユーザーIDが表示されること。 - **注意点:** 匿名プロファイルのアトリビューションを避けるため、アクティベーション後、ペイウォールの取得前に `identify` を呼び出してください。 ::: ### リリース準備をする \{#prepare-for-release\} サンドボックスでの統合が正常に動作したら、リリースチェックリストを確認して本番環境の準備が整っているか確認してください。 **ガイド:** [リリースチェックリスト](release-checklist) LLMに送るプロンプト: ``` Read these Adapty docs before releasing: - https://adapty.io/docs/ja/release-checklist.md ``` :::tip[チェックポイント] - **確認事項:** チェックリストの全項目が確認済みであること:ストアの連携、サーバー通知、購入フロー、アクセスレベルの確認、プライバシー要件。 - **注意点:** サーバー通知が設定されていない場合 → **App settings → iOS SDK** でApp Store サーバー通知を設定し、**App settings → Android SDK** でGoogle Play リアルタイム デベロッパー通知を設定してください。 ::: ## プレーンテキストのドキュメントインデックスファイル \{#plain-text-doc-index-files\} 個別ページを超えた広いコンテキストをLLMに提供したい場合、Adaptyの全ドキュメントをリスト化・統合したインデックスファイルを用意しています: - [`llms.txt`](https://adapty.io/docs/ja/llms.txt):`.md` リンク付きで全ページをリスト化。LLMがウェブサイトにアクセスしやすくするための[新しいスタンダード](https://llmstxt.org/)です。一部のAIエージェント(例:ChatGPT)では、`llms.txt` をダウンロードしてチャットにファイルとしてアップロードする必要があります。 - [`llms-full.txt`](https://adapty.io/docs/ja/llms-full.txt):Adaptyの全ドキュメントを1つのファイルにまとめたもの。非常に大きいファイルのため、全体像が必要な場合にのみ使用してください。 - React Native専用の [`react-native-llms.txt`](https://adapty.io/docs/ja/react-native-llms.txt) と [`react-native-llms-full.txt`](https://adapty.io/docs/ja/react-native-llms-full.txt):サイト全体と比べてトークン数を節約できるプラットフォーム別のサブセットです。 --- # File: react-native-get-pb-paywalls --- --- title: "React Native SDKでペイウォールビルダーのペイウォールと設定を取得する" description: "Adapty for React NativeアプリでPBペイウォールを取得し、サブスクリプション管理を改善する方法をご紹介します。" --- Adapty ダッシュボードの新しいペイウォールビルダーで[ペイウォールのビジュアルデザインを作成](adapty-paywall-builder)したら、モバイルアプリに表示できます。最初のステップは、プレースメントに関連付けられたペイウォールとそのビュー設定を取得することです。詳細は以下をご覧ください。 :::warning 新しいペイウォールビルダーは React Native SDK バージョン 3.0 以上で動作します。 ::: このトピックはペイウォールビルダーでカスタマイズしたペイウォールに関するものです。ペイウォールを手動で実装する場合は、[モバイルアプリのリモートコンフィグペイウォール向けにペイウォールとプロダクトを取得する](fetch-paywalls-and-products-react-native)をご参照ください。 :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: <details> <summary>モバイルアプリでペイウォールを表示する前に(クリックして展開)</summary> 1. Adapty ダッシュボードで[プロダクトを作成](create-product)します。 2. Adapty ダッシュボードで[ペイウォールを作成し、プロダクトを追加](create-paywall)します。 3. Adapty ダッシュボードで[プレースメントを作成し、ペイウォールを追加](create-placement)します。 4. モバイルアプリに [Adapty SDK](sdk-installation-reactnative) をインストールします。 </details> ## ペイウォールビルダーで作成したペイウォールを取得する \{#fetch-paywall-designed-with-paywall-builder\} [ペイウォールビルダーでペイウォールをデザイン](adapty-paywall-builder)した場合、ユーザーへの表示のためにモバイルアプリのコードでレンダリング処理を実装する必要はありません。このようなペイウォールにはペイウォール内に表示するコンテンツとその表示方法の両方が含まれています。ただし、プレースメントを通じて ID を取得し、ビュー設定を取得してからモバイルアプリに表示する必要があります。 パフォーマンスを最適化するために、ペイウォールとその[ビュー設定](react-native-get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder)はできるだけ早く取得し、ユーザーに表示する前に画像のダウンロードが完了するよう十分な時間を確保することが重要です。 ペイウォールを取得するには、`getPaywall` メソッドを使用します。 ```typescript showLineNumbers try { const placementId = 'YOUR_PLACEMENT_ID'; const locale = 'en'; const paywall = await adapty.getPaywall(placementId, locale); // the requested paywall } catch (error) { // handle the error } ``` パラメーター: | パラメーター | 必須/任意 | 説明 | |-------------------|--------|-----------| | **placementId** | 必須 | 取得したい[プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** | <p>任意</p><p>デフォルト: `en`</p> | <p>[ペイウォールのローカライゼーション](add-paywall-locale-in-adapty-paywall-builder)の識別子。このパラメーターは、マイナス(**-**)で区切られた1つまたは2つのサブタグで構成される言語コードです。最初のサブタグは言語、2番目は地域を表します。</p><p></p><p>例:`en` は英語、`pt-br` はブラジルポルトガル語を表します。</p><p>ロケールコードの詳細と推奨される使用方法については、[ローカライゼーションとロケールコード](localizations-and-locale-codes)をご覧ください。</p> | | **fetchPolicy** | デフォルト: `.reloadRevalidatingCacheData` | <p>デフォルトでは、SDK はサーバーからデータを読み込もうとし、失敗した場合はキャッシュされたデータを返します。ユーザーが常に最新のデータを取得できるため、このオプションを推奨します。</p><p></p><p>ただし、ユーザーが不安定なインターネット環境を使用していると考えられる場合は、`.returnCacheDataElseLoad` を使用してキャッシュデータが存在する場合に返すことを検討してください。この場合、ユーザーは最新のデータを取得できないことがありますが、インターネット接続の状況に関わらず読み込み時間が速くなります。キャッシュは定期的に更新されるため、セッション中はネットワークリクエストを避けるためにキャッシュを使用しても安全です。</p><p></p><p>キャッシュはアプリの再起動後も保持され、アプリの再インストールや手動でのクリアによってのみ削除されます。</p><p></p><p>Adapty SDK はペイウォールをローカルに2層で保存します:上記の定期更新キャッシュと[フォールバックペイウォール](fallback-paywalls)。また、ペイウォールを高速に取得するために CDN を使用し、CDN に到達できない場合に備えてスタンドアロンのフォールバックサーバーも用意しています。このシステムは、インターネット接続が不安定な場合でも信頼性を確保しながら、常に最新バージョンのペイウォールを取得できるように設計されています。</p> | | **loadTimeoutMs** | デフォルト: 5秒 | <p>このメソッドのタイムアウトを制限する値です。タイムアウトに達した場合、キャッシュされたデータまたはローカルフォールバックが返されます。</p><p>内部的に複数のリクエストで構成される場合があるため、まれに `loadTimeout` で指定した時間よりも少し遅くタイムアウトすることがあります。</p><p>Android の場合:拡張関数(例:`5.seconds`、`.seconds` は `import com.adapty.utils.seconds` からインポート)または `TimeInterval.seconds(5)` を使用して `TimeInterval` を作成できます。制限なしにするには、`TimeInterval.INFINITE` を使用します。</p> | レスポンスパラメーター: | パラメーター | 説明 | | :-------- |:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Paywall | プロダクト ID のリスト、ペイウォール識別子、リモートコンフィグ、その他いくつかのプロパティを含む [`AdaptyPaywall`](https://react-native.adapty.io/interfaces/adaptypaywall) オブジェクト。 | ## ペイウォールビルダーで作成したペイウォールのビュー設定を取得する \{#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder\} :::important ペイウォールビルダーの **Show on device** トグルを有効にしてください。このオプションが有効になっていない場合、ビュー設定を取得できません。 ::: ペイウォールを取得したら、`ViewConfiguration` が含まれているか確認します。これはペイウォールビルダーで作成されたことを示します。この情報をもとにペイウォールの表示方法を判断してください。`ViewConfiguration` が存在する場合はペイウォールビルダーのペイウォールとして扱い、存在しない場合は[リモートコンフィグペイウォールとして処理](present-remote-config-paywalls-react-native)してください。 React Native SDK では、ビュー設定を手動で取得せずに `createPaywallView` メソッドを直接呼び出します。 :::warning `createPaywallView` メソッドの結果は1回のみ使用できます。再度使用する必要がある場合は、`createPaywallView` メソッドを新たに呼び出してください。再作成せずに2回呼び出すと、`AdaptyUIError.viewAlreadyPresented` エラーが発生することがあります。 ::: ```typescript showLineNumbers // for the Adapty SDK < 3.14 – import {createPaywallView} from 'react-native-adapty/dist/ui'; if (paywall.hasViewConfiguration) { try { const view = await createPaywallView(paywall); } catch (error) { // handle the error } } else { //use your custom logic } ``` パラメーター: | パラメーター | 必須/任意 | 説明 | | :------------------- | :------- | :----------------------------------------------------------- | | **paywall** | 必須 | 目的のペイウォールのコントローラーを取得するための `AdaptyPaywall` オブジェクト。 | | **customTags** | 任意 | カスタムタグとその解決済み値の辞書を定義します。カスタムタグはペイウォールコンテンツ内のプレースホルダーとして機能し、ペイウォール内のパーソナライズされたコンテンツとして特定の文字列に動的に置き換えられます。詳しくはペイウォールビルダーのカスタムタグのトピックをご参照ください。 | | **prefetchProducts** | 任意 | 画面上のプロダクト表示タイミングを最適化するために有効にします。`true` の場合、AdaptyUI は必要なプロダクトを自動的に取得します。デフォルト: `false`。 | :::note 複数の言語を使用している場合は、[ペイウォールビルダーのローカライゼーション](add-paywall-locale-in-adapty-paywall-builder)の追加方法と、ロケールコードの正しい使用方法を[こちら](react-native-localizations-and-locale-codes)でご確認ください。 ::: ビューを取得したら、[ペイウォールを表示](react-native-present-paywalls)します。 ## デフォルトオーディエンス向けのペイウォールを取得してより高速に表示する \{#get-a-paywall-for-a-default-audience-to-fetch-it-faster\} 通常、ペイウォールはほぼ瞬時に取得されるため、このプロセスを高速化することを心配する必要はありません。ただし、オーディエンスやペイウォールが多数あり、ユーザーのインターネット接続が遅い場合、ペイウォールの取得に時間がかかることがあります。そのような状況では、ペイウォールを表示しないよりもスムーズなユーザー体験を提供するために、デフォルトのペイウォールを表示したい場合があります。 この問題に対処するために、`getPaywallForDefaultAudience` メソッドを使用できます。このメソッドは、**All Users** オーディエンス向けに指定されたプレースメントのペイウォールを取得します。ただし、推奨されるアプローチは、上記の[ペイウォール情報の取得](#fetch-paywall-designed-with-paywall-builder)セクションで説明したように `getPaywall` メソッドでペイウォールを取得することを理解しておくことが重要です。 :::warning `getPaywall` を推奨する理由 `getPaywallForDefaultAudience` メソッドにはいくつかの重大な欠点があります: - **後方互換性の問題の可能性**: 現在と将来のアプリバージョンで異なるペイウォールを表示する必要がある場合、課題が生じる可能性があります。現在(レガシー)バージョンをサポートするペイウォールを設計するか、現在(レガシー)バージョンのユーザーがレンダリングされないペイウォールで問題が発生することを受け入れるかのどちらかになります。 - **ターゲティングの喪失**: すべてのユーザーが **All Users** オーディエンス向けに設計された同じペイウォールを見ることになるため、パーソナライズされたターゲティング(国、マーケティングアトリビューション、独自のカスタム属性に基づくターゲティングを含む)が失われます。 ペイウォール取得の高速化というメリットのためにこれらの欠点を受け入れる場合は、以下のように `getPaywallForDefaultAudience` メソッドを使用してください。そうでない場合は、[上記](#fetch-paywall-designed-with-paywall-builder)で説明した `getPaywall` を使用してください。 ::: ```typescript showLineNumbers try { const id = 'YOUR_PLACEMENT_ID'; const locale = 'en'; const paywall = await adapty.getPaywallForDefaultAudience(id, locale); // the requested paywall } catch (error) { // handle the error } ``` :::note `getPaywallForDefaultAudience` メソッドは React Native SDK バージョン 2.11.2 以降で利用できます。 ::: | パラメーター | 必須/任意 | 説明 | |---------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **placementId** | 必須 | [プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** | <p>任意</p><p>デフォルト: `en`</p> | <p>[ペイウォールのローカライゼーション](add-remote-config-locale)の識別子。このパラメーターは、マイナス(**-**)で区切られた1つ以上のサブタグで構成される言語コードです。最初のサブタグは言語、2番目は地域を表します。</p><p></p><p>例:`en` は英語、`pt-br` はブラジルポルトガル語を表します。</p><p></p><p>ロケールコードの詳細と推奨される使用方法については、[ローカライゼーションとロケールコード](react-native-localizations-and-locale-codes)をご覧ください。</p> | | **fetchPolicy** | デフォルト: `.reloadRevalidatingCacheData` | <p>デフォルトでは、SDK はサーバーからデータを読み込もうとし、失敗した場合はキャッシュされたデータを返します。ユーザーが常に最新のデータを取得できるため、このオプションを推奨します。</p><p></p><p>ただし、ユーザーが不安定なインターネット環境を使用していると考えられる場合は、`.returnCacheDataElseLoad` を使用してキャッシュデータが存在する場合に返すことを検討してください。この場合、ユーザーは最新のデータを取得できないことがありますが、インターネット接続の状況に関わらず読み込み時間が速くなります。キャッシュは定期的に更新されるため、セッション中はネットワークリクエストを避けるためにキャッシュを使用しても安全です。</p><p></p><p>キャッシュはアプリの再起動後も保持され、アプリの再インストールや手動でのクリアによってのみ削除されます。</p> | ## アセットのカスタマイズ \{#customize-assets\} ペイウォール内の画像や動画をカスタマイズするには、カスタムアセットを実装します。 ヒーロー画像とヒーロー動画には定義済みのID(`hero_image` と `hero_video`)があります。カスタムアセットバンドルでは、これらの ID でエレメントをターゲットにしてその動作をカスタマイズします。 その他の画像や動画については、Adapty ダッシュボードで[カスタム ID を設定](custom-media)する必要があります。 例えば、次のようなことができます: - 特定のユーザーに異なる画像や動画を表示する。 - リモートのメイン画像を読み込む間、ローカルのプレビュー画像を表示する。 - 動画の再生前にプレビュー画像を表示する。 :::important この機能を使用するには、Adapty React Native SDK をバージョン 3.8.0 以上に更新してください。 ::: カスタムアセットをシンプルな辞書で提供する方法の例を示します: ```javascript const customAssets: Record<string, AdaptyCustomAsset> = { 'custom_image': { type: 'image', relativeAssetPath: 'custom_image.png' }, 'hero_video': { type: 'video', fileLocation: { ios: { fileName: 'custom_video.mp4' }, android: { relativeAssetPath: 'videos/custom_video.mp4' } } } }; view = await createPaywallView(paywall, { customAssets }) ``` :::note アセットが見つからない場合、ペイウォールはデフォルトの表示にフォールバックします。 ::: --- # File: react-native-present-paywalls --- --- title: "React Native - 新しいペイウォールビルダーのペイウォールを表示する" description: "Adapty を使用して React Native アプリでペイウォールを表示します。" --- ペイウォールビルダーを使ってペイウォールをカスタマイズした場合、ユーザーに表示するためのレンダリングコードをモバイルアプリ側で書く必要はありません。そのようなペイウォールには、表示する内容と表示方法の両方が含まれています。 始める前に、以下を確認してください: 1. [ペイウォールを作成](create-paywall)していること。 2. ペイウォールを[プレースメント](placements)に追加していること。 3. [ペイウォールを取得し、ビューを準備](react-native-get-pb-paywalls)していること。 :::warning このガイドは、SDK v3.0 以降が必要な**新しいペイウォールビルダーのペイウォール**専用です。ペイウォールの表示方法は、ペイウォールビルダーのバージョンやリモートコンフィグペイウォールによって異なります。 - **リモートコンフィグペイウォール**の表示については、[リモートコンフィグで設計したペイウォールのレンダリング](present-remote-config-paywalls)を参照してください。 ::: Adapty React Native SDK では、ペイウォールを表示する方法が 2 つあります: - **React コンポーネント**: アプリのアーキテクチャやナビゲーションシステムに組み込める埋め込みコンポーネントです。 - **モーダル表示** ## React コンポーネント \{#react-component\} :::note **React コンポーネント**方式には SDK 3.14.0 以降が必要です。 ::: 既存のコンポーネントツリーにペイウォールを埋め込むには、React Native コンポーネントの階層内で `AdaptyPaywallView` コンポーネントを直接使用します。埋め込みコンポーネントにより、アプリのアーキテクチャやナビゲーションシステムに統合できます。 :::note Android では、ペイウォールがステータスバーの後ろまで拡張されない場合、上部にビジュアルオーバーレイが表示されることがあります。ペイウォールではこれをオフにすることをお勧めします。[ペイウォール上部のビジュアルオーバーレイ(Android)](#visual-overlay-at-the-top-of-the-paywall-android)を参照してください。 ::: ```typescript showLineNumbers title="React Native (TSX)" function MyPaywall({ paywall }) { const paywallParams = useMemo(() => ({ loadTimeoutMs: 3000, }), []); const onCloseButtonPress = useCallback<EventHandlers['onCloseButtonPress']>(() => {}, []); const onProductSelected = useCallback<EventHandlers['onProductSelected']>((productId) => {}, []); const onPurchaseStarted = useCallback<EventHandlers['onPurchaseStarted']>((product) => {}, []); const onPurchaseCompleted = useCallback<EventHandlers['onPurchaseCompleted']>((purchaseResult, product) => {}, []); const onPurchaseFailed = useCallback<EventHandlers['onPurchaseFailed']>((error, product) => {}, []); const onRestoreStarted = useCallback<EventHandlers['onRestoreStarted']>(() => {}, []); const onRestoreCompleted = useCallback<EventHandlers['onRestoreCompleted']>((profile) => {}, []); const onRestoreFailed = useCallback<EventHandlers['onRestoreFailed']>((error) => {}, []); const onPaywallShown = useCallback<EventHandlers['onPaywallShown']>(() => {}, []); const onRenderingFailed = useCallback<EventHandlers['onRenderingFailed']>((error) => {}, []); const onLoadingProductsFailed = useCallback<EventHandlers['onLoadingProductsFailed']>((error) => {}, []); const onUrlPress = useCallback<EventHandlers['onUrlPress']>((url) => {}, []); const onCustomAction = useCallback<EventHandlers['onCustomAction']>((actionId) => {}, []); const onWebPaymentNavigationFinished = useCallback<EventHandlers['onWebPaymentNavigationFinished']>(() => {}, []); return ( <AdaptyPaywallView paywall={paywall} params={paywallParams} style={styles.paywall} onCloseButtonPress={onCloseButtonPress} onProductSelected={onProductSelected} onPurchaseStarted={onPurchaseStarted} onPurchaseCompleted={onPurchaseCompleted} onPurchaseFailed={onPurchaseFailed} onRestoreStarted={onRestoreStarted} onRestoreCompleted={onRestoreCompleted} onRestoreFailed={onRestoreFailed} onPaywallShown={onPaywallShown} onRenderingFailed={onRenderingFailed} onLoadingProductsFailed={onLoadingProductsFailed} onCustomAction={onCustomAction} onUrlPress={onUrlPress} onWebPaymentNavigationFinished={onWebPaymentNavigationFinished} /> ); } ``` ## モーダル表示 \{#modal-presentation\} ペイウォールをスタンドアロン画面として表示するには、[`createPaywallView`](react-native-get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder) メソッドで作成した `view` の `view.present()` メソッドを使用します。各 `view` は一度しか使用できません。ペイウォールを再度表示する必要がある場合は、`createPaywallView` をもう一度呼び出して新しい `view` インスタンスを作成してください。 :::warning 同じ `view` を再作成せずに再利用することは禁止されています。`AdaptyUIError.viewAlreadyPresented` エラーが発生します。 ::: <Tabs groupId="version" queryString> <TabItem value="new" label="SDK version 3.14 or later" default> ```typescript showLineNumbers title="React Native (TSX)" const view = await createPaywallView(paywall); // Optional: handle paywall events (close, purchase, restore, etc) // view.setEventHandlers({ ... }); try { await view.present(); } catch (error) { // handle the error } ``` :::important `setEventHandlers` を複数回呼び出すと、提供したハンドラーが上書きされ、対象のイベントに設定されていたデフォルトおよび以前のハンドラーが置き換えられます。 ::: </TabItem> <TabItem value="old" label="SDK version < 3.14" default> ```typescript showLineNumbers title="React Native (TSX)" const view = await createPaywallView(paywall); view.registerEventHandlers(); // handle close press, etc try { await view.present(); } catch (error) { // handle the error } ``` </TabItem> </Tabs> ### iOS の表示スタイルを設定する \{#configure-ios-presentation-style\} `present()` メソッドに `iosPresentationStyle` パラメーターを渡すことで、iOS でのペイウォールの表示方法を設定できます。パラメーターには `'full_screen'`(デフォルト)または `'page_sheet'` を指定します。 ```typescript showLineNumbers try { await view.present(iosPresentationStyle: 'page_sheet'); } catch (error) { // handle the error } ``` ## 開発者定義タイマーを使用する \{#use-developer-defined-timer\} モバイルアプリで開発者定義タイマーを使用するには、`timerId`(この例では `CUSTOM_TIMER_NY`)を使用します。これは Adapty ダッシュボードで設定した開発者定義タイマーの **Timer ID** です。これにより、アプリがタイマーの終了時刻(元旦など)から現在時刻を引いて計算した `13d 09h 03m 34s` のような正確な値でタイマーを動的に更新できます。 <Tabs> <TabItem value="component" label="React component"> ```typescript showLineNumbers title="React Native (TSX)" const paywallParams = { customTimers: { 'CUSTOM_TIMER_NY': new Date(2025, 0, 1) } }; <AdaptyPaywallView paywall={paywall} params={paywallParams} // ... your event handlers /> ``` </TabItem> <TabItem value="modal" label="Modal presentation"> ```typescript showLineNumbers title="React Native (TSX)" const customTimers = { 'CUSTOM_TIMER_NY': new Date(2025, 0, 1) }; const view = await createPaywallView(paywall, { customTimers }); ``` </TabItem> </Tabs> この例では、`CUSTOM_TIMER_NY` は Adapty ダッシュボードで設定した開発者定義タイマーの **Timer ID** です。`timerResolver` により、アプリがタイマーの終了時刻(元旦など)から現在時刻を引いて計算した `13d 09h 03m 34s` のような正確な値でタイマーを動的に更新できます。 ## ダイアログを表示する \{#show-dialog\} Android でペイウォールビューが表示されているときは、ネイティブのアラートダイアログの代わりにこのメソッドを使用してください。Android では、通常の RN アラートがペイウォールビューの後ろに表示されるため、ユーザーには見えません。このメソッドを使用することで、すべてのプラットフォームでペイウォールの上に正しくダイアログが表示されます。 ```typescript showLineNumbers title="React Native (TSX)" try { const action = await view.showDialog({ title: 'Close paywall?', content: 'You will lose access to exclusive offers.', primaryActionTitle: 'Stay', secondaryActionTitle: 'Close', }); if (action === 'secondary') { // User confirmed - close the paywall await view.dismiss(); } // If primary - do nothing, user stays } catch (error) { // handle error } ``` ## あるサブスクリプションを別のものに置き換える \{#replace-one-subscription-with-another\} Android で別のサブスクリプションがアクティブな状態でユーザーが新しいサブスクリプションを購入しようとした場合、ペイウォールビューを作成する際にサブスクリプション更新パラメーターを渡すことで、新しい購入の処理方法を制御できます。現在のサブスクリプションを新しいものに置き換えるには、`createPaywallView` の `productPurchaseParams` に `oldSubVendorProductId` と `prorationMode` パラメーターを指定します。 ```typescript showLineNumbers title="React Native (TSX)" const productPurchaseParams = paywall.productIdentifiers.map((productId) => { let params = {}; if (Platform.OS === 'android') { params.android = { subscriptionUpdateParams: { oldSubVendorProductId: 'PRODUCT_ID_OF_THE_CURRENT_ACTIVE_SUBSCRIPTION', prorationMode: 'with_time_proration', }, }; } return { productId, params }; }); const view = await createPaywallView(paywall, { productPurchaseParams }); ``` ## トラブルシューティング \{#troubleshooting\} ### ペイウォール上部のビジュアルオーバーレイ(Android) \{#visual-overlay-at-the-top-of-the-paywall-android\} :::note この設定は React Native SDK 3.15.5 以降でサポートされており、ベアの React Native プロジェクトでのみ利用できます。 Expo マネージドワークフローを使用している場合、この Android リソースを直接追加することはできません。この設定を適用するには、対応する Android リソースを追加するカスタム Expo config プラグインを作成し、app.config.js に登録する必要があります。これは Expo がネイティブ Android プロジェクトを管理しているために必要です。 ::: `AdaptyPaywallView` がステータスバーの後ろまで拡張されない場合でも、上部にビジュアルオーバーレイが表示されることがあります。これを削除するには、アプリに以下のブールリソースを追加します: 1. `android/app/src/main/res/values` に移動します。`bools.xml` ファイルがない場合は作成してください。 2. 以下のリソースを追加します: ```xml <resources> <bool name="adapty_paywall_enable_safe_area_paddings">false</bool> </resources> ``` この変更はアプリ内のすべてのペイウォールにグローバルに適用されることに注意してください。 --- # File: react-native-handle-paywall-actions --- --- title: "React Native SDKでボタンアクションに対応する" description: "AdaptyのReact Nativeでペイウォールのボタンアクションを処理して、アプリのマネタイズを改善しましょう。" --- Adaptypのペイウォールビルダーを使ってペイウォールを作成する場合、ボタンを正しく設定することが重要です: 1. [ペイウォールビルダーでボタンを追加](paywall-buttons)し、既存のアクションを割り当てるか、カスタムアクションIDを作成します。 2. 割り当てた各アクションを処理するコードをアプリに記述します。 このガイドでは、コード内でカスタムアクションおよび既存アクションを処理する方法を説明します。 :::warning **購入、復元、ペイウォールのクローズ、URLの開放は自動的に処理されます。** それ以外のボタンアクションはすべて、アプリコードで適切な処理を実装する必要があります。 ::: ## ペイウォールを閉じる \{#close-paywalls\} ペイウォールを閉じるボタンを追加するには: 1. ペイウォールビルダーでボタンを追加し、**Close** アクションを割り当てます。 2. アプリコードで、ペイウォールを閉じる `close` アクションのハンドラーを実装します。 :::info React Native SDKでは、`close` アクションはデフォルトでペイウォールを閉じます。ただし、必要に応じてコードでこの動作をオーバーライドできます。たとえば、あるペイウォールを閉じると別のペイウォールが開くようにすることもできます。 ::: <Tabs groupId="version" queryString> <TabItem value="new" label="SDK version 3.14 or later" default> <Tabs groupId="presentation-method" queryString> <TabItem value="platform" label="React component" default> Reactコンポーネントの場合、個別のイベントハンドラーpropを通じてcloseアクションを処理します: ```javascript function MyPaywall({ paywall }) { const onCloseButtonPress = useCallback<EventHandlers['onCloseButtonPress']>(() => { // Handle close button press - navigate away or hide component navigation.goBack(); }, [navigation]); return ( <AdaptyPaywallView paywall={paywall} style={styles.container} onCloseButtonPress={onCloseButtonPress} /> ); } ``` </TabItem> <TabItem value="standalone" label="Modal presentation"> モーダル表示の場合、closeハンドラーを実装します: ```javascript const view = await createPaywallView(paywall); const unsubscribe = view.setEventHandlers({ onCloseButtonPress() { return true; // allow paywall closing } }); ``` </TabItem> </Tabs> </TabItem> <TabItem value="old" label="SDK version < 3.14" default> SDKバージョン3.14未満では、モーダル表示のみサポートされています: ```javascript const view = await createPaywallView(paywall); const unsubscribe = view.registerEventHandlers({ onCloseButtonPress() { return true; // allow paywall closing } }); ``` </TabItem> </Tabs> ## ペイウォールからURLを開く \{#open-urls-from-paywalls\} :::tip リンクのグループ(利用規約や購入の復元など)を追加したい場合は、ペイウォールビルダーに **Link** 要素を追加し、**Open URL** アクションが設定されたボタンと同様に処理してください。 ::: ペイウォールからリンク(**利用規約**や**プライバシーポリシー**など)を開くボタンを追加するには: 1. ペイウォールビルダーでボタンを追加し、**Open URL** アクションを割り当て、開きたいURLを入力します。 2. アプリコードで、受け取ったURLをブラウザで開く `openUrl` アクションのハンドラーを実装します。 :::info React Native SDKでは、`openUrl` アクションはデフォルトでURLを開きます。ただし、必要に応じてコードでこの動作をオーバーライドできます。 ::: <Tabs groupId="version" queryString> <TabItem value="new" label="SDK version 3.14 or later" default> <Tabs groupId="presentation-method" queryString> <TabItem value="platform" label="React component" default> Reactコンポーネントの場合、イベントハンドラーpropを通じてURLの開放を処理します: ```javascript function MyPaywall({ paywall }) { const onUrlPress = useCallback<EventHandlers['onUrlPress']>((url) => { Linking.openURL(url); }, []); return ( <AdaptyPaywallView paywall={paywall} style={styles.container} onUrlPress={onUrlPress} /> ); } ``` </TabItem> <TabItem value="standalone" label="Modal presentation"> モーダル表示の場合、URLハンドラーを実装します: ```javascript const view = await createPaywallView(paywall); const unsubscribe = view.setEventHandlers({ onUrlPress(url) { Linking.openURL(url); return false; // Keep paywall open }, }); ``` </TabItem> </Tabs> </TabItem> <TabItem value="old" label="SDK version < 3.14" default> SDKバージョン3.14未満では、モーダル表示のみサポートされています: ```javascript const view = await createPaywallView(paywall); const unsubscribe = view.registerEventHandlers({ onUrlPress(url) { Linking.openURL(url); return false; // Keep paywall open }, }); ``` </TabItem> </Tabs> ## アプリにログインする \{#log-into-the-app\} ユーザーをアプリにログインさせるボタンを追加するには: 1. ペイウォールビルダーでボタンを追加し、**Login** アクションを割り当てます。 2. アプリコードで、ユーザーを識別する `login` アクションのハンドラーを実装します。 <Tabs groupId="version" queryString> <TabItem value="new" label="SDK version 3.14 or later" default> <Tabs groupId="presentation-method" queryString> <TabItem value="platform" label="React component" default> Reactコンポーネントの場合、イベントハンドラーpropを通じてログインを処理します: ```javascript function MyPaywall({ paywall }) { const onCustomAction = useCallback<EventHandlers['onCustomAction']>((actionId) => { if (actionId === 'login') { navigation.navigate('Login'); } }, [navigation]); return ( <AdaptyPaywallView paywall={paywall} style={styles.container} onCustomAction={onCustomAction} /> ); } ``` </TabItem> <TabItem value="standalone" label="Modal presentation"> モーダル表示の場合、ログインハンドラーを実装します: ```javascript const view = await createPaywallView(paywall); const unsubscribe = view.setEventHandlers({ onCustomAction(actionId) { if (actionId === 'login') { navigation.navigate('Login'); } } }); ``` </TabItem> </Tabs> </TabItem> <TabItem value="old" label="SDK version < 3.14" default> SDKバージョン3.14未満では、モーダル表示のみサポートされています: ```javascript const view = await createPaywallView(paywall); const unsubscribe = view.registerEventHandlers({ onCustomAction(actionId) { if (actionId === 'login') { navigation.navigate('Login'); } } }); ``` </TabItem> </Tabs> ## カスタムアクションを処理する \{#handle-custom-actions\} その他のアクションを処理するボタンを追加するには: 1. ペイウォールビルダーでボタンを追加し、**Custom** アクションを割り当て、IDを設定します。 2. アプリコードで、作成したアクションIDのハンドラーを実装します。 たとえば、別のサブスクリプションオファーや買い切り購入のセットがある場合、別のペイウォールを表示するボタンを追加できます: <Tabs groupId="version" queryString> <TabItem value="new" label="SDK version 3.14 or later" default> <Tabs groupId="presentation-method" queryString> <TabItem value="platform" label="React component" default> Reactコンポーネントの場合、イベントハンドラーpropを通じてカスタムアクションを処理します: ```javascript function MyPaywall({ paywall }) { const onCustomAction = useCallback<EventHandlers['onCustomAction']>((actionId) => { if (actionId === 'openNewPaywall') { // Display another paywall } }, []); return ( <AdaptyPaywallView paywall={paywall} style={styles.container} onCustomAction={onCustomAction} /> ); } ``` </TabItem> <TabItem value="standalone" label="Modal presentation"> モーダル表示の場合、カスタムアクションハンドラーを実装します: ```javascript const unsubscribe = view.setEventHandlers({ onCustomAction(actionId) { if (actionId === 'openNewPaywall') { // Display another paywall } }, }); ``` </TabItem> </Tabs> </TabItem> <TabItem value="old" label="SDK version < 3.14" default> SDKバージョン3.14未満では、モーダル表示のみサポートされています: ```javascript const unsubscribe = view.registerEventHandlers({ onCustomAction(actionId) { if (actionId === 'openNewPaywall') { // Display another paywall } }, }); ``` </TabItem> </Tabs> --- # File: react-native-handling-events-1 --- --- title: "React Native - ペイウォールイベントの処理" description: "AdaptyのSDKを使用して、React Nativeでサブスクリプションイベントを処理します。" --- :::important このガイドでは、購入・復元・プロダクト選択・ペイウォールのレンダリングに関するイベント処理を説明します。ボタン操作(ペイウォールを閉じる、リンクを開くなど)の処理も実装する必要があります。詳細は[ボタンアクションの処理ガイド](react-native-handle-paywall-actions)を参照してください。 ::: [ペイウォールビルダー](adapty-paywall-builder)で設定されたペイウォールは、購入や復元のために追加のコードは不要です。ただし、アプリが反応できるいくつかのイベントが発生します。これらのイベントには、ボタン操作(閉じるボタン、URL、プロダクト選択など)や、ペイウォール上で行われた購入関連のアクションの通知が含まれます。以下でこれらのイベントへの対応方法を確認してください。 :::warning このガイドは**新しいペイウォールビルダーのペイウォール**専用です。Adapty SDK v3.0以降が必要です。 ::: モバイルアプリのペイウォール画面で発生するプロセスを制御・監視するには、イベントハンドラーを実装します: <Tabs groupId="version" queryString> <TabItem value="new" label="SDK version 3.14 or later" default> <Tabs groupId="presentation-method" queryString> <TabItem value="platform" label="React component" default> Reactコンポーネントの場合、`AdaptyPaywallView`コンポーネントの個別のイベントハンドラーpropを通じてイベントを処理します: ```typescript showLineNumbers title="React Native (TSX)" function MyPaywall({ paywall }) { const onCloseButtonPress = useCallback<EventHandlers['onCloseButtonPress']>(() => {}, []); const onProductSelected = useCallback<EventHandlers['onProductSelected']>((productId) => {}, []); const onPurchaseStarted = useCallback<EventHandlers['onPurchaseStarted']>((product) => {}, []); const onPurchaseCompleted = useCallback<EventHandlers['onPurchaseCompleted']>((purchaseResult, product) => {}, []); const onPurchaseFailed = useCallback<EventHandlers['onPurchaseFailed']>((error, product) => {}, []); const onRestoreStarted = useCallback<EventHandlers['onRestoreStarted']>(() => {}, []); const onRestoreCompleted = useCallback<EventHandlers['onRestoreCompleted']>((profile) => {}, []); const onRestoreFailed = useCallback<EventHandlers['onRestoreFailed']>((error) => {}, []); const onPaywallShown = useCallback<EventHandlers['onPaywallShown']>(() => {}, []); const onRenderingFailed = useCallback<EventHandlers['onRenderingFailed']>((error) => {}, []); const onLoadingProductsFailed = useCallback<EventHandlers['onLoadingProductsFailed']>((error) => {}, []); const onUrlPress = useCallback<EventHandlers['onUrlPress']>((url) => { Linking.openURL(url); }, []); const onCustomAction = useCallback<EventHandlers['onCustomAction']>((actionId) => {}, []); const onWebPaymentNavigationFinished = useCallback<EventHandlers['onWebPaymentNavigationFinished']>(() => {}, []); return ( <AdaptyPaywallView paywall={paywall} style={styles.container} onCloseButtonPress={onCloseButtonPress} onProductSelected={onProductSelected} onPurchaseStarted={onPurchaseStarted} onPurchaseCompleted={onPurchaseCompleted} onPurchaseFailed={onPurchaseFailed} onRestoreStarted={onRestoreStarted} onRestoreCompleted={onRestoreCompleted} onRestoreFailed={onRestoreFailed} onPaywallShown={onPaywallShown} onRenderingFailed={onRenderingFailed} onLoadingProductsFailed={onLoadingProductsFailed} onUrlPress={onUrlPress} onCustomAction={onCustomAction} onWebPaymentNavigationFinished={onWebPaymentNavigationFinished} /> ); } ``` </TabItem> <TabItem value="standalone" label="Modal presentation"> モーダル表示の場合は、イベントハンドラーメソッドを実装します。 :::important `setEventHandlers`を複数回呼び出すと、以前に設定したハンドラーが上書きされます。デフォルトのハンドラーも含め、該当するイベントのハンドラーがすべて置き換えられます。 ::: ```javascript showLineNumbers title="React Native (TSX)" const view = await createPaywallView(paywall); const unsubscribe = view.setEventHandlers({ onCloseButtonPress() { return true; }, onAndroidSystemBack() { return true; }, onPurchaseCompleted(purchaseResult, product) { return purchaseResult.type !== 'user_cancelled'; }, onPurchaseStarted(product) { /***/}, onPurchaseFailed(error) { /***/ }, onRestoreCompleted(profile) { /***/ }, onRestoreFailed(error, product) { /***/ }, onProductSelected(productId) { /***/}, onRenderingFailed(error) { /***/ }, onLoadingProductsFailed(error) { /***/ }, onUrlPress(url) { Linking.openURL(url); return false; // Keep paywall open }, onPaywallShown() { /***/ }, onPaywallClosed() { /***/ }, onWebPaymentNavigationFinished() { /***/ }, }); ``` </TabItem> </Tabs> </TabItem> <TabItem value="old" label="SDK version < 3.14" default> SDK version < 3.14では、モーダル表示のみサポートされています: ```javascript showLineNumbers title="React Native (TSX)" const view = await createPaywallView(paywall); const unsubscribe = view.registerEventHandlers({ onCloseButtonPress() { return true; }, onAndroidSystemBack() { return true; }, onPurchaseCompleted(purchaseResult, product) { return purchaseResult.type !== 'user_cancelled'; }, onPurchaseStarted(product) { /***/}, onPurchaseFailed(error, product) { /***/ }, onRestoreCompleted(profile) { /***/ }, onRestoreFailed(error) { /***/ }, onProductSelected(productId) { /***/}, onRenderingFailed(error) { /***/ }, onLoadingProductsFailed(error) { /***/ }, onUrlPress(url) { Linking.openURL(url); return false; // Keep paywall open }, onPaywallShown() { /***/ }, onPaywallClosed() { /***/ }, onWebPaymentNavigationFinished() { /***/ }, }); ``` </TabItem> </Tabs> <Details> <summary>イベントの例(クリックして展開)</summary> ```javascript // onCloseButtonPress { "event": "close_button_press" } // onAndroidSystemBack { "event": "android_system_back" } // onUrlPress { "event": "url_press", "url": "https://example.com/terms" } // onCustomAction { "event": "custom_action", "actionId": "login" } // onProductSelected { "event": "product_selected", "productId": "premium_monthly" } // onPurchaseStarted { "event": "purchase_started", "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" } } // onPurchaseCompleted - Success { "event": "purchase_completed", "purchaseResult": { "type": "success", "profile": { "accessLevels": { "premium": { "id": "premium", "isActive": true, "expiresAt": "2024-02-15T10:30:00Z" } } } }, "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" } } // onPurchaseCompleted - Cancelled { "event": "purchase_completed", "purchaseResult": { "type": "user_cancelled" }, "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" } } // onPurchaseFailed { "event": "purchase_failed", "error": { "code": "purchase_failed", "message": "Purchase failed due to insufficient funds", "details": { "underlyingError": "Insufficient funds in account" }, "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" } } } // onRestoreCompleted { "event": "restore_completed", "profile": { "accessLevels": { "premium": { "id": "premium", "isActive": true, "expiresAt": "2024-02-15T10:30:00Z" } }, "subscriptions": [ { "vendorProductId": "premium_monthly", "isActive": true, "expiresAt": "2024-02-15T10:30:00Z" } ] } } // onRestoreFailed { "event": "restore_failed", "error": { "code": "restore_failed", "message": "Purchase restoration failed", "details": { "underlyingError": "No previous purchases found" } } } // onRenderingFailed { "event": "rendering_failed", "error": { "code": "rendering_failed", "message": "Failed to render paywall interface", "details": { "underlyingError": "Invalid paywall configuration" } } } // onLoadingProductsFailed { "event": "loading_products_failed", "error": { "code": "products_loading_failed", "message": "Failed to load products from the server", "details": { "underlyingError": "Network timeout" } } } // onPaywallShown { "event": "paywall_shown" } // onPaywallClosed { "event": "paywall_closed" } // onWebPaymentNavigationFinished { "event": "web_payment_navigation_finished" } ``` </Details> 必要なイベントハンドラーのみを登録し、不要なものは省略できます。この場合、未使用のイベントリスナーは作成されません。必須のイベントハンドラーはありません。 イベントハンドラーはbooleanを返します。`true`が返された場合、表示プロセスが完了したとみなされ、ペイウォール画面が閉じられ、そのビューのイベントリスナーが削除されます。 一部のイベントハンドラーにはデフォルトの動作があり、必要に応じてオーバーライドできます: - `onCloseButtonPress`:閉じるボタンが押されたときにペイウォールを閉じます。 - `onUrlPress`:タップされたURLを開き、ペイウォールを開いたままにします。 - `onAndroidSystemBack`(モーダル表示のみ):**Back**ボタンが押されたときにペイウォールを閉じます。 - `onRestoreCompleted`:復元が成功した後にペイウォールを閉じます。 - `onPurchaseCompleted`:ユーザーがキャンセルした場合を除き、ペイウォールを閉じます。 - `onRenderingFailed`:レンダリングに失敗した場合にペイウォールを閉じます。 ### イベントハンドラー \{#event-handlers\} | イベントハンドラー | 説明 | |:-----------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **onCustomAction** | ユーザーがカスタムアクション(例:[カスタムボタン](paywall-buttons)のクリック)を実行したときに呼び出されます。 | | **onUrlPress** | ユーザーがペイウォール内のURLをクリックしたときに呼び出されます。 | | **onAndroidSystemBack** | モーダル表示のみ:ユーザーがAndroidのシステム**Back**ボタンをタップしたときに呼び出されます。 | | **onCloseButtonPress** | 閉じるボタンが表示されていてユーザーがタップしたときに呼び出されます。このハンドラーでペイウォール画面を閉じることを推奨します。 | | **onPurchaseCompleted** | 購入が完了したとき(成功、ユーザーによるキャンセル、承認待ちのいずれの場合も)に呼び出されます。購入成功時は更新された`AdaptyProfile`を提供します。ユーザーのキャンセルや保留中の支払い(保護者の承認が必要な場合など)は`onPurchaseFailed`ではなくこのイベントをトリガーします。 | | **onPurchaseStarted** | ユーザーが「購入」アクションボタンをタップして購入プロセスを開始したときに呼び出されます。 | | **onPurchaseFailed** | エラー(支払い制限、無効なプロダクト、ネットワーク障害、トランザクション検証の失敗など)により購入が失敗したときに呼び出されます。ユーザーのキャンセルや保留中の支払いでは呼び出されず、それらは`onPurchaseCompleted`をトリガーします。 | | **onRestoreStarted** | ユーザーが購入の復元プロセスを開始したときに呼び出されます。 | | **onRestoreCompleted** | 購入の復元が成功し、更新された`AdaptyProfile`を提供するときに呼び出されます。ユーザーが必要な`accessLevel`を持っている場合は画面を閉じることを推奨します。確認方法については[サブスクリプションステータス](react-native-listen-subscription-changes)のトピックを参照してください。 | | **onRestoreFailed** | 復元プロセスが失敗し、`AdaptyError`を提供するときに呼び出されます。 | | **onProductSelected** | ペイウォールビュー内のプロダクトが選択されたときに呼び出されます。購入前にユーザーが何を選択しているかを監視できます。 | | **onRenderingFailed** | ビューのレンダリング中にエラーが発生し、`AdaptyError`を提供するときに呼び出されます。このようなエラーは通常発生しないため、もし発生した場合はご連絡ください。 | | **onLoadingProductsFailed** | プロダクトの読み込みに失敗し、`AdaptyError`を提供するときに呼び出されます。ビュー作成時に`prefetchProducts: true`を設定していない場合、AdaptyUIが自動的にサーバーから必要なオブジェクトを取得します。 | | **onPaywallShown** | ペイウォールがユーザーに表示されたときに呼び出されます。iOSでは、ユーザーがペイウォール内の[ウェブペイウォールボタン](web-paywall#step-2a-add-a-web-purchase-button)をタップしてアプリ内ブラウザでウェブペイウォールが開いたときにも呼び出されます。 | | **onPaywallClosed** | モーダル表示のみ:ユーザーがペイウォールを閉じたときに呼び出されます。iOSでは、アプリ内ブラウザで開いた[ウェブペイウォール](web-paywall#step-2a-add-a-web-purchase-button)が画面から消えたときにも呼び出されます。 | | **onWebPaymentNavigationFinished** | [ウェブペイウォール](web-paywall)を購入のために開こうとした後(成功・失敗を問わず)に呼び出されます。 | --- # File: react-native-use-fallback-paywalls-expo --- --- title: "ExpoプロジェクトでフォールバックペイウォールToを使用する" description: "react-native-adapty の config plugin を使って、Expo React Native プロジェクトにフォールバックペイウォールを設定します。" --- :::important このガイドは **Expo プロジェクト** を対象としています。 **純粋な React Native(non-Expo)** を使用している場合は、[純粋な React Native のフォールバックガイド](react-native-use-fallback-paywalls-pure) を参照してください。 ::: スムーズなユーザー体験を維持するために、フロー、[ペイウォール](paywalls)、[オンボーディング](onboardings)に[フォールバック](/fallback-paywalls)を設定することが重要です。この対策により、インターネット接続が部分的または完全に失われた場合でも、アプリケーションの機能を維持できます。 * **アプリケーションが Adapty サーバーにアクセスできない場合:** フォールバックのフローまたはペイウォールを表示し、ローカルのオンボーディング設定にアクセスできます。 * **アプリケーションがインターネットにアクセスできない場合:** フォールバックのフローまたはペイウォールを表示できます。オンボーディングはリモートコンテンツを含むため、動作にはインターネット接続が必要です。 :::important このガイドの手順を進める前に、Adapty からフォールバック設定ファイルを[ダウンロード](/local-fallback-paywalls)してください。 ::: Adapty SDK は **ネイティブ** バンドルからフォールバックファイルを読み込みます。iOS では `.app` パッケージ内のリソース、Android では `android/app/src/main/assets/` 以下のエントリです。Expo プロジェクトでは `npx expo prebuild --clean` を実行するたびにこれらのディレクトリが再生成されるため、手動でファイルを配置することはできません。`react-native-adapty` の config plugin が、ファイルをネイティブバンドルに組み込む処理を自動的に行います。 :::tip 完全な動作サンプルは [`FocusJournalExpo` サンプルアプリ](https://github.com/adaptyteam/AdaptySDK-React-Native/tree/master/examples/FocusJournalExpo) で確認できます。 ::: ## 設定 \{#configuration\} 1. フォールバック JSON ファイルをプロジェクト内の任意の場所に配置します。通常は他のアセットの隣が適しています: ``` <your-project>/ └── assets/ ├── ios_fallback.json └── android_fallback.json ``` 2. `app.json`(または `app.config.js`)の `react-native-adapty` エントリに `fallbackFile` オプションを追加します。各プラットフォームのキーはオプションです。必要なプラットフォームだけ設定してください: ```json title="app.json" { "expo": { "plugins": [ [ "react-native-adapty", { "fallbackFile": { "ios": "./assets/ios_fallback.json", "android": "./assets/android_fallback.json" } } ] ] } } ``` :::note Adapty はプラットフォームごとに異なるフォールバック JSON をエクスポートします。iOS は Apple のプロダクト ID、Android は Google Play のプロダクト ID が使われます。各プラットフォームに対応するファイルを指定してください。 ::: 3. ネイティブプロジェクトを再生成します: ```sh title="Shell" npx expo prebuild ``` plugin は iOS ファイルを Xcode プロジェクトのバンドルリソースに追加し、Android ファイルを `android/app/src/main/assets/` にコピーします。prebuild の出力には次のような行が含まれます: ``` [react-native-adapty] Registered ios_fallback.json as iOS bundle resource [react-native-adapty] Copied android_fallback.json to android assets/ ``` 4. 実行時に SDK へファイルを登録します: ```typescript showLineNumbers title="App.tsx" import { adapty } from 'react-native-adapty'; await adapty.activate('PUBLIC_SDK_KEY'); await adapty.setFallback({ ios: { fileName: 'ios_fallback.json' }, android: { relativeAssetPath: 'android_fallback.json' }, }); ``` `setFallback` に渡すファイル名は、`fallbackFile` で設定したファイルのベース名と一致している必要があります。 :::important `setFallback` は、SDK がペイウォールまたはオンボーディングを取得する前に実行する必要があります。 ::: ## 確認 \{#verification\} `npx expo prebuild` 実行後、両方のプラットフォームを確認してください: - **Android**: `android/app/src/main/assets/` の内容を一覧表示します。`fallbackFile.android` で設定したファイルが存在し、iOS 専用のファイル名が含まれていないことを確認してください。 - **iOS**: `ios/<ProjectName>.xcodeproj/project.pbxproj` で iOS のファイル名を検索します。`PBXFileReference`、`Resources` グループ、`PBXResourcesBuildPhase` に表示されているはずです。Android 専用のファイル名が `project.pbxproj` に含まれていないことを確認してください。 --- # File: react-native-use-fallback-paywalls-pure --- --- title: "純粋な React Native プロジェクトでフォールバックペイウォールを使用する" description: "純粋な React Native(非 Expo)プロジェクトでフォールバックペイウォールを設定します。" --- :::important このガイドは **純粋な React Native(非 Expo)プロジェクト** に適用されます。 **Expo** を使用している場合は、代わりに [Expo フォールバックガイド](react-native-use-fallback-paywalls-expo) を参照してください。 ::: スムーズなユーザー体験を維持するために、フロー、[ペイウォール](paywalls)、[オンボーディング](onboardings)に[フォールバック](/fallback-paywalls)を設定することが重要です。この対策により、インターネット接続が部分的または完全に失われた場合でも、アプリケーションの機能を維持できます。 * **アプリケーションが Adapty サーバーにアクセスできない場合:** フォールバックのフローまたはペイウォールを表示し、ローカルのオンボーディング設定にアクセスできます。 * **アプリケーションがインターネットにアクセスできない場合:** フォールバックのフローまたはペイウォールを表示できます。オンボーディングはリモートコンテンツを含むため、動作にはインターネット接続が必要です。 :::important このガイドの手順を進める前に、Adapty からフォールバック設定ファイルを[ダウンロード](/local-fallback-paywalls)してください。 ::: ## 設定 \{#configuration\} ### Android \{#android\} 1. フォールバック設定ファイルをアプリケーションに追加します。以下のディレクトリのいずれかを選択してください: * **android/app/src/main/assets/** * **android/app/src/main/res/raw/** 注意: `res/raw` フォルダには特別なファイル命名規則があります(文字で始まる、大文字不可、アンダースコア以外の特殊文字不可、名前にスペース不可)。 2. `FileLocation` 定数の `android` プロパティを更新します: * ファイルが `assets` ディレクトリにある場合は、そのディレクトリからの相対パスを渡します。 * ファイルが `res/raw` ディレクトリにある場合は、拡張子なしのファイル名を渡します。 ### iOS \{#ios\} 1. フォールバック JSON ファイルをプロジェクトバンドルに追加します:XCode で **File** メニューを開き、**Add Files to "YourProjectName"** オプションを選択します。 2. 設定ファイルの名前を `FileLocation` 定数の `ios` プロパティに渡します。 ## 使用例 \{#example\} <Tabs groupId="current-os" queryString> <TabItem value="current" label="現行バージョン (v3.8+)" default> ```typescript showLineNumbers //after v3.8 const fileLocation = { ios: { fileName: 'ios_fallback.json' }, android: { //if the file is located in 'android/app/src/main/assets/' relativeAssetPath: 'android_fallback.json' } } await adapty.setFallback(fileLocation); ``` </TabItem> <TabItem value="old" label="旧バージョン (v3.8 以前)" default> ```typescript showLineNumbers //Legacy (before v3.8) const paywallsLocation = { ios: { fileName: 'ios_fallback.json' }, android: { //if the file is located in 'android/app/src/main/assets/' relativeAssetPath: 'android_fallback.json' } } await adapty.setFallbackPaywalls(paywallsLocation); ``` </TabItem> </Tabs> パラメーター: | パラメーター | 説明 | | :------------------- | :------------------------------------------------------- | | **fileLocation** | フォールバック設定ファイルの場所を表すオブジェクト。 | --- # File: react-native-localizations-and-locale-codes --- --- title: "React Native SDKでローカライゼーションとロケールコードを使用する" description: "Adapty SDKを使ってReact NativeアプリのペイウォールをローカライズするFormatする方法を学びましょう。" --- ## なぜ重要なのか \{#why-this-is-important\} ロケールコードが必要になるシナリオはいくつかあります。たとえば、アプリの現在のローカライゼーションに対応した正しいペイウォールを取得しようとする場合などです。 ロケールコードは複雑で、プラットフォームによって異なる場合があるため、Adaptyではサポートするすべてのプラットフォームに対して独自の統一標準を採用しています。ただし、このコードが複雑であるため、サーバーに何を送信して正しいローカライゼーションを取得しているのか、またその後の処理がどのように行われるのかを正確に理解することが非常に重要です。そうすることで、期待どおりの結果を常に受け取れるようになります。 ## AdaptyのロケールコードFormatの標準 \{#locale-code-standard-at-adapty\} ロケールコードについて、Adaptyはわずかに修正した [BCP 47標準](https://en.wikipedia.org/wiki/IETF_language_tag) を使用しています。各コードは小文字のサブタグをハイフンで区切った形式です。例:`en`(英語)、`pt-br`(ポルトガル語(ブラジル))、`zh`(簡体字中国語)、`zh-hant`(繁体字中国語)。 ## ロケールコードのマッチング \{#locale-code-matching\} Adaptyがクライアントサイドのセルからロケールコードを受け取り、ペイウォールの対応するローカライゼーションを探し始めると、以下の処理が行われます: 1. 受け取ったロケール文字列が小文字に変換され、アンダースコア(`_`)がすべてハイフン(`-`)に置換されます 2. 完全に一致するロケールコードのローカライゼーションを検索します 3. 一致するものが見つからなかった場合、最初のハイフンより前の部分文字列(`pt-br` の場合は `pt`)を取得し、一致するローカライゼーションを探します 4. それでも見つからない場合、デフォルトの `en` ローカライゼーションを返します これにより、`'pt_BR'` を送信したiOSデバイス、`pt-BR` を送信したAndroidデバイス、そして `pt-br` を送信した別のデバイスはすべて同じ結果を受け取ります。 ## ローカライゼーションの実装:推奨する方法 \{#implementing-localizations-recommended-way\} ローカライゼーションについて気になっているということは、すでにプロジェクト内でローカライズされた文字列ファイルを扱っている可能性が高いです。その場合、各ローカライゼーションに対応するファイルに、意図するAdaptyロケールコードをキーと値のペアとして追加することをおすすめします。そして、SDKを呼び出す際にそのキーの値を取得します。次のようにします: ```javascript showLineNumbers // 1. Modify your localization files (e.g., using react-i18next) /* en.json */ { "adapty_paywalls_locale": "en" } /* es.json */ { "adapty_paywalls_locale": "es" } /* pt-BR.json */ { "adapty_paywalls_locale": "pt-br" } // 2. Extract and use the locale code const MyComponent = () => { const { t } = useTranslation(); const fetchPaywall = async () => { const locale = t('adapty_paywalls_locale'); // pass locale code to adapty.getPaywall or adapty.getPaywallForDefaultAudience method const paywall = await adapty.getPaywallForDefaultAudience('placement_id', locale); }; }; ``` この方法により、アプリのすべてのユーザーに対してどのローカライゼーションが取得されるかを完全にコントロールできます。 ## ローカライゼーションの実装:別の方法 \{#implementing-localizations-the-other-way\} すべてのローカライゼーションに対して明示的にロケールコードを定義せずに、同様の(ただし完全に同一ではない)結果を得ることもできます。その場合、たとえば [`react-native-localize`](https://github.com/zoontek/react-native-localize) などを使ってデバイスからロケールコードを取得します: ```javascript showLineNumbers const fetchPaywall = async () => { // getLocales() returns the user's preferred locales in BCP-47 format (e.g., 'en-US', 'pt-BR') const locale = RNLocalize.getLocales()[0].languageTag; // pass locale code to adapty.getPaywall or adapty.getPaywallForDefaultAudience method const paywall = await adapty.getPaywallForDefaultAudience('placement_id', locale); }; ``` この方法は以下の理由からおすすめしていません: 1. iOSでは、優先言語と現在の地域ロケールは同一ではありません。ローカライゼーションが正しく選択されるようにするには、Appleの解決ロジックに任せるか(推奨方法のローカライズ済み文字列ファイルを使用すれば自動的に機能します)、自分でそのロジックを再現する必要があります。 2. デバイスのロケールが、Adaptyで設定したローカライゼーションのいずれとも一致しない場合があります。その場合、SDKは最初のサブタグで一致するものにフォールバックするか、最終的に `en` にフォールバックします。これは、そのユーザーに対してデフォルトにしたい言語ではない可能性があります。 それでもこの方法を使用する場合は、関連するすべてのユースケースに対応できていることを確認してください。 --- # File: react-native-web-paywall --- --- title: "ウェブペイウォールの実装" description: "Adapty SDK を使用して React Native アプリにウェブペイウォールを実装する方法を説明します。" --- :::important 始める前に、[ダッシュボードでウェブペイウォールを設定](web-paywall)し、Adapty SDK バージョン 3.6.1 以降をインストールしていることを確認してください。 ::: ## ウェブペイウォールを開く \{#open-web-paywalls\} 自分で開発したペイウォールを使用する場合は、SDK メソッドを使ってウェブペイウォールを処理する必要があります。`.openWebPaywall` メソッドは以下を行います: 1. 特定のユーザーに表示されたペイウォールと、そのユーザーがリダイレクトされるウェブページを Adapty が紐付けるための、一意の URL を生成します。 2. ユーザーがアプリに戻ってきたことを検知し、短い間隔で `.getProfile` をリクエストして、プロファイルのアクセス権が更新されたかどうかを確認します。 これにより、支払いが成功してアクセス権が更新された場合、サブスクリプションはほぼ即座にアプリ内で有効化されます。 ```typescript showLineNumbers title="React Native (TSX)" try { await adapty.openWebPaywall(product); } catch (error) { console.warn('Failed to open web paywall:', error); } ``` :::note `openWebPaywall` メソッドには 2 つのバージョンがあります: 1. `openWebPaywall(product)` — ペイウォールに基づいて URL を生成し、プロダクトデータも URL に追加します。 2. `openWebPaywall(paywall)` — ペイウォールに基づいて URL を生成しますが、プロダクトデータは URL に追加しません。Adapty ペイウォール内のプロダクトとウェブペイウォール内のプロダクトが異なる場合に使用してください。 ::: #### エラーのハンドリング \{#handle-errors\} | エラー | 説明 | 推奨される対処法 | |-----------------------------------------|--------------------------------------------------------|---------------------------------------------------------------------------| | AdaptyError.paywallWithoutPurchaseUrl | ペイウォールにウェブ購入 URL が設定されていない | Adapty ダッシュボードでペイウォールが正しく設定されているか確認してください | | AdaptyError.productWithoutPurchaseUrl | プロダクトにウェブ購入 URL が設定されていない | Adapty ダッシュボードでプロダクトの設定を確認してください | | AdaptyError.failedOpeningWebPaywallUrl | ブラウザで URL を開くことができなかった | デバイスの設定を確認するか、別の購入方法を提供してください | | AdaptyError.failedDecodingWebPaywallUrl | URL のパラメータのエンコードに失敗した | URL パラメータが有効で正しい形式であることを確認してください | ## アプリ内ブラウザでウェブペイウォールを開く \{#open-web-paywalls-in-an-in-app-browser\} :::important アプリ内ブラウザでのウェブペイウォールの表示は、Adapty SDK v3.15 以降でサポートされています。 ::: デフォルトでは、ウェブペイウォールは外部ブラウザで開きます。 シームレスなユーザー体験を提供するために、アプリ内ブラウザでウェブペイウォールを開くことができます。これにより、ウェブ購入ページがアプリ内に表示され、ユーザーはアプリを切り替えることなく取引を完了できます。 これを有効にするには、`openWebPaywall` の第 2 引数に `WebPresentation.BrowserInApp` を渡してください: ```typescript showLineNumbers title="React Native (TSX)" try { await adapty.openWebPaywall( product, WebPresentation.BrowserInApp, // default – WebPresentation.BrowserOutApp ); } catch (error) { console.warn('Failed to open web paywall:', error); } ``` --- # File: react-native-troubleshoot-paywall-builder --- --- title: "React Native SDKでペイウォールビルダーのトラブルシューティング" description: "React Native SDKでペイウォールビルダーのトラブルシューティング" --- このガイドでは、React Native SDK で Adapty ペイウォールビルダーを使用してデザインしたペイウォールで発生する一般的な問題の解決方法を説明します。 ## ペイウォール設定の取得に失敗する \{#getting-a-paywall-configuration-fails\} **問題**: `getPaywallConfiguration` メソッドがペイウォール設定の取得に失敗する。 **原因**: ペイウォールビルダーで、デバイスへの表示が有効になっていない。 **解決策**: ペイウォールビルダーで **Show on device** トグルを有効にしてください。 <img src="/assets/shared/img/show-on-device.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## ペイウォールの表示回数が多すぎる \{#the-paywall-view-number-is-too-big\} **問題**: ペイウォールの表示回数が想定の2倍になっている。 **原因**: コード内で `logShowPaywall` を呼び出している可能性があります。ペイウォールビルダーを使用している場合、このメソッドを呼び出すと表示回数が重複します。ペイウォールビルダーでデザインされたペイウォールは、アナリティクスが自動的に計測されるため、このメソッドを使用する必要はありません。 **解決策**: ペイウォールビルダーを使用している場合は、コード内で `logShowPaywall` を呼び出していないことを確認してください。 ## その他の問題 \{#other-issues\} **問題**: 上記以外のペイウォールビルダー関連の問題が発生している。 **解決策**: 必要に応じて[マイグレーションガイド](react-native-sdk-migration-guides)を参照し、SDK を最新バージョンに移行してください。新しいバージョンでは多くの問題が修正されています。 --- # File: react-native-quickstart-manual --- --- title: "React Native SDKのカスタムペイウォールで購入を有効にする" description: "Adapty SDKをReact Nativeのカスタムペイウォールに統合して、アプリ内課金を有効にします。" --- このガイドでは、Adaptyをカスタムペイウォールに統合する方法を説明します。ペイウォールの実装を完全にコントロールしながら、Adapty SDKがプロダクトの取得、新規購入の処理、過去の購入の復元を行います。 :::important **このガイドはカスタムペイウォールを実装する開発者向けです。** 最も簡単に購入を有効にしたい場合は、[ペイウォールビルダー](react-native-quickstart-paywalls)をご利用ください。ペイウォールビルダーを使えば、ノーコードのビジュアルエディタでペイウォールを作成でき、Adaptyがすべての購入ロジックを自動的に処理します。アプリを再公開することなく、異なるデザインをテストすることも可能です。 ::: ## 始める前に \{#before-you-start\} ### プロダクトの設定 \{#set-up-products\} アプリ内課金を有効にするには、3つの重要な概念を理解する必要があります: - [**プロダクト**](product) – ユーザーが購入できるもの(サブスクリプション、消耗型アイテム、永続アクセスなど) - [**ペイウォール**](paywalls) – どのプロダクトを提供するかを定義する設定。Adaptyでは、ペイウォールがプロダクトを取得する唯一の方法ですが、この設計によりアプリのコードを変更せずにプロダクト、価格、オファーを変更できます。 - [**プレースメント**](placements) – アプリ内でペイウォールを表示する場所とタイミング(`main`、`onboarding`、`settings`など)。ダッシュボードでプレースメントにペイウォールを設定し、コード内ではプレースメントIDで取得します。これにより、A/Bテストの実施や異なるユーザーへの異なるペイウォールの表示が簡単になります。 カスタムペイウォールを使用する場合でも、これらの概念を理解しておくことが重要です。基本的には、アプリで販売するプロダクトを管理するための仕組みです。 カスタムペイウォールを実装するには、**ペイウォール**を作成して**プレースメント**に追加する必要があります。この設定により、プロダクトを取得できるようになります。ダッシュボードで何をすべきかを理解するには、[こちら](quickstart)のクイックスタートガイドをご参照ください。 ### ユーザーの管理 \{#manage-users\} バックエンド認証の有無にかかわらず使用できます。 ただし、Adapty SDKは匿名ユーザーと識別済みユーザーを異なる方法で処理します。詳細を把握し、ユーザーを適切に扱うために、[識別クイックスタートガイド](react-native-quickstart-identify)をお読みください。 ## ステップ1. プロダクトを取得する \{#step-1-get-products\} カスタムペイウォール用のプロダクトを取得するには、次の手順を実行します: 1. `getPaywall`メソッドに[プレースメント](placements)IDを渡して`paywall`オブジェクトを取得する。 2. `getPaywallProducts`メソッドを使用して、このペイウォールのプロダクト配列を取得する。 ```typescript showLineNumbers async function loadPaywall() { try { const paywall: AdaptyPaywall = await adapty.getPaywall('YOUR_PLACEMENT_ID'); const products: AdaptyPaywallProduct[] = await adapty.getPaywallProducts(paywall); // Use products to build your custom paywall UI } catch (error) { // Handle the error } } ``` ## ステップ2. 購入を受け付ける \{#step-2-accept-purchases\} ユーザーがカスタムペイウォールでプロダクトをタップしたら、選択したプロダクトを引数として`makePurchase`メソッドを呼び出します。これにより購入フローが処理され、更新されたプロファイルが返されます。 ```typescript showLineNumbers async function purchaseProduct(product: AdaptyPaywallProduct) { try { const purchaseResult: AdaptyPurchaseResult = await adapty.makePurchase(product); switch (purchaseResult.type) { case 'success': // Purchase successful, profile updated break; case 'user_cancelled': // User canceled the purchase break; case 'pending': // Purchase is pending (e.g., user will pay offline with cash) break; } } catch (error) { // Handle the error } } ``` ## ステップ3. 購入を復元する \{#step-3-restore-purchases\} アプリストアでは、サブスクリプションを提供するすべてのアプリに対して、ユーザーが購入を復元できる手段を用意することを求めています。 ユーザーが復元ボタンをタップしたら`restorePurchases`メソッドを呼び出します。これにより購入履歴がAdaptyと同期され、更新されたプロファイルが返されます。 ```typescript showLineNumbers async function restorePurchases() { try { const profile: AdaptyProfile = await adapty.restorePurchases(); // Restore successful, profile updated } catch (error) { // Handle the error } } ``` ## 次のステップ \{#next-steps\} --- no_index: true --- import Callout from '../../../components/Callout.astro'; <Callout type="tip"> ご質問やお困りのことがあれば、[サポートフォーラム](https://adapty.featurebase.app/)をご覧ください。よくある質問への回答を見つけたり、ご自身の質問を投稿することができます。チームとコミュニティがサポートいたします! </Callout> ペイウォールをアプリに表示する準備が整いました。[App Storeサンドボックス](test-purchases-in-sandbox)または[Google Playストア](testing-on-android)でテスト購入を行い、ペイウォールからテスト購入を完了できることを確認してください。本番環境に対応した実装がどのように機能するかを確認するには、サンプルアプリの[CustomPurchaseScreen.tsx](https://github.com/adaptyteam/AdaptySDK-React-Native/blob/master/examples/ExpoGoWebMock/src/CustomPurchaseScreen.tsx)を参照してください。このファイルでは、適切なエラー処理、ローディング状態、UIの状態管理を含む購入処理の実装例を確認できます。 次に、[ユーザーが購入を完了したかどうかを確認](react-native-check-subscription-status)して、ペイウォールを表示するか有料機能へのアクセスを許可するかを判断してください。 --- # File: fetch-paywalls-and-products-react-native --- --- title: "React Native SDKでリモートコンフィグペイウォールのペイウォールとプロダクトを取得する" description: "Adapty React Native SDKでペイウォールとプロダクトを取得し、ユーザーの収益化を強化します。" --- リモートコンフィグやカスタムペイウォールを表示する前に、それらの情報を取得する必要があります。このトピックはリモートコンフィグおよびカスタムペイウォールに関するものです。ペイウォールビルダーでカスタマイズしたペイウォールの取得については、[ペイウォールビルダーのペイウォールとその設定を取得する](react-native-get-pb-paywalls)を参照してください。 :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: <details> <summary>モバイルアプリでペイウォールとプロダクトの取得を始める前に(クリックして展開)</summary> 1. Adapty ダッシュボードで[プロダクトを作成する](create-product)。 2. Adapty ダッシュボードで[ペイウォールを作成し、プロダクトをペイウォールに組み込む](create-paywall)。 3. Adapty ダッシュボードで[プレースメントを作成し、ペイウォールをプレースメントに組み込む](create-placement)。 4. モバイルアプリに[Adapty SDKをインストールする](sdk-installation-reactnative)。 </details> ## ペイウォール情報を取得する \{#fetch-paywall-information\} Adaptyでは、[プロダクト](product)はApp StoreとGoogle Playの両方のプロダクトを組み合わせたものです。これらのクロスプラットフォームプロダクトはペイウォールに統合され、特定のモバイルアプリのプレースメント内で表示できます。 プロダクトを表示するには、`getPaywall`メソッドを使用していずれかの[プレースメント](placements)から[ペイウォール](paywalls)を取得する必要があります。 :::important **プロダクトIDをハードコードしないでください。** ハードコードすべきIDはプレースメントIDのみです。ペイウォールはリモートで設定されるため、プロダクトの数や利用可能なオファーはいつでも変わる可能性があります。アプリはこれらの変更を動的に処理する必要があります。今日は2つのプロダクトが返されても、明日は3つになる可能性があり、コード変更なしにすべてを表示できるようにしてください。 ::: ```typescript showLineNumbers try { const id = 'YOUR_PLACEMENT_ID'; const locale = 'en'; const paywall = await adapty.getPaywall(id, locale); // the requested paywall } catch (error) { // handle the error } ``` | パラメータ | 必須 | 説明 | |-------------------|--------|-----------| | **placementId** | 必須 | [プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** | <p>任意</p><p>デフォルト: `en`</p> | <p>[ペイウォールのローカライズ](add-remote-config-locale)の識別子。このパラメータは、マイナス(**-**)で区切られた1つ以上のサブタグで構成される言語コードです。最初のサブタグは言語、2番目は地域を表します。</p><p></p><p>例: `en`は英語、`pt-br`はブラジルポルトガル語を表します。</p><p></p><p>ロケールコードの詳細と推奨される使用方法については、[ローカライズとロケールコード](react-native-localizations-and-locale-codes)を参照してください。</p> | | **fetchPolicy** | デフォルト: `.reloadRevalidatingCacheData` | <p>デフォルトでは、SDKはサーバーからデータを読み込もうとし、失敗した場合はキャッシュデータを返します。ユーザーが常に最新のデータを取得できるため、この設定を推奨します。</p><p></p><p>ただし、ユーザーが不安定なインターネット環境にいると想定される場合は、`.returnCacheDataElseLoad`を使用してキャッシュデータが存在すれば返すことを検討してください。この場合、最新データが取得できないこともありますが、接続状況に関わらず読み込み時間が短縮されます。キャッシュは定期的に更新されるため、セッション中にネットワークリクエストを避けるために使用しても安全です。</p><p></p><p>キャッシュはアプリを再起動しても保持され、アプリの再インストールまたは手動でのクリーンアップ時のみ削除されます。</p><p></p><p>Adapty SDKはペイウォールを2つのレイヤーで保存します: 上記の定期更新キャッシュと[フォールバックペイウォール](react-native-use-fallback-paywalls)です。また、ペイウォールをより速く取得するためにCDNを使用し、CDNに到達できない場合のためにスタンドアロンのフォールバックサーバーも利用しています。このシステムは、インターネット接続が不安定な場合でも常に最新のペイウォールを取得できるよう設計されています。</p> | | **loadTimeoutMs** | デフォルト: 5秒 | <p>このメソッドのタイムアウト上限を設定します。タイムアウトに達した場合、キャッシュデータまたはローカルフォールバックが返されます。</p><p></p><p>まれに、内部で複数のリクエストが実行される場合があるため、`loadTimeout`で指定した時間よりわずかに遅れてタイムアウトすることがあります。</p> | プロダクトIDをハードコードしないでください!ペイウォールはリモートで設定されるため、利用可能なプロダクト、プロダクト数、特別オファー(無料トライアルなど)は随時変更される可能性があります。これらのシナリオをコードで適切に処理してください。 例えば、最初に2つのプロダクトを取得した場合はその2つを表示し、後で3つになった場合はコード変更なしに3つすべてを表示できるようにしてください。ハードコードが必要なのはプレースメントIDのみです。 レスポンスパラメータ: | パラメータ | 説明 | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- | | Paywall | プロダクトIDのリスト、ペイウォール識別子、リモートコンフィグ、およびその他のプロパティを含む[`AdaptyPaywall`](https://react-native.adapty.io/interfaces/adaptypaywall)オブジェクト。 | ## プロダクトを取得する \{#fetch-products\} ペイウォールを取得したら、対応するプロダクト配列を照会できます: ```typescript showLineNumbers try { // ...paywall const products = await adapty.getPaywallProducts(paywall); // the requested products list } catch (error) { // handle the error } ``` レスポンスパラメータ: | パラメータ | 説明 | | :-------- |:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Products | プロダクト識別子、プロダクト名、価格、通貨、サブスクリプション期間、およびその他のプロパティを含む[`AdaptyPaywallProduct`](https://react-native.adapty.io/interfaces/adaptypaywallproduct)オブジェクトのリスト。 | 独自のペイウォールデザインを実装する際は、[`AdaptyPaywallProduct`](https://react-native.adapty.io/interfaces/adaptypaywallproduct)オブジェクトのプロパティにアクセスする必要があります。以下によく使用されるプロパティを示しますが、利用可能なすべてのプロパティの詳細についてはリンク先のドキュメントを参照してください。 | プロパティ | 説明 | |-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **タイトル** | プロダクトのタイトルを表示するには、`product.localizedTitle`を使用します。ローカライズはデバイスのロケールではなく、ユーザーが選択したストアの国に基づきます。 | | **価格** | ローカライズされた価格を表示するには、`product.price?.localizedString`を使用します。このローカライズはデバイスのロケール情報に基づきます。`product.price?.amount`を使用して数値として価格にアクセスすることもできます。値は現地通貨で提供されます。関連する通貨記号を取得するには、`product.price?.currencySymbol`を使用します。 | | **サブスクリプション期間** | 期間(週、月、年など)を表示するには、`product.subscription?.localizedSubscriptionPeriod`を使用します。このローカライズはデバイスのロケールに基づきます。プログラムでサブスクリプション期間を取得するには、`product.subscription?.subscriptionPeriod`を使用します。そこから`unit`プロパティにアクセスして長さ(`'day'`、`'week'`、`'month'`、`'year'`、または`'unknown'`)を取得できます。`numberOfUnits`の値で期間単位の数を取得できます。例えば、四半期サブスクリプションの場合、unitプロパティは`'month'`、numberOfUnitsは`3`になります。 | | **初回オファー** | サブスクリプションに初回オファーが含まれているかどうかを示すバッジなどを表示するには、`product.subscription?.offer?.phases`プロパティを確認します。これは最大2つの割引フェーズ(無料トライアルフェーズと初回割引価格フェーズ)を含むリストです。各フェーズオブジェクトには以下の便利なプロパティがあります:<br/>• `paymentMode`: `'free_trial'`、`'pay_as_you_go'`、`'pay_up_front'`、`'unknown'`の値を持つ文字列。無料トライアルは`'free_trial'`タイプになります。<br/>• `price`: 数値としての割引価格。無料トライアルの場合は`0`になります。<br/>• `localizedNumberOfPeriods`: オファーの長さを説明するデバイスのロケールでローカライズされた文字列。例えば、3日間のトライアルオファーはこのフィールドに`'3 days'`と表示されます。<br/>• `subscriptionPeriod`: または、このプロパティを使用してオファー期間の個別の詳細を取得できます。オファーに対しても前のセクションで説明したのと同じように機能します。<br/>• `localizedSubscriptionPeriod`: ユーザーのロケールに合わせてフォーマットされた割引のサブスクリプション期間。 | ## デフォルトオーディエンスのペイウォールでペイウォール取得を高速化する \{#speed-up-paywall-fetching-with-default-audience-paywall\} 通常、ペイウォールはほぼ瞬時に取得されるため、このプロセスの高速化について心配する必要はありません。しかし、オーディエンスやペイウォールが多数あり、かつユーザーのインターネット接続が弱い場合、ペイウォールの取得に予想以上の時間がかかることがあります。そのような場合、ペイウォールをまったく表示しないよりも、スムーズなユーザー体験を確保するためにデフォルトのペイウォールを表示したいことがあるでしょう。 この問題に対処するため、`getPaywallForDefaultAudience`メソッドを使用できます。これは指定したプレースメントの**All Users**オーディエンス向けペイウォールを取得します。ただし、上記の[ペイウォール情報を取得する](fetch-paywalls-and-products-react-native#fetch-paywall-information)セクションで詳述している`getPaywall`メソッドによる取得が推奨アプローチであることを理解しておくことが重要です。 :::warning `getPaywall`を推奨する理由 `getPaywallForDefaultAudience`メソッドにはいくつかの重大な欠点があります: - **後方互換性の問題が生じる可能性**: 現在と将来のアプリバージョンで異なるペイウォールを表示する必要がある場合、課題が生じる可能性があります。現在の(レガシー)バージョンをサポートするペイウォールを設計するか、現在の(レガシー)バージョンのユーザーがレンダリングされないペイウォールに遭遇する可能性を受け入れるかのどちらかになります。 - **ターゲティングの喪失**: すべてのユーザーが**All Users**オーディエンス向けに設計された同じペイウォールを見ることになり、国、マーケティングアトリビューション、独自のカスタム属性に基づくパーソナライズされたターゲティングが失われます。 これらの欠点を受け入れてでも高速なペイウォール取得のメリットを得たい場合は、以下のように`getPaywallForDefaultAudience`メソッドを使用してください。そうでなければ、[上記](fetch-paywalls-and-products-react-native#fetch-paywall-information)で説明した`getPaywall`を使用してください。 ::: ```typescript showLineNumbers try { const id = 'YOUR_PLACEMENT_ID'; const locale = 'en'; const paywall = await adapty.getPaywallForDefaultAudience(id, locale); // the requested paywall } catch (error) { // handle the error } ``` :::note `getPaywallForDefaultAudience`メソッドはReact Native SDKバージョン2.11.2以降で利用可能です。 ::: | パラメータ | 必須 | 説明 | |---------|--------|-----------| | **placementId** | 必須 | [プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** | <p>任意</p><p>デフォルト: `en`</p> | <p>[ペイウォールのローカライズ](add-remote-config-locale)の識別子。このパラメータは、マイナス(**-**)で区切られた1つ以上のサブタグで構成される言語コードです。最初のサブタグは言語、2番目は地域を表します。</p><p></p><p>例: `en`は英語、`pt-br`はブラジルポルトガル語を表します。</p><p></p><p>ロケールコードの詳細と推奨される使用方法については、[ローカライズとロケールコード](react-native-localizations-and-locale-codes)を参照してください。</p> | | **fetchPolicy** | デフォルト: `.reloadRevalidatingCacheData` | <p>デフォルトでは、SDKはサーバーからデータを読み込もうとし、失敗した場合はキャッシュデータを返します。ユーザーが常に最新のデータを取得できるため、この設定を推奨します。</p><p></p><p>ただし、ユーザーが不安定なインターネット環境にいると想定される場合は、`.returnCacheDataElseLoad`を使用してキャッシュデータが存在すれば返すことを検討してください。この場合、最新データが取得できないこともありますが、接続状況に関わらず読み込み時間が短縮されます。キャッシュは定期的に更新されるため、セッション中にネットワークリクエストを避けるために使用しても安全です。</p><p></p><p>キャッシュはアプリを再起動しても保持され、アプリの再インストールまたは手動でのクリーンアップ時のみ削除されます。</p> | --- # File: present-remote-config-paywalls-react-native --- --- title: "React Native SDKでリモートコンフィグによるペイウォールをレンダリングする" description: "Adapty React Native SDKでリモートコンフィグのペイウォールを表示し、ユーザー体験をパーソナライズする方法をご覧ください。" --- リモートコンフィグを使ってペイウォールをカスタマイズした場合、ユーザーに表示するためのレンダリング処理をモバイルアプリのコードに実装する必要があります。リモートコンフィグはニーズに合わせた柔軟性を提供するため、ペイウォールに何を含めるか、またどのように表示するかはあなた次第です。リモートコンフィグから取得したカスタムペイウォールを表示できるよう、リモートコンフィグを取得するメソッドを提供しています。 ## ペイウォールのリモートコンフィグを取得して表示する \{#get-paywall-remote-config-and-present-it\} ペイウォールのリモートコンフィグを取得するには、`remoteConfig` プロパティにアクセスして必要な値を取り出します。 ```typescript showLineNumbers try { const paywall = await adapty.getPaywall({ placementId: "YOUR_PLACEMENT_ID" }); const headerText = paywall.remoteConfig?.data?.["header_text"]; } catch (error) { // handle the error } ``` 必要な値をすべて取得したら、それらをレンダリングして見栄えの良いページに組み立てましょう。さまざまなスマートフォンの画面サイズや向きに対応したデザインにすることで、デバイスを問わずシームレスで使いやすい体験を提供できます。 :::warning AdaptyアナリティクスがファネルやみA/B テストのデータを正確に収集できるよう、以下で説明する[ペイウォール表示イベントの記録](present-remote-config-paywalls-react-native#track-paywall-view-events)を必ず行ってください。 ::: ペイウォールの表示が完了したら、購入フローの設定に進みます。ユーザーが購入を行う際は、ペイウォールのプロダクトを使って `.makePurchase()` を呼び出すだけです。`.makePurchase()` メソッドの詳細については、[購入の実装](react-native-making-purchases)をご覧ください。 インターネット接続がない場合やキャッシュが利用できない場合でもスムーズな体験を確保するため、[フォールバックペイウォールの作成](react-native-use-fallback-paywalls)をおすすめします。 ## ペイウォール表示イベントを記録する \{#track-paywall-view-events\} Adaptyはペイウォールのパフォーマンス測定をサポートしています。購入データは自動的に収集されますが、ペイウォールの表示ログはお客様側で記録する必要があります。ペイウォールをいつ表示するかを把握しているのはあなただけだからです。 ペイウォール表示イベントをログに記録するには、`.logShowPaywall(paywall)` を呼び出すだけです。これにより、ファネルやA/B テストのペイウォール指標に反映されます。 :::important [ペイウォールビルダー](adapty-paywall-builder)で作成したペイウォールを表示する場合、`.logShowPaywall(paywall)` の呼び出しは不要です。 ::: ```typescript showLineNumbers await adapty.logShowPaywall(paywall); ``` リクエストパラメータ: | パラメータ | 必須 | 説明 | | :---------- | :------- |:--------------------------------------------------------------------------------------------| | **paywall** | 必須 | [`AdaptyPaywall`](https://react-native.adapty.io/interfaces/adaptypaywall) オブジェクト。 | --- # File: react-native-making-purchases --- --- title: "React Native SDKでモバイルアプリ内購入を行う" description: "Adaptyを使ったアプリ内課金とサブスクリプション処理のガイド。" --- モバイルアプリ内にペイウォールを表示することは、ユーザーにプレミアムコンテンツやサービスへのアクセスを提供する上で欠かせないステップです。ただし、[ペイウォールビルダー](adapty-paywall-builder)を使ってペイウォールをカスタマイズしている場合に限り、ペイウォールを表示するだけで購入が完了します。 ペイウォールビルダーを使用しない場合は、`.makePurchase()` という別のメソッドを使って購入を完了し、目的のコンテンツをアンロックする必要があります。このメソッドは、ユーザーがペイウォールを通じて取引を進めるための入り口となります。 ペイウォールに、ユーザーが購入しようとしているプロダクトに対するアクティブなプロモーションオファーがある場合、Adaptyは購入時に自動的にそれを適用します。 :::warning 初回オファーが自動的に適用されるのは、ペイウォールビルダーを使って設定したペイウォールを使用している場合のみです。 それ以外の場合は、[iOSで初回オファーの利用資格をユーザーが持っているか確認する](fetch-paywalls-and-products#check-intro-offer-eligibility-on-ios)必要があります。このステップをスキップすると、リリース時にアプリが審査で却下される可能性があります。また、初回オファーの対象ユーザーに通常価格が請求されてしまう恐れもあります。 ::: すべてのステップを漏れなく完了した上で[初期設定](quickstart)を終えていることを確認してください。設定が完了していないと、購入の検証ができません。 ## 購入を行う \{#make-purchase\} :::note **[ペイウォールビルダー](adapty-paywall-builder)を使用していますか?** 購入は自動的に処理されます。このステップはスキップできます。 **ステップバイステップのガイドをお探しですか?** フルコンテキストのエンドツーエンド実装手順については、[クイックスタートガイド](react-native-implement-paywalls-manually)をご覧ください。 ::: ```typescript showLineNumbers try { const purchaseResult = await adapty.makePurchase(product); switch (purchaseResult.type) { case 'success': const isSubscribed = purchaseResult.profile?.accessLevels['YOUR_ACCESS_LEVEL']?.isActive; if (isSubscribed) { // Grant access to the paid features } break; case 'user_cancelled': // Handle the case where the user canceled the purchase break; case 'pending': // Handle deferred purchases (e.g., the user will pay offline with cash) break; } } catch (error) { // Handle the error } ``` リクエストパラメーター: | パラメーター | 必須 | 説明 | | :---------- | :------- |:-------------------------------------------------------------------------------------------------------------------------------| | **Product** | 必須 | ペイウォールから取得した [`AdaptyPaywallProduct`](https://react-native.adapty.io/interfaces/adaptypaywallproduct) オブジェクト。 | レスポンスパラメーター: | パラメーター | 説明 | |---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Profile** | <p>リクエストが成功した場合、このオブジェクトがレスポンスに含まれます。[AdaptyProfile](https://react-native.adapty.io/interfaces/adaptyprofile) オブジェクトは、アプリ内のユーザーのアクセスレベル、サブスクリプション、および買い切り購入に関する包括的な情報を提供します。</p><p>アクセスレベルのステータスを確認して、ユーザーがアプリへの必要なアクセス権を持っているかどうかを判断してください。</p> | :::warning **注意:** Apple の StoreKit バージョンが v2.0 未満、かつ Adapty SDK バージョンが v2.9.0 未満の場合は、代わりに [Apple App Store の共有シークレット](app-store-connection-configuration#step-5-enter-app-store-shared-secret)を提供する必要があります。この方法は現在 Apple によって非推奨とされています。 ::: ## 購入時にサブスクリプションを変更する \{#change-subscription-when-making-a-purchase\} ユーザーが現在のサブスクリプションを更新する代わりに新しいサブスクリプションを選択した場合の動作は、アプリストアによって異なります。 - App Store の場合、サブスクリプションはサブスクリプショングループ内で自動的に更新されます。ユーザーがあるグループのサブスクリプションを購入している状態で別のグループのサブスクリプションを購入した場合、両方のサブスクリプションが同時にアクティブになります。 - Google Play の場合、サブスクリプションは自動的に更新されません。以下で説明するように、モバイルアプリのコードで切り替えを管理する必要があります。 Android でサブスクリプションを別のものに置き換えるには、追加パラメーターを指定して `.makePurchase()` メソッドを呼び出します。 ```typescript showLineNumbers try { const purchaseResult = await adapty.makePurchase(product, params); switch (purchaseResult.type) { case 'success': const isSubscribed = purchaseResult.profile?.accessLevels['YOUR_ACCESS_LEVEL']?.isActive; if (isSubscribed) { // Grant access to the paid features } break; case 'user_cancelled': // Handle the case where the user canceled the purchase break; case 'pending': // Handle deferred purchases (e.g., the user will pay offline with cash) break; } } catch (error) { // Handle the error } ``` 追加のリクエストパラメーター: | パラメーター | 必須 | 説明 | | :--------- | :------- | :----------------------------------------------------------- | | **params** | 必須 | [`MakePurchaseParamsInput`](https://react-native.adapty.io/types/makepurchaseparamsinput) 型のオブジェクト。 | :::info **バージョン 3.8.2 以降**: `MakePurchaseParamsInput` の構造が更新されました。`oldSubVendorProductId` と `prorationMode` は `subscriptionUpdateParams` 配下にネストされ、`isOfferPersonalized` は上位レベルに移動しました。 例: ```javascript makePurchase(product, { android: { subscriptionUpdateParams: { oldSubVendorProductId: 'old_product_id', prorationMode: 'charge_prorated_price' }, isOfferPersonalized: true } }); ``` ::: サブスクリプションと置き換えモードの詳細については、Google デベロッパードキュメントをご覧ください: - [置き換えモードについて](https://developer.android.com/google/play/billing/subscriptions#replacement-modes) - [置き換えモードに関する Google の推奨事項](https://developer.android.com/google/play/billing/subscriptions#replacement-recommendations) - 置き換えモード [`CHARGE_PRORATED_PRICE`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode#CHARGE_PRORATED_PRICE())。注意: このメソッドはサブスクリプションのアップグレードにのみ使用できます。ダウングレードはサポートされていません。 - 置き換えモード [`DEFERRED`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode#DEFERRED())。注意: 実際のサブスクリプション変更は、現在のサブスクリプションの請求期間が終了したときにのみ行われます。 ## iOSでオファーコードを利用する \{#redeem-offer-codes-in-ios\} --- no_index: true --- import Callout from '../../../components/Callout.astro'; <Details> <summary>オファーコードについて</summary> オファーコードを使うと、特定のユーザーに割引や無料トライアルを提供できます。自動的に適用される通常のオファーとは異なり、オファーコードはメールキャンペーン、SNS、印刷物など、アプリの外で配布します。ユーザーはApp Storeでコードを入力するか、引き換えURLを使うか、アプリ内ダイアログから利用できます。 オファーコードを設定するには、App Store Connectでサブスクリプションを開き、**Offer Codes** セクションに移動してください。オファーコードは[3種類](https://developer.apple.com/help/app-store-connect/manage-subscriptions/set-up-subscription-offer-codes)作成できます。 - **Free** — 指定した期間はサブスクリプションが無料になり、次の更新から通常価格になります。 - **Pay as you go** — 指定した期間、各請求サイクルに割引価格が適用され、その後は通常価格で更新されます。 - **Pay up front** — オファー期間全体に対して一括で割引価格を支払い、その後は通常価格で更新されます。 オファーコードをAdaptyに追加する必要はありません。Appleはオファー期間中のすべてのトランザクションにオファーコードカテゴリのタグを付与します。これには最初の引き換えとその後の割引更新がすべて含まれます。Adaptyはこのタグを検出し、各トランザクションをオファーカテゴリ `offer_code` として記録します。オファー期間が終了してサブスクリプションが通常価格で更新されると、タグは付与されなくなります。[Adapty ダッシュボード](controls-filters-grouping-compare-proceeds)のアナリティクスで **Offer Code** オファータイプによるフィルタリングが可能です。 #### 収益の差異が生じた場合のトラブルシューティング \{#revenue-discrepancy-troubleshooting\} オファーコードのトランザクションが、割引価格ではなく通常価格でAdaptyに記録されている場合は、App Store Connectで以下を確認してください。 - オファーコードに、ユーザーが引き換え可能なすべての地域に対して正しい価格が設定されているか。 - ユーザーの特定の国や地域に対してオファー価格が設定されているか。Appleはトランザクションに地域価格を含めて送信します。その地域のオファー価格が設定されていない場合、Appleは通常価格を送信することがあります。 [Adapty ダッシュボード](controls-filters-grouping-compare-proceeds)で、**Offer Code** オファータイプと **Offer Discount Type** フィルターを使ってオファーコードのトランザクションをフィルタリング・確認できます。 #### レガシープロモコード(非推奨) \{#legacy-promo-codes-deprecated\} <Callout type="warning"> Appleは2026年3月にアプリ内課金向けのプロモコードを廃止しました。オファーコードはより多くの機能(適格性の設定、有効期限、四半期あたり最大100万コード)を備えた後継機能です。アプリ内課金にプロモコードを使用していた場合は、App Store Connectでオファーコードに移行してください。 </Callout> レガシープロモコード(アプリのバージョンごとに最大100件)は、サブスクリプションへの無料アクセスを付与していました。オファーコードとは異なり、Appleはプロモコードのトランザクションに割引情報を含めず、レシートには通常価格が記載されていました。そのため、Adaptyはこれらのトランザクションを通常価格で記録し、Adaptyアナリティクスとレポートの間に収益の差異が生じていました。 本来は無料であるべきトランザクションが通常価格で記録されている履歴がある場合、それはレガシープロモコードによるものと考えられます。これらのコードは現在廃止されているため、正確な収益追跡のためにオファーコードに移行してください。 </Details> アプリ内にコード利用シートを表示するには: ```typescript showLineNumbers adapty.presentCodeRedemptionSheet(); ``` :::danger 弊社の観測によると、一部のアプリではオファーコード利用シートが正常に動作しない場合があります。ユーザーを App Store に直接リダイレクトすることをお勧めします。 そのためには、以下の形式のURLを開く必要があります: `https://apps.apple.com/redeem?ctx=offercodes&id={apple_app_id}&code={code}` ::: ## プリペイドプランの管理(Android) \{#manage-prepaid-plans-android\} アプリのユーザーが[プリペイドプラン](https://developer.android.com/google/play/billing/subscriptions#prepaid-plans)(例:数ヶ月分の非更新型サブスクリプションを購入)を利用できる場合、プリペイドプランの[保留中のトランザクション](https://developer.android.com/google/play/billing/subscriptions#pending)を有効にすることができます。 ```typescript showLineNumbers adapty.activate("PUBLIC_SDK_KEY", { android: { pendingPrepaidPlansEnabled: true } }); ``` --- # File: react-native-restore-purchase --- --- title: "React Native SDKでのアプリ内購入の復元" description: "Adaptyで購入を復元してシームレスなユーザー体験を実現する方法を学びます。" --- iOSとAndroid両方での購入の復元は、ユーザーが再度課金されることなく、サブスクリプションやアプリ内課金などの以前に購入したコンテンツへのアクセスを取り戻せる機能です。この機能は、アプリをアンインストールして再インストールしたユーザーや、新しいデバイスに切り替えたユーザーが、再度支払いをせずに以前購入したコンテンツにアクセスしたい場合に特に役立ちます。 :::note [ペイウォールビルダー](adapty-paywall-builder)で作成したペイウォールでは、追加のコードなしに購入が自動的に復元されます。その場合は、このステップをスキップできます。 ::: [ペイウォールビルダー](adapty-paywall-builder)を使用してペイウォールをカスタマイズしていない場合に購入を復元するには、`.restorePurchases()` メソッドを呼び出します: ```typescript showLineNumbers try { const profile = await adapty.restorePurchases(); const isSubscribed = profile.accessLevels['YOUR_ACCESS_LEVEL']?.isActive; if (isSubscribed) { // restore access } } catch (error) { // handle the error } ``` レスポンスパラメーター: | パラメーター | 説明 | |---------|-----------| | **Profile** | <p>[`AdaptyProfile`](https://react-native.adapty.io/interfaces/adaptyprofile) オブジェクト。このモデルにはアクセスレベル、サブスクリプション、および非サブスクリプション購入に関する情報が含まれています。</p><p>ユーザーがアプリへのアクセス権を持っているかどうかを判断するには、**アクセスレベルのステータス**を確認してください。</p> | :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: --- # File: implement-observer-mode-react-native --- --- title: "React Native SDKでオブザーバーモードを実装する" description: "AdaptyのオブザーバーモードをReact Native SDKに実装して、ユーザーのサブスクリプションイベントを追跡する方法を説明します。" --- 独自の購入インフラをすでにお持ちで、Adaptyへの完全な移行の準備ができていない場合は、[オブザーバーモード](observer-vs-full-mode)を試すことができます。基本的な形式では、オブザーバーモードは高度な分析と、アトリビューションおよびアナリティクスシステムとのシームレスな連携を提供します。 これがニーズに合っている場合、必要な作業は次の2つだけです: 1. `observerMode` パラメータを `true` に設定して、Adapty SDKの設定時にオブザーバーモードを有効にする。セットアップ手順は[React Native](sdk-installation-reactnative)を参照してください。 2. 既存の購入インフラからAdaptyへ[トランザクションを報告する](report-transactions-observer-mode-react-native)。 ### オブザーバーモードのセットアップ \{#observer-mode-setup\} 購入とサブスクリプションのステータスを自分で管理し、サブスクリプションイベントの送信と分析にのみAdaptyを使用する場合は、オブザーバーモードを有効にしてください。 :::important オブザーバーモードで動作している場合、Adapty SDKはトランザクションをクローズしないため、必ず自分でトランザクションを処理してください。 ::: ```typescript showLineNumbers title="App.tsx" adapty.activate('YOUR_PUBLIC_SDK_KEY', { observerMode: true, // Enable observer mode }); ``` パラメータ: | パラメータ | 説明 | | --------------------------- | ------------------------------------------------------------ | | observerMode | [オブザーバーモード](observer-vs-full-mode)を制御するboolean値。デフォルト値は `false` です。 | ## オブザーバーモードでAdaptyのペイウォールを使用する \{#using-adapty-paywalls-in-observer-mode\} Adaptyのペイウォールとそのアクセスレベル機能も使いたい場合は利用できますが、オブザーバーモードでは追加のセットアップが必要です。上記の手順に加えて、次の作業が必要です: 1. [リモートコンフィグペイウォール](present-remote-config-paywalls-react-native)と同様にペイウォールを表示する。 3. 購入トランザクションに[ペイウォールを関連付ける](report-transactions-observer-mode-react-native)。 --- # File: report-transactions-observer-mode-react-native --- --- title: "React Native SDKのオブザーバーモードでトランザクションを報告する" description: "React Native SDKのAdapty Observer Modeで購入トランザクションを報告し、ユーザーインサイトと収益トラッキングを実現します。" --- <Tabs groupId="sdk-version" queryString> <TabItem value="current" label="Adapty SDK v3.4+ (current)" default> オブザーバーモードでは、Adapty SDKは既存の購入システムで行われた購入を自動的に追跡することができません。アプリストアからトランザクションを手動で報告する必要があります。アナリティクスのエラーを防ぐため、アプリをリリースする**前に**この設定を完了させることが重要です。 各トランザクションをAdaptyに明示的に報告するには`reportTransaction`を使用します。 :::warning **トランザクションの報告を省略しないでください!** `reportTransaction`を呼び出さない場合、Adaptyはトランザクションを認識せず、アナリティクスに表示されず、インテグレーションにも送信されません。 ::: Adaptyのペイウォールを使用している場合は、トランザクションを報告する際に`variationId`を含めてください。これにより、購入が起動元のペイウォールに紐付けられ、正確なペイウォールアナリティクスが確保されます。 ```typescript showLineNumbers const variationId = paywall.variationId; try { await adapty.reportTransaction(transactionId, variationId); } catch (error) { // handle the `AdaptyError` } ``` パラメーター: | パラメーター | 必須/任意 | 説明 | | ------------- | --------- | ------------------------------------------------------------ | | transactionId | 必須 | <ul><li> iOS の場合: トランザクションの識別子。</li><li> Android の場合: 購入のString識別子(`purchase.getOrderId`)。purchaseは課金ライブラリの[Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase)クラスのインスタンスです。</li></ul> | | variationId | 任意 | バリアントのString識別子。[AdaptyPaywall](https://react-native.adapty.io/interfaces/adaptypaywall)オブジェクトの`variationId`プロパティを使用して取得できます。 | </TabItem> <TabItem value="old" label="Adapty SDK 3.3.x (legacy)" default> オブザーバーモードでは、Adapty SDKは既存の購入システムで行われた購入を自動的に追跡することができません。アプリストアからトランザクションを手動で報告するか、復元する必要があります。アナリティクスのエラーを防ぐため、アプリをリリースする**前に**この設定を完了させることが重要です。 両プラットフォームで`reportTransaction`を使用して各トランザクションを明示的に報告し、Androidでは追加ステップとして`restorePurchases`を使用してAdaptyがトランザクションを認識できるようにしてください。 :::warning **トランザクションの報告を省略しないでください!** これらのメソッドを呼び出さない場合、Adaptyはトランザクションを認識せず、アナリティクスに表示されず、インテグレーションにも送信されません。 ::: Adaptyのペイウォールを使用している場合は、トランザクションを報告する際に`variationId`を含めてください。これにより、購入が起動元のペイウォールに紐付けられ、正確なペイウォールアナリティクスが確保されます。 ```typescript showLineNumbers if (Platform.OS === 'android') { try { await adapty.restorePurchases(); } catch (error) { // handle the error } } ... const variationId = paywall.variationId; try { await adapty.reportTransaction(transactionId, variationId); } catch (error) { // handle the `AdaptyError` } ``` パラメーター: | パラメーター | 必須/任意 | 説明 | | ------------- | --------- | ------------------------------------------------------------ | | transactionId | 必須 | <ul><li> iOS、StoreKit 1 の場合: [SKPaymentTransaction](https://developer.apple.com/documentation/storekit/skpaymenttransaction)オブジェクト。</li><li> iOS、StoreKit 2 の場合: [Transaction](https://developer.apple.com/documentation/storekit/transaction)オブジェクト。</li><li> Android の場合: 購入のString識別子(`purchase.getOrderId`)。purchaseは課金ライブラリの[Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase)クラスのインスタンスです。</li></ul> | | variationId | 任意 | バリアントのString識別子。[AdaptyPaywall](https://react-native.adapty.io/interfaces/adaptypaywall)オブジェクトの`variationId`プロパティを使用して取得できます。 | </TabItem> <TabItem value="old2" label="Adapty SDK up to 3.2.x (legacy)" default> <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS" default> **トランザクションの報告** - バージョン3.1.x以前は、App Storeのトランザクションを自動的に監視するため、手動での報告は不要です。 - バージョン3.2はオブザーバーモードをサポートしていません。 </TabItem> <TabItem value="kotlin" label="Android and Android-based cross-platforms" default> **トランザクションの報告** オブザーバーモードでAdaptyにトランザクションを報告するには`restorePurchases`を使用してください。詳細は[モバイルコードでの購入の復元](react-native-restore-purchase)ページをご覧ください。 :::warning **トランザクションの報告を省略しないでください!** `restorePurchases`を呼び出さない場合、Adaptyはトランザクションを認識せず、アナリティクスに表示されず、インテグレーションにも送信されません。 ::: </TabItem> </Tabs> **ペイウォールとトランザクションの関連付け** Adapty SDKは購入の発生元を判断できません。購入処理はお客様自身が行うためです。そのため、オブザーバーモードでペイウォールやA/B テストを使用する場合は、アプリストアから受け取ったトランザクションをモバイルアプリのコードで対応するペイウォールに関連付ける必要があります。アプリをリリースする前にこれを正しく設定することが重要です。設定しないと、アナリティクスにエラーが生じます。 ```typescript const variationId = paywall.variationId; try { await adapty.setVariationId('transactionId', variationId); } catch (error) { // handle the `AdaptyError` } ``` リクエストパラメーター: | パラメーター | 必須/任意 | 説明 | | ------------- | --------- | ------------------------------------------------------------ | | transactionId | 必須 | <p>iOS、StoreKit 1 の場合: [SKPaymentTransaction](https://developer.apple.com/documentation/storekit/skpaymenttransaction)オブジェクト。</p><p>iOS、StoreKit 2 の場合: [Transaction](https://developer.apple.com/documentation/storekit/transaction)オブジェクト。</p><p>Android の場合: 購入のString識別子(purchase.getOrderId)。purchaseは課金ライブラリの[Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase)クラスのインスタンスです。</p> | | variationId | 必須 | バリアントのString識別子。[AdaptyPaywall](https://react-native.adapty.io/interfaces/adaptypaywall)オブジェクトの`variationId`プロパティを使用して取得できます。 | </TabItem> </Tabs> --- # File: react-native-troubleshoot-purchases --- --- title: "React Native SDKでの購入に関するトラブルシューティング" description: "React Native SDKでの購入に関するトラブルシューティング" --- このガイドでは、React Native SDKで手動購入を実装する際によく発生する問題の解決方法を説明します。 ## makePurchaseは正常に呼び出されるが、プロファイルが更新されない \{#makepurchase-is-called-successfully-but-the-profile-is-not-being-updated\} **問題**: `makePurchase`メソッドは正常に完了するが、ユーザーのプロファイルとサブスクリプションのステータスがAdaptyで更新されない。 **原因**: 通常、Google Play Storeのセットアップが不完全か、設定に問題があることを示しています。 **解決策**: [Google Playのセットアップ手順](initial-android)がすべて完了していることを確認してください。 ## makePurchaseが2回呼び出される \{#makepurchase-is-invoked-twice\} **問題**: 同じ購入に対して`makePurchase`メソッドが複数回呼び出されている。 **原因**: UIの状態管理の問題や、ユーザーの素早い操作によって購入フローが複数回トリガーされる場合によく発生します。 **解決策**: [Google Playのセットアップ手順](initial-android)がすべて完了していることを確認してください。 ## オブザーバーモードでのAdaptyError.cantMakePayments \{#adaptyelrorcantmakepayments-in-observer-mode\} **問題**: オブザーバーモードで`makePurchase`を使用すると`AdaptyError.cantMakePayments`が発生する。 **原因**: オブザーバーモードでは、購入はご自身の側で処理する必要があり、Adaptyの`makePurchase`メソッドは使用できません。 **解決策**: 購入に`makePurchase`を使用する場合は、オブザーバーモードをオフにしてください。`makePurchase`を使用するか、オブザーバーモードで購入を自分で処理するか、どちらか一方を選択する必要があります。詳細は[オブザーバーモードの実装](implement-observer-mode-react-native)をご覧ください。 ## Adapty error: (code: 103, message: Play Market request failed on purchases updated: responseCode=3, debugMessage=Billing Unavailable, detail: null) \{#adapty-error-code-103-message-play-market-request-failed-on-purchases-updated-responsecode3-debugmessagebilling-unavailable-detail-null\} **問題**: Google Play Storeから請求不可エラーが返される。 **原因**: このエラーはAdaptyとは関係ありません。デバイスで課金が利用できないことを示すGoogle Play課金ライブラリのエラーです。 **解決策**: このエラーはAdaptyとは関係ありません。Play Storeのドキュメントで詳細を確認できます: [Handle BillingResult response codes](https://developer.android.com/google/play/billing/errors#billing_unavailable_error_code_3) | Play Billing | Android Developers。 ## makePurchasesCompletionHandlersが見つからない \{#not-found-makepurchasescompletionhandlers\} **問題**: `makePurchasesCompletionHandlers`が見つからないという問題が発生している。 **原因**: 通常、サンドボックステストに関連する問題です。 **解決策**: 新しいサンドボックスユーザーを作成して再試行してください。これによりサンドボックス関連の購入完了ハンドラーの問題が解決されることが多いです。 ## その他の問題 \{#other-issues\} **問題**: 上記に該当しない購入関連の問題が発生している。 **解決策**: 必要に応じて[移行ガイド](react-native-sdk-migration-guides)を使用してSDKを最新バージョンに移行してください。多くの問題は新しいSDKバージョンで解決されています。 --- # File: react-native-identifying-users --- --- title: "React Native SDKでユーザーを識別する" description: "Adapty SDKを使用してReact Nativeアプリでユーザーを識別する方法を学びましょう。" --- Adaptyはすべてのユーザーに対して内部プロファイルIDを作成します。ただし、独自の認証システムがある場合は、Customer User IDを設定してください。[Profiles](profiles-crm)セクションでCustomer User IDからユーザーを検索したり、[サーバーサイドAPI](getting-started-with-server-side-api)で使用したりできます。このIDはすべての連携先にも送信されます。 ### 設定時にCustomer User IDを設定する \{#setting-customer-user-id-on-configuration\} 設定時にユーザーIDが取得できる場合は、`.activate()`メソッドの`customerUserId`パラメーターとして渡すだけです。 ```typescript showLineNumbers adapty.activate("PUBLIC_SDK_KEY", { customerUserId: "YOUR_USER_ID" }); ``` :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: ### 設定後にCustomer User IDを設定する \{#setting-customer-user-id-after-configuration\} SDKの設定時にユーザーIDが取得できない場合は、後から`.identify()`メソッドを使っていつでも設定できます。最も一般的なユースケースは、ユーザーが匿名ユーザーから認証済みユーザーに切り替わる、登録後や認証後です。 ```typescript showLineNumbers try { await adapty.identify("YOUR_USER_ID"); // successfully identified } catch (error) { // handle the error } ``` リクエストパラメーター: - **Customer User ID**(必須): 文字列のユーザー識別子。 :::warning 重要なユーザーデータの再送信 ユーザーがアカウントに再度ログインした場合など、Adaptyのサーバーがそのユーザーの情報をすでに保持しているケースがあります。そのような場合、Adapty SDKは自動的に新しいユーザーとして動作を切り替えます。カスタム属性やサードパーティネットワークからのアトリビューションなど、匿名ユーザーに対して設定していたデータがあれば、識別済みユーザーに対して再度送信する必要があります。 また、新しいユーザーのデータが異なる可能性があるため、ユーザーを識別した後はすべてのペイウォールとプロダクトを再取得することも重要です。 ::: ### ログアウトとログイン \{#logging-out-and-logging-in\} `.logout()`メソッドを呼び出すことで、いつでもユーザーをログアウトできます。 ```typescript showLineNumbers try { await adapty.logout(); // successful logout } catch (error) { // handle the error } ``` その後、`.identify()`メソッドを使ってユーザーをログインさせることができます。 ## `appAccountToken`を割り当てる(iOS) \{#assign-appaccounttoken-ios\} [`appAccountToken`](https://developer.apple.com/documentation/storekit/product/purchaseoption/appaccounttoken(_:))は、App Storeのトランザクションを内部のユーザーIDに紐付けるための**UUID**です。 StoreKitはすべてのトランザクションにこのトークンを関連付けるため、バックエンドでApp Storeのデータとユーザーを照合できます。 ユーザーごとに生成した安定したUUIDを使用し、同じアカウントでは複数のデバイス間で同じものを再利用してください。 これにより、購入とApp Storeの通知が正しく紐付けられます。 トークンは2つの方法で設定できます。SDKのアクティベーション時、またはユーザーの識別時です。 :::important `appAccountToken`は必ず`customerUserId`と一緒に渡す必要があります。 トークンのみを渡した場合、トランザクションに含まれません。 ::: ```typescript showLineNumbers // During configuration: adapty.activate("PUBLIC_SDK_KEY", { customerUserId: "YOUR_USER_ID", ios: { appAccountToken: "YOUR_APP_ACCOUNT_TOKEN" }, }); // Or when identifying users try { await adapty.identify("YOUR_USER_ID", { ios: {appAccountToken: 'YOUR_APP_ACCOUNT_TOKEN'} }); // successfully identified } catch (error) { // handle the error } ``` ### 難読化アカウントIDを設定する(Android) \{#set-obfuscated-account-ids-android\} Google Playでは、ユーザーのプライバシーとセキュリティを強化するために、特定のユースケースで難読化アカウントIDが必要です。これらのIDは、ユーザー情報を匿名のまま購入をGoogle Playが識別するのに役立ちます。不正防止や分析において特に重要です。 アプリが機密性の高いユーザーデータを扱う場合や、特定のプライバシー規制への準拠が求められる場合に、これらのIDを設定する必要があります。難読化されたIDを使うことで、実際のユーザー識別子を公開せずにGoogle Playが購入を追跡できます。 ```typescript showLineNumbers // During configuration: adapty.activate("PUBLIC_SDK_KEY", { customerUserId: "YOUR_USER_ID", android: { obfuscatedAccountId: 'YOUR_OBFUSCATED_ACCOUNT_ID' } }); // Or when identifying users try { await adapty.identify("YOUR_USER_ID", { android: { obfuscatedAccountId: 'YOUR_OBFUSCATED_ACCOUNT_ID' } }); // successfully identified } catch (error) { // handle the error } ``` ## 複数デバイス間でユーザーを検出する \{#detect-users-across-devices\} --- no_index: true --- SDKが有効化されると、StoreKit(iOS)またはGoogle Play Billing(Android)からユーザーの既存のエンタイトルメントを自動的に読み取り、Adaptyバックエンドと同期します。有効なサブスクリプションは、アプリが`restorePurchases`を呼び出すことなく、Adaptyプロファイルに表示されます。 **自動では行われない**のは、新しいデバイスのプロファイルが元のデバイスと同じユーザーのものであることの認識です。AdaptyはCustomer User IDでプロファイルを照合するため、同一性の継続性はCUIDとして何を使用するかによって異なります。 **デバイス間でAdaptyが検出できること** | あなたの設定 | Adaptyが検出すること | 必要な対応 | | --- | --- | --- | | Customer User ID = `device_id`(アプリのログインなし) | 新しいデバイスは異なるCUIDを取得するため、異なるプロファイルが作成されます。サブスクリプションは**Access level updated**イベントを通じて新しいプロファイルに同期されますが、`subscription_started`は発火しません。新しいプロファイルは元の購入の継承者として扱われます。`subscription_started`に基づくアナリティクスは、リターニングユーザーをカウント不足します。 | リターニングユーザーが既存のプロファイルをデバイス間で照合できるよう、安定したアカウントIDをCustomer User IDとして使用してください。 | | Customer User ID = 安定したアカウントID(すべてのデバイスでログイン) | SDKは`activate()`でサブスクリプションを自動同期し、`identify()`がCUIDで既存のプロファイルを照合します。 | 追加の設定は不要です。IDとサブスクリプションの両方が自動的に解決されます。 | | Apple Family Sharing の継承者 | ファミリーメンバーは**Access level updated**イベントのみを通じてサブスクリプションを受け取ります。`subscription_started`は発火しません。 | **Access level updated**をリッスンしてください。完全なイベントマトリクスは[Apple Family Sharing](apple-family-sharing)を参照してください。 | | 同じApple/Googleアカウント、異なるアプリ内ユーザー | 最初に購入を記録したプロファイルが親になります。その後のプロファイルは継承者チェーンを通じてサブスクリプションを確認し、**Access level updated**イベントが1回発生します。 | ログインを必須にし、あなたのモデルに合った[共有モード](sharing-paid-access-between-user-accounts)を選択してください。 | **新しいデバイスでの購入の復元** ペイウォールにユーザーが操作できる「購入を復元」ボタンを設置してください。Apple App Review(ガイドライン3.1.1)で必須とされており、自動同期がエッジケースを見逃した場合のフォールバックとして機能します。このボタンはSDKの`restorePurchases`を呼び出す必要があります。 初回起動時にプログラムで`restorePurchases`を呼び出すことは、通常の使用では必要ありません。SDKはすでに`activate()`で同等の処理を実行しています。プログラムによる呼び出しは、`activate()`完了後にアクセスが欠落している場合のデバッグなど、強制的に新しいレシートチェックを行う場合にのみ使用してください。 --- # File: react-native-setting-user-attributes --- --- title: "React Native SDKでユーザー属性を設定する" description: "Adapty SDKを使ってReact Nativeアプリのユーザーデータとプロファイルデータを更新する方法を学びましょう。" --- メールアドレス、電話番号などの任意の属性をアプリのユーザーに設定できます。設定した属性を使ってユーザー[セグメント](segments)を作成したり、CRMで確認したりすることができます。 ### ユーザー属性の設定 \{#setting-user-attributes\} ユーザー属性を設定するには、`.updateProfile()` メソッドを呼び出します: ```typescript showLineNumbers // Only for TypeScript validation const params: AdaptyProfileParameters = { email: 'email@email.com', phoneNumber: '+18888888888', firstName: 'John', lastName: 'Appleseed', gender: 'other', birthday: new Date().toISOString(), }; try { await adapty.updateProfile(params); } catch (error) { // handle `AdaptyError` } ``` なお、`updateProfile` メソッドで以前に設定した属性はリセットされません。 :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: ### 利用可能なキーの一覧 \{#the-allowed-keys-list\} `AdaptyProfileParameters.Builder` の利用可能なキー `<Key>` と値 `<Value>` は以下の通りです: | キー | 値 | |---|-----| | <p>email</p><p>phoneNumber</p><p>firstName</p><p>lastName</p> | 文字列 | | gender | 列挙型。使用できる値は `female`、`male`、`other` | | birthday | 日付 | ### カスタムユーザー属性 \{#custom-user-attributes\} 独自のカスタム属性を設定することもできます。これらは通常、アプリの使用状況に関連しています。たとえば、フィットネスアプリであれば1週間あたりの運動回数、語学学習アプリであればユーザーの習熟度などが考えられます。セグメントで使用してターゲットを絞ったペイウォールやオファーを作成したり、アナリティクスで収益に最も影響するプロダクト指標を特定したりするのに活用できます。 ```typescript showLineNumbers try { await adapty.updateProfile({ codableCustomAttributes: { key_1: 'value_1', key_2: 2, }, }); } catch (error) { // handle `AdaptyError` } ``` 既存のキーを削除するには、`.withRemoved(customAttributeForKey:)` メソッドを使用します: ```typescript showLineNumbers try { // to remove a key, pass null as its value await adapty.updateProfile({ codableCustomAttributes: { key_1: null, key_2: null, }, }); } catch (error) { // handle `AdaptyError` } ``` 事前にどのカスタム属性が設定済みかを確認したい場合は、`AdaptyProfile` オブジェクトの `customAttributes` フィールドを使用してください。 :::warning ユーザー属性は複数のデバイスからいつでも送信される可能性があるため、`customAttributes` の値が最新でない場合があります。最後の同期以降にサーバー上の属性が変更されている可能性があります。 ::: ### 制限 \{#limits\} - ユーザーごとに最大30件のカスタム属性 - キー名は最大30文字。キー名には英数字および以下の文字を使用できます:`_` `-` `.` - 値は文字列または浮動小数点数で、最大50文字。 --- # File: react-native-listen-subscription-changes --- --- title: "React Native SDKでサブスクリプションステータスを確認する" description: "React NativeアプリでのAdaptyのユーザーサブスクリプションステータスの追跡と管理でカスタマーリテンションを向上させましょう。" --- Adaptyを使えば、サブスクリプションステータスの管理が簡単になります。プロダクトIDをコードに手動で記述する必要はありません。アクティブな[アクセスレベル](access-level)を確認するだけで、ユーザーのサブスクリプションステータスを手軽に把握できます。 <details> <summary>サブスクリプションステータスの確認を始める前に(クリックして展開)</summary> - iOSの場合、[App Store Server Notifications](enable-app-store-server-notifications)を設定してください - Androidの場合、[リアルタイムデベロッパー通知(RTDN)](enable-real-time-developer-notifications-rtdn)を設定してください </details> ## アクセスレベルとAdaptyProfileオブジェクト \{#access-level-and-the-adaptyprofile-object\} アクセスレベルは[AdaptyProfile](https://react-native.adapty.io/interfaces/adaptyprofile)オブジェクトのプロパティです。アプリ起動時(例:[ユーザーを識別する](react-native-identifying-users#setting-customer-user-id-on-configuration)タイミングなど)にプロファイルを取得し、変更があるたびに更新することをおすすめします。こうすることで、都度リクエストを送ることなくプロファイルオブジェクトを利用できます。 プロファイルの更新通知を受け取るには、以下の[プロファイル更新(アクセスレベルを含む)のリッスン](react-native-listen-subscription-changes)セクションで説明する方法でプロファイルの変更を監視してください。 :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: ## サーバーからアクセスレベルを取得する \{#retrieving-the-access-level-from-the-server\} サーバーからアクセスレベルを取得するには、`.getProfile()`メソッドを使用します。 ```typescript showLineNumbers try { const profile = await adapty.getProfile(); } catch (error) { // handle the error } ``` レスポンスパラメーター: | パラメーター | 説明 | | --------- | ------------------------------------------------------------ | | Profile | <p>[AdaptyProfile](https://react-native.adapty.io/interfaces/adaptyprofile)オブジェクトです。通常、ユーザーがアプリのプレミアム機能にアクセスできるかどうかを判断するには、プロファイルのアクセスレベルステータスのみを確認すれば十分です。</p><p></p><p>`.getProfile`メソッドは常にAPIへのクエリを試みるため、最新の結果を提供します。何らかの理由(例:インターネット接続なし)でAdapty SDKがサーバーから情報を取得できない場合は、キャッシュのデータが返されます。また、Adapty SDKは`AdaptyProfile`キャッシュを定期的に更新し、情報をできる限り最新の状態に保ちます。</p> | `.getProfile()`メソッドはユーザープロファイルを返し、そこからアクセスレベルステータスを取得できます。1つのアプリに複数のアクセスレベルを設定することも可能です。例えば、ニュースアプリでトピックごとに独立したサブスクリプションを販売する場合、「sports」や「science」といったアクセスレベルを作成できます。ただし、ほとんどの場合はアクセスレベルは1つで十分なので、デフォルトの「premium」アクセスレベルをそのまま使用できます。 デフォルトの「premium」アクセスレベルを確認する例: ```typescript showLineNumbers try { const profile = await adapty.getProfile(); const isActive = profile.accessLevels?.["premium"]?.isActive; if (isActive) { // grant access to premium features } } catch (error) { // handle the error } ``` ### サブスクリプションステータスの更新をリッスンする \{#listening-for-subscription-status-updates\} ユーザーのサブスクリプションに変更があると、Adaptyはイベントを発火します。 Adaptyからメッセージを受け取るには、追加の設定が必要です。 ```typescript showLineNumbers // Create an "onLatestProfileLoad" event listener adapty.addEventListener('onLatestProfileLoad', profile => { // handle any changes to subscription state }); ``` アプリ起動時にもAdaptyはイベントを発火します。この場合、キャッシュされたサブスクリプションステータスが渡されます。 ### サブスクリプションステータスのキャッシュ \{#subscription-status-cache\} Adapty SDKに実装されたキャッシュは、プロファイルのサブスクリプションステータスを保存します。そのため、サーバーが利用できない場合でも、キャッシュされたデータからプロファイルのサブスクリプションステータスを取得できます。 ただし、キャッシュからの直接データ取得はできません。SDKは1分ごとにサーバーへ定期的にクエリを送信し、プロファイルに関する更新や変更を確認します。新しいトランザクションやその他の更新といった変更があった場合、サーバーとの同期を保つためにキャッシュへ反映されます。 --- # File: react-native-deal-with-att --- --- title: "Deal with ATT in React Native SDK" description: "Get started with Adapty on React Native to streamline subscription setup and management." --- アプリが AppTrackingTransparency フレームワークを使用しており、ユーザーにアプリトラッキング認証リクエストを表示する場合は、[認証ステータス](https://developer.apple.com/documentation/apptrackingtransparency/attrackingmanager/authorizationstatus/) を Adapty に送信する必要があります。 ```typescript showLineNumbers try { await adapty.updateProfile({ // you can also pass a string value (validated via tsc) if you prefer appTrackingTransparencyStatus: AppTrackingTransparencyStatus.Authorized, }); } catch (error) { // handle `AdaptyError` } ``` :::warning この値は変更されたらできるだけ早く送信することを強くお勧めします。そうすることで、設定済みのインテグレーションにタイムリーにデータが送信されます。 ::: --- # File: kids-mode-react-native --- --- title: "React Native SDK のキッズモード" description: "キッズモードを簡単に有効化して、Apple と Google のポリシーに準拠しましょう。React Native SDK では IDFA、GAID、広告データは収集されません。" --- React Native アプリが子ども向けの場合、[Apple](https://developer.apple.com/kids/) および [Google](https://support.google.com/googleplay/android-developer/answer/9893335) のポリシーに従う必要があります。Adapty SDK を使用している場合、いくつかの簡単な手順でこれらのポリシーに準拠するよう設定し、アプリストアの審査を通過できます。 ## 必要な設定 \{#whats-required\} 以下の収集を無効にするよう Adapty SDK を設定する必要があります。 - [IDFA(広告識別子)](https://en.wikipedia.org/wiki/Identifier_for_Advertisers)(iOS) - [Android 広告 ID(AAID/GAID)](https://support.google.com/googleplay/android-developer/answer/6048248)(Android) - [IP アドレス](https://www.ftc.gov/system/files/ftc_gov/pdf/p235402_coppa_application.pdf) また、カスタマーユーザー ID の使用には注意が必要です。`<FirstName.LastName>` 形式のユーザー ID やメールアドレスは、個人情報の収集とみなされます。キッズモードでは、ランダム化または匿名化された識別子(ハッシュ化された ID やデバイス生成の UUID など)を使用してコンプライアンスを確保することがベストプラクティスです。 ## キッズモードを有効にする \{#enabling-kids-mode\} ### Adapty ダッシュボードでの設定 \{#updates-in-the-adapty-dashboard\} Adapty ダッシュボードで IP アドレスの収集を無効にする必要があります。[App settings](https://app.adapty.io/settings/general) に移動し、**Collect users' IP address** の下にある **Disable IP address collection** をクリックしてください。 ### モバイルアプリのコードでの設定 \{#updates-in-your-mobile-app-code\} ポリシーに準拠するため、Adapty SDK を有効化する際にユーザーの IDFA(iOS)、GAID/AAID(Android)、および IP アドレスの収集を無効にしてください。 ```typescript showLineNumbers title="App.tsx" adapty.activate('YOUR_PUBLIC_SDK_KEY', { // Disable IP address collection ipAddressCollectionDisabled: true, // Disable IDFA collection on iOS ios: { idfaCollectionDisabled: true, }, // Disable Google Advertising ID collection on Android android: { adIdCollectionDisabled: true, }, }); ``` ### Android マニフェストでの設定 \{#updates-in-your-android-manifest\} :::note アプリが**子どものみ**を対象としており、Android 13(API 33)以上でコンパイルする場合、Google Play では `AD_ID` パーミッションをリクエストしないよう求められます。アプリ内の別の SDK(アナリティクス、アトリビューション、広告など)がマニフェストのマージによってこのパーミッションを追加する場合があります。`adIdCollectionDisabled` を設定すると Adapty による ID の収集は停止しますが、別の SDK が宣言しているパーミッション自体は削除されません。 ::: パーミッションを削除するには、`android/app/src/main/AndroidManifest.xml` の `<manifest>` 要素内に以下を追加してください。`<manifest>` 要素には `xmlns:tools="http://schemas.android.com/tools"` の宣言が必要です。 ```xml showLineNumbers title="AndroidManifest.xml" <uses-permission android:name="com.google.android.gms.permission.AD_ID" tools:node="remove" /> ``` --- # File: react-native-get-onboardings --- --- title: "React Native SDKでオンボーディングを取得する" description: "React Native向けAdaptyでオンボーディングを取得する方法を説明します。" --- Adapty ダッシュボードのビルダーで[オンボーディングのビジュアルをデザイン](design-onboarding)したら、React Nativeアプリに表示できます。まず、以下の手順でプレースメントに関連付けられたオンボーディングとそのビュー設定を取得します。 開始する前に、以下を確認してください: 1. [Adapty React Native SDK](sdk-installation-reactnative) バージョン3.8.0以上をインストール済みであること。 2. [オンボーディングを作成済み](create-onboarding)であること。 3. [プレースメント](placements)にオンボーディングを追加済みであること。 ## オンボーディングの取得 \{#fetch-onboarding\} ノーコードビルダーで[オンボーディング](onboardings)を作成すると、アプリが取得・表示する必要のある設定コンテナとして保存されます。このコンテナはエクスペリエンス全体(表示するコンテンツ、提示方法、クイズの回答やフォーム入力などのユーザー操作の処理)を管理します。また、コンテナは自動的に分析イベントを追跡するため、ビュートラッキングを別途実装する必要はありません。 パフォーマンスを最大化するために、ユーザーに表示する前に画像のダウンロード時間を確保できるよう、オンボーディング設定を早めに取得してください。 オンボーディングを取得するには、`getOnboarding`メソッドを使用します: ```typescript showLineNumbers try { const placementId = 'YOUR_PLACEMENT_ID'; const locale = 'en'; const onboarding = await adapty.getOnboarding(placementId, locale); // the requested onboarding } catch (error) { // handle the error } ``` 次に、`createOnboardingView`メソッドを呼び出してビューインスタンスを作成します。 :::warning `createOnboardingView`メソッドの結果は一度しか使用できません。再度使用する必要がある場合は、`createOnboardingView`メソッドを新たに呼び出してください。再作成せずに2回呼び出すと、`AdaptyUIError.viewAlreadyPresented`エラーが発生することがあります。 ::: ```typescript showLineNumbers // for the Adapty SDK < 3.14 – import {createOnboardingView} from 'react-native-adapty/dist/ui'; if (onboarding.hasViewConfiguration) { try { const view = await createOnboardingView(onboarding); } catch (error) { // handle the error } } else { //use your custom logic } ``` パラメーター: | パラメーター | 必須/任意 | 説明 | |-------------------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **placementId** | 必須 | 対象の[プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** | <p>任意</p><p>デフォルト:`en`</p> | <p>オンボーディングのローカライズ識別子。このパラメーターは、マイナス(**-**)文字で区切られた1つまたは2つのサブタグで構成される言語コードを指定します。最初のサブタグは言語、2番目は地域を表します。</p><p></p><p>例:`en`は英語、`pt-br`はブラジルポルトガル語を表します。</p><p>ロケールコードと推奨される使用方法については、[ローカライズとロケールコード](localizations-and-locale-codes)を参照してください。</p> | | **fetchPolicy** | デフォルト:`.reloadRevalidatingCacheData` | <p>デフォルトでは、SDKはサーバーからデータを読み込もうとし、失敗した場合はキャッシュデータを返します。ユーザーが常に最新データを取得できるため、このオプションを推奨します。</p><p></p><p>ただし、ユーザーのインターネット接続が不安定だと思われる場合は、`.returnCacheDataElseLoad`を使用してキャッシュデータが存在すれば返すことを検討してください。この場合、ユーザーが最新データを取得できないことがありますが、接続状況に関わらず読み込み時間が短縮されます。キャッシュは定期的に更新されるため、セッション中のネットワークリクエストを避けるために安全に使用できます。</p><p></p><p>キャッシュはアプリの再起動後も保持され、アプリの再インストールまたは手動クリーンアップ時にのみ消去されます。</p><p></p><p>Adapty SDKはオンボーディングをローカルに2層で保存します:上記の定期更新キャッシュとフォールバックオンボーディングです。また、CDNを使用してオンボーディングをより速く取得し、CDNが到達不能な場合に備えてスタンドアロンのフォールバックサーバーも使用します。このシステムは、インターネット接続が乏しい場合でも、常に最新バージョンのオンボーディングを取得できるよう設計されています。</p> | | **loadTimeoutMs** | デフォルト:5秒 | <p>このメソッドのタイムアウトを制限する値です。タイムアウトに達した場合、キャッシュデータまたはローカルフォールバックが返されます。</p><p>なお、このメソッドは内部で複数のリクエストで構成される場合があるため、まれに`loadTimeout`で指定した時間よりも若干遅くタイムアウトすることがあります。</p> | レスポンスパラメーター: | パラメーター | 説明 | |:----------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------| | Onboarding | オンボーディング識別子と設定、リモートコンフィグ、その他いくつかのプロパティを含む[`AdaptyOnboarding`](https://react-native.adapty.io/interfaces/adaptyonboarding)オブジェクト。 | ## デフォルトオーディエンスのオンボーディングで取得を高速化する \{#speed-up-onboarding-fetching-with-default-audience-onboarding\} 通常、オンボーディングはほぼ即時に取得されるため、この処理を高速化することを心配する必要はありません。ただし、オーディエンスとオンボーディングが多数あり、ユーザーのインターネット接続が遅い場合、オンボーディングの取得に予想以上の時間がかかることがあります。そのような状況では、オンボーディングをまったく表示しないよりも、スムーズなユーザー体験を確保するためにデフォルトのオンボーディングを表示したい場合があります。 これに対応するために、`getOnboardingForDefaultAudience`メソッドを使用できます。このメソッドは、指定されたプレースメントの**All Users**オーディエンス向けオンボーディングを取得します。ただし、上記の[オンボーディングの取得](#fetch-onboarding)セクションで説明した`getOnboarding`メソッドを使用することが推奨アプローチであることを理解することが重要です。 :::warning `getOnboardingForDefaultAudience`の代わりに`getOnboarding`の使用を検討してください。後者には重要な制限があります: - **互換性の問題**:複数のアプリバージョンをサポートする際に問題が生じる可能性があり、後方互換性のあるデザインが必要になるか、古いバージョンで正しく表示されないことを受け入れる必要があります。 - **パーソナライゼーションなし**:「All Users」オーディエンス向けのコンテンツのみを表示し、国、アトリビューション、カスタム属性に基づくターゲティングができません。 取得速度の向上がこれらのデメリットを上回る場合は、以下に示す`getOnboardingForDefaultAudience`を使用してください。それ以外の場合は、[上記](#fetch-onboarding)の`getOnboarding`を使用してください。 ::: ```typescript showLineNumbers try { const placementId = 'YOUR_PLACEMENT_ID'; const locale = 'en'; const onboarding = await adapty.getOnboardingForDefaultAudience(placementId, locale); // the requested onboarding } catch (error) { // handle the error } ``` パラメーター: | パラメーター | 必須/任意 | 説明 | |---------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **placementId** | 必須 | 対象の[プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** | <p>任意</p><p>デフォルト:`en`</p> | <p>オンボーディングのローカライズ識別子。このパラメーターは、マイナス(**-**)文字で区切られた1つまたは2つのサブタグで構成される言語コードを指定します。最初のサブタグは言語、2番目は地域を表します。</p><p></p><p>例:`en`は英語、`pt-br`はブラジルポルトガル語を表します。</p><p>ロケールコードと推奨される使用方法については、[ローカライズとロケールコード](localizations-and-locale-codes)を参照してください。</p> | | **fetchPolicy** | デフォルト:`.reloadRevalidatingCacheData` | <p>デフォルトでは、SDKはサーバーからデータを読み込もうとし、失敗した場合はキャッシュデータを返します。ユーザーが常に最新データを取得できるため、このオプションを推奨します。</p><p></p><p>ただし、ユーザーのインターネット接続が不安定だと思われる場合は、`.returnCacheDataElseLoad`を使用してキャッシュデータが存在すれば返すことを検討してください。この場合、ユーザーが最新データを取得できないことがありますが、接続状況に関わらず読み込み時間が短縮されます。キャッシュは定期的に更新されるため、セッション中のネットワークリクエストを避けるために安全に使用できます。</p><p></p><p>キャッシュはアプリの再起動後も保持され、アプリの再インストールまたは手動クリーンアップ時にのみ消去されます。</p><p></p><p>Adapty SDKはオンボーディングをローカルに2層で保存します:上記の定期更新キャッシュとフォールバックオンボーディングです。また、CDNを使用してオンボーディングをより速く取得し、CDNが到達不能な場合に備えてスタンドアロンのフォールバックサーバーも使用します。このシステムは、インターネット接続が乏しい場合でも、常に最新バージョンのオンボーディングを取得できるよう設計されています。</p> | --- # File: react-native-present-onboardings --- --- title: "React Native SDKでオンボーディングを表示する" description: "React Nativeでオンボーディングを表示してコンバージョンと収益を向上させる方法を解説します。" --- ペイウォールビルダーを使ってオンボーディングをカスタマイズした場合、モバイルアプリのコード上でレンダリング処理を実装しなくても、ユーザーに表示できます。このようなオンボーディングには、表示する内容と表示方法の両方が含まれています。 始める前に、以下を確認してください: 1. [Adapty React Native SDK](sdk-installation-reactnative) 3.8.0 以降をインストール済みであること。 2. [オンボーディングを作成](create-onboarding)済みであること。 3. オンボーディングを[プレースメント](placements)に追加済みであること。 Adapty React Native SDK では、オンボーディングを表示する方法が2つあります: - **Reactコンポーネント**: 埋め込み型コンポーネントとして、アプリのアーキテクチャやナビゲーションシステムに統合できます。 - **モーダル表示** ## React コンポーネント \{#react-component\} `AdaptyOnboardingView` コンポーネントを React Native のコンポーネント階層に直接組み込むことで、既存のコンポーネントツリーにオンボーディングを埋め込めます。埋め込み型コンポーネントを使うと、アプリのアーキテクチャやナビゲーションシステムとシームレスに統合できます。 :::note Android では、視覚的なレンダリングアーティファクトを避けるために、`AdaptyOnboardingView` の追加設定を推奨します。詳しくは [Android でシステム UI がオンボーディングコンテンツと重なる場合](#system-ui-overlaps-onboarding-content-on-android) を参照してください。 ::: <Tabs groupId="version" queryString> <TabItem value="new" label="SDK バージョン 3.14 以降" default> ```typescript showLineNumbers title="React Native (TSX)" function MyOnboarding({ onboarding }) { const onAnalytics = useCallback<OnboardingEventHandlers['onAnalytics']>((event, meta) => {}, []); const onClose = useCallback<OnboardingEventHandlers['onClose']>((actionId, meta) => {}, []); const onCustom = useCallback<OnboardingEventHandlers['onCustom']>((actionId, meta) => {}, []); const onPaywall = useCallback<OnboardingEventHandlers['onPaywall']>((actionId, meta) => {}, []); const onStateUpdated = useCallback<OnboardingEventHandlers['onStateUpdated']>((action, meta) => {}, []); const onFinishedLoading = useCallback<OnboardingEventHandlers['onFinishedLoading']>((meta) => {}, []); const onError = useCallback<OnboardingEventHandlers['onError']>((error) => {}, []); return ( <AdaptyOnboardingView onboarding={onboarding} style={styles.container} onAnalytics={onAnalytics} onClose={onClose} onCustom={onCustom} onPaywall={onPaywall} onStateUpdated={onStateUpdated} onFinishedLoading={onFinishedLoading} onError={onError} /> ); } ``` </TabItem> <TabItem value="old" label="SDK バージョン < 3.14" default> ```typescript showLineNumbers title="React Native (TSX)" function MyOnboarding({ onboarding }) { return ( <AdaptyOnboardingView onboarding={onboarding} style={{ flex: 1 }} eventHandlers={{ onAnalytics(event, meta) { // Handle analytics events }, onClose(actionId, meta) { // Handle close actions }, onCustom(actionId, meta) { // Handle custom actions }, onPaywall(actionId, meta) { // Handle paywall actions }, onStateUpdated(action, meta) { // Handle state updates }, onFinishedLoading(meta) { // Handle when onboarding finishes loading }, onError(error) { // Handle errors }, }} /> ); } ``` </TabItem> </Tabs> ## モーダル表示 \{#modal-presentation\} オンボーディングをユーザーが閉じられるスタンドアロン画面として表示するには、`createOnboardingView` メソッドで作成した `view` に対して `view.present()` メソッドを使用します。各 `view` は一度しか使用できません。オンボーディングを再度表示する必要がある場合は、`createOnboardingView` をもう一度呼び出して新しい `view` インスタンスを作成してください。 :::warning 同じ `view` を再作成せずに再利用することは禁止されています。これを行うと `AdaptyUIError.viewAlreadyPresented` エラーが発生します。 ::: <Tabs groupId="version" queryString> <TabItem value="new" label="SDK version 3.14 or later" default> ```typescript showLineNumbers title="React Native (TSX)" const view = await createOnboardingView(onboarding); // Optional: handle onboarding events (close, custom actions, etc) // view.setEventHandlers({ ... }); try { await view.present(); } catch (error) { // handle the error } ``` </TabItem> <TabItem value="old" label="SDK version < 3.14" default> ```typescript showLineNumbers title="React Native (TSX)" const view = await createOnboardingView(onboarding); view.registerEventHandlers(); // handle close press, etc try { await view.present(); } catch (error) { // handle the error } ``` </TabItem> </Tabs> ### iOSの表示スタイルを設定する \{#configure-ios-presentation-style\} `present()` メソッドに `iosPresentationStyle` パラメーターを渡すことで、iOSでのペイウォールの表示方法を設定できます。パラメーターには `'full_screen'`(デフォルト)または `'page_sheet'` を指定できます。 ```typescript showLineNumbers try { await view.present({ iosPresentationStyle: 'page_sheet' }); } catch (error) { // handle the error } ``` ## オンボーディング中のローダー \{#loader-during-onboarding\} React Native でオンボーディングを表示する際、オンボーディングが表示される前に短い白いフラッシュやローディング画面が表示されることがあります。これは、基盤となるネイティブビューが初期化される間に発生します。ニーズやワークフローに応じて、さまざまな方法で対処できます。 #### onFinishedLoading を使ったスプラッシュ画面の制御 \{#control-splash-screen-using-onfinishedloading\} :::note このアプローチは React コンポーネントを使用する場合にのみ利用可能です。モーダル表示には対応していません。 ::: React Nativeで推奨されるアプローチは、オンボーディングが完全に読み込まれるまでスプラッシュスクリーンまたはカスタムオーバーレイを表示し続け、その後手動で非表示にすることです。 Reactコンポーネント(`AdaptyOnboardingView`)を使用する場合は、スプラッシュスクリーンやオーバーレイを非表示にする前に`onFinishedLoading`イベントを待ちます: <Tabs groupId="version" queryString> <TabItem value="new" label="SDK バージョン 3.14 以降" default> ```typescript showLineNumbers title="React Native (TSX)" function MyOnboarding({ onboarding }) { const [isLoading, setIsLoading] = useState(true); const onFinishedLoading = useCallback<OnboardingEventHandlers['onFinishedLoading']>((meta) => { // Hide your splash screen or custom overlay here setIsLoading(false); }, []); return ( <> <AdaptyOnboardingView onboarding={onboarding} onFinishedLoading={onFinishedLoading} // ... other callbacks /> {isLoading && <YourCustomLoadingOverlay />} </> ); } ``` </TabItem> <TabItem value="old" label="SDK バージョン < 3.14"> ```typescript showLineNumbers title="React Native (TSX)" function MyOnboarding({ onboarding }) { const [isLoading, setIsLoading] = useState(true); return ( <> <AdaptyOnboardingView onboarding={onboarding} eventHandlers={{ onFinishedLoading(meta) { // Hide your splash screen or custom overlay here setIsLoading(false); }, // ... other handlers }} /> {isLoading && <YourCustomLoadingOverlay />} </> ); } ``` </TabItem> </Tabs> #### ネイティブローダーのカスタマイズ \{#customize-native-loader\} :::important Expo マネージドワークフローでは、カスタムネイティブレイアウト(Android の `res/layout` など)を配置することはサポートされていません。Expo アプリの場合、スプラッシュスクリーンを制御するか、React Native オーバーレイを使用するのが唯一の選択肢です。 ::: Android と iOS それぞれのプラットフォーム固有のレイアウトを使って、ネイティブローダーを差し替えることができます。モーダル表示を使用している場合は、この方法が唯一の選択肢になります。 ただし、React Native アプリではこのアプローチは通常あまり便利ではありません。 - Android と iOS で別々の実装が必要 - Expo マネージドワークフローとは互換性がない 各プラットフォーム向けにプレースホルダーを定義します: - **iOS**: `AdaptyOnboardingPlaceholderView.xib` を Xcode プロジェクトに追加します。[詳細はこちら](ios-present-onboardings#add-smooth-transitions-between-the-splash-screen-and-onboarding)。 - **Android**: `res/layout` に `adapty_onboarding_placeholder_view.xml` を作成し、プレースホルダーを定義します。[詳細はこちら](android-present-onboardings#add-smooth-transitions-between-the-splash-screen-and-onboarding)。 ## オンボーディングでのリンクの開き方をカスタマイズする \{#customize-how-links-open-in-onboardings\} :::important オンボーディングでのリンクの開き方のカスタマイズは、Adapty SDK v3.15.1 以降でサポートされています。 ::: デフォルトでは、オンボーディング内のリンクはアプリ内ブラウザで開きます。これにより、ユーザーはアプリを切り替えることなくウェブページを閲覧でき、シームレスなユーザー体験が提供されます。 外部ブラウザでリンクを開くように変更したい場合は、`externalUrlsPresentation` パラメータを `WebPresentation.BrowserOutApp` に設定してこの動作をカスタマイズできます。 <Tabs groupId="rn-onboarding-views" queryString> <TabItem value="component" label="React component" default> ```typescript showLineNumbers title="React Native (TSX)" function MyOnboarding({ onboarding }) { const onAnalytics = useCallback<OnboardingEventHandlers['onAnalytics']>((event, meta) => {}, []); const onClose = useCallback<OnboardingEventHandlers['onClose']>((actionId, meta) => {}, []); const onCustom = useCallback<OnboardingEventHandlers['onCustom']>((actionId, meta) => {}, []); const onPaywall = useCallback<OnboardingEventHandlers['onPaywall']>((actionId, meta) => {}, []); const onStateUpdated = useCallback<OnboardingEventHandlers['onStateUpdated']>((action, meta) => {}, []); const onFinishedLoading = useCallback<OnboardingEventHandlers['onFinishedLoading']>((meta) => {}, []); const onError = useCallback<OnboardingEventHandlers['onError']>((error) => {}, []); return ( <AdaptyOnboardingView onboarding={onboarding} style={styles.container} externalUrlsPresentation={WebPresentation.BrowserOutApp} // default – BrowserInApp onAnalytics={onAnalytics} onClose={onClose} onCustom={onCustom} onPaywall={onPaywall} onStateUpdated={onStateUpdated} onFinishedLoading={onFinishedLoading} onError={onError} /> ); } ``` </TabItem> <TabItem value="modal" label="Modal presentation"> ```typescript showLineNumbers title="React Native (TSX)" const view = await createOnboardingView( onboarding, { externalUrlsPresentation: WebPresentation.BrowserOutApp } // default – BrowserInApp ); try { await view.present(); } catch (error) { // handle the error } ``` </TabItem> </Tabs> ## トラブルシューティング \{#troubleshooting\} ### システムUIがAndroidのオンボーディングコンテンツと重なる \{#system-ui-overlaps-onboarding-content-on-android\} :::note この設定はベアReact Nativeプロジェクトでのみサポートされています。 Expoマネージドワークフローを使用している場合、このAndroidリソースを直接追加することはできません。この設定を適用するには、対応するAndroidリソースを追加するカスタムExpo設定プラグインを作成し、app.config.jsに登録する必要があります。ExpoがネイティブAndroidプロジェクトを管理しているため、この手順が必要です。 ::: Androidで`AdaptyOnboardingView`を使用すると、ステータスバーやナビゲーションバーなどのシステムUI要素がペイウォールコンテンツの上に表示される場合があります。これを防ぐには、次のboolean リソースをアプリに追加してください: 1. `android/app/src/main/res/values` に移動します。`bools.xml` ファイルがない場合は作成してください。 2. 次のリソースを追加します: ```xml <resources> <bool name="adapty_onboarding_enable_safe_area_paddings">false</bool> </resources> ``` この変更はアプリ内のすべてのオンボーディングにグローバルに適用されます。 ## 次のステップ \{#next-steps\} オンボーディングを表示したら、[ユーザーのインタラクションとイベントの処理](react-native-handling-onboarding-events)について確認しましょう。オンボーディングイベントを処理して、ユーザーのアクションに応答したりアナリティクスを追跡したりする方法を学べます。 --- # File: react-native-handling-onboarding-events --- --- title: "React Native SDKでオンボーディングイベントを処理する" description: "Adaptyを使用してReact NativeでオンボーディングIng関連イベントを処理します。" --- ビルダーで設定されたオンボーディングは、アプリが応答できるイベントを生成します。これらのイベントの処理方法は、使用するプレゼンテーション方式によって異なります: - **モーダルプレゼンテーション**:すべてのオンボーディングビューのイベントを処理するイベントハンドラーのセットアップが必要 - **Reactコンポーネント**:ウィジェット内のインラインコールバックパラメーターを通じてイベントを処理 始める前に、以下を確認してください: 1. [Adapty React Native SDK](sdk-installation-reactnative) 3.8.0以降をインストール済みであること。 2. [オンボーディングを作成](create-onboarding)済みであること。 3. オンボーディングを[プレースメント](placements)に追加済みであること。 モバイルアプリ内のオンボーディング画面で発生するプロセスを制御・監視するには、イベントハンドラーを実装してください: <Tabs groupId="version" queryString> <TabItem value="new" label="SDK version 3.14 or later" default> <Tabs groupId="presentation-method" queryString> <TabItem value="platform" label="React component" default> Reactコンポーネントでは、`AdaptyOnboardingView`コンポーネントの個別のイベントハンドラープロップを通じてイベントを処理します: ```typescript showLineNumbers title="React Native (TSX)" function MyOnboarding({ onboarding }) { const onAnalytics = useCallback<OnboardingEventHandlers['onAnalytics']>((event, meta) => {}, []); const onClose = useCallback<OnboardingEventHandlers['onClose']>((actionId, meta) => {}, []); const onCustom = useCallback<OnboardingEventHandlers['onCustom']>((actionId, meta) => {}, []); const onPaywall = useCallback<OnboardingEventHandlers['onPaywall']>((actionId, meta) => {}, []); const onStateUpdated = useCallback<OnboardingEventHandlers['onStateUpdated']>((action, meta) => {}, []); const onFinishedLoading = useCallback<OnboardingEventHandlers['onFinishedLoading']>((meta) => {}, []); const onError = useCallback<OnboardingEventHandlers['onError']>((error) => {}, []); return ( <AdaptyOnboardingView onboarding={onboarding} style={styles.container} onAnalytics={onAnalytics} onClose={onClose} onCustom={onCustom} onPaywall={onPaywall} onStateUpdated={onStateUpdated} onFinishedLoading={onFinishedLoading} onError={onError} /> ); } ``` </TabItem> <TabItem value="standalone" label="Modal presentation"> モーダルプレゼンテーションでは、イベントハンドラーメソッドを実装します。 :::important `setEventHandlers`を複数回呼び出すと、提供したハンドラーが上書きされ、特定のイベントに対するデフォルトと以前に設定したハンドラーの両方が置き換えられます。 ::: ```javascript showLineNumbers title="React Native" const view = await createOnboardingView(onboarding); const unsubscribe = view.setEventHandlers({ onAnalytics(event, meta) { // Track analytics events }, onClose(actionId, meta) { // Handle close action view.dismiss(); return true; }, onCustom(actionId, meta) { // Handle custom actions }, onPaywall(actionId, meta) { // Handle paywall actions }, onStateUpdated(action, meta) { // Handle user input updates }, onFinishedLoading(meta) { // Onboarding finished loading }, onError(error) { // Handle loading errors }, }); try { await view.present(); } catch (error) { // handle the error } ``` </TabItem> </Tabs> </TabItem> <TabItem value="old" label="SDK version < 3.14"> SDKバージョン3.14未満では、モーダルプレゼンテーションのみサポートされています: ```javascript showLineNumbers title="React Native" const view = await createOnboardingView(onboarding); const unsubscribe = view.registerEventHandlers({ onAnalytics(event, meta) { // Track analytics events }, onClose(actionId, meta) { // Handle close action view.dismiss(); return true; }, onCustom(actionId, meta) { // Handle custom actions }, onPaywall(actionId, meta) { // Handle paywall actions }, onStateUpdated(action, meta) { // Handle user input updates }, onFinishedLoading(meta) { // Onboarding finished loading }, onError(error) { // Handle loading errors }, }); try { await view.present(); } catch (error) { // handle the error } ``` </TabItem> </Tabs> ## イベントの種類 \{#event-types\} 以下のセクションでは、使用するプレゼンテーション方式に関わらず処理できる各種イベントについて説明します。 ### カスタムアクションを処理する \{#handle-custom-actions\} ビルダーでボタンに**カスタム**アクションを追加してIDを割り当てることができます。 <img src="/assets/shared/img/ios-events-1.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> このIDをコード内で使用し、カスタムアクションとして処理できます。たとえば、ユーザーが**ログイン**や**通知を許可**などのカスタムボタンをタップすると、ビルダーの**Action ID**に対応する`actionId`パラメーターを持つイベントハンドラーがトリガーされます。「allowNotifications」のような独自のIDを作成できます。 <Tabs groupId="version" queryString> <TabItem value="new" label="SDK version 3.14 or later" default> <Tabs groupId="presentation-method" queryString> <TabItem value="platform" label="React component" default> ```typescript showLineNumbers title="React Native (TSX)" function MyOnboarding({ onboarding }) { const onCustom = useCallback<OnboardingEventHandlers['onCustom']>((actionId, meta) => { switch (actionId) { case 'login': login(); break; case 'allow_notifications': allowNotifications(); break; } }, []); return ( <AdaptyOnboardingView onboarding={onboarding} style={styles.container} onCustom={onCustom} /> ); } ``` </TabItem> <TabItem value="standalone" label="Modal presentation"> ```javascript showLineNumbers title="React Native" const view = await createOnboardingView(onboarding); const unsubscribe = view.setEventHandlers({ onCustom(actionId, meta) { switch (actionId) { case 'login': login(); break; case 'allow_notifications': allowNotifications(); break; } }, }); ``` </TabItem> </Tabs> </TabItem> <TabItem value="old" label="SDK version < 3.14"> ```javascript showLineNumbers title="React Native" const view = await createOnboardingView(onboarding); const unsubscribe = view.registerEventHandlers({ onCustom(actionId, meta) { switch (actionId) { case 'login': login(); break; case 'allow_notifications': allowNotifications(); break; } }, }); ``` </TabItem> </Tabs> <Details> <summary>イベントの例(クリックして展開)</summary> ```json { "actionId": "allow_notifications", "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 0, "screensTotal": 3 } } ``` </Details> ### オンボーディングの読み込み完了 \{#finishing-loading-onboarding\} オンボーディングの読み込みが完了すると、このイベントがトリガーされます: <Tabs groupId="version" queryString> <TabItem value="new" label="SDK version 3.14 or later" default> <Tabs groupId="presentation-method" queryString> <TabItem value="platform" label="React component" default> ```typescript showLineNumbers title="React Native (TSX)" function MyOnboarding({ onboarding }) { const onFinishedLoading = useCallback<OnboardingEventHandlers['onFinishedLoading']>((meta) => { console.log('Onboarding loaded:', meta.onboardingId); }, []); return ( <AdaptyOnboardingView onboarding={onboarding} style={styles.container} onFinishedLoading={onFinishedLoading} /> ); } ``` </TabItem> <TabItem value="standalone" label="Modal presentation"> ```javascript showLineNumbers title="React Native" const view = await createOnboardingView(onboarding); const unsubscribe = view.setEventHandlers({ onFinishedLoading(meta) { console.log('Onboarding loaded:', meta.onboardingId); }, }); ``` </TabItem> </Tabs> </TabItem> <TabItem value="old" label="SDK version < 3.14"> ```javascript showLineNumbers title="React Native" const view = await createOnboardingView(onboarding); const unsubscribe = view.registerEventHandlers({ onFinishedLoading(meta) { console.log('Onboarding loaded:', meta.onboardingId); }, }); ``` </TabItem> </Tabs> <Details> <summary>イベントの例(クリックして展開)</summary> ```json { "meta": { "onboarding_id": "onboarding_123", "screen_cid": "welcome_screen", "screen_index": 0, "total_screens": 4 } } ``` </Details> ### オンボーディングを閉じる \{#closing-onboarding\} ユーザーが**閉じる**アクションが割り当てられたボタンをタップすると、オンボーディングが閉じられたと判断されます。 <img src="/assets/shared/img/ios-events-2.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> :::important ユーザーがオンボーディングを閉じたときの動作は自分で管理する必要があります。たとえば、オンボーディング自体の表示を停止する処理が必要です。 ::: <Tabs groupId="version" queryString> <TabItem value="new" label="SDK version 3.14 or later" default> <Tabs groupId="presentation-method" queryString> <TabItem value="platform" label="React component" default> ```typescript showLineNumbers title="React Native (TSX)" function MyOnboarding({ onboarding, navigation }) { const onClose = useCallback<OnboardingEventHandlers['onClose']>((actionId, meta) => { navigation.goBack(); }, [navigation]); return ( <AdaptyOnboardingView onboarding={onboarding} style={styles.container} onClose={onClose} /> ); } ``` </TabItem> <TabItem value="standalone" label="Modal presentation"> ```javascript showLineNumbers title="React Native" const view = await createOnboardingView(onboarding); const unsubscribe = view.setEventHandlers({ onClose(actionId, meta) { await view.dismiss(); return true; }, }); ``` </TabItem> </Tabs> </TabItem> <TabItem value="old" label="SDK version < 3.14"> ```javascript showLineNumbers title="React Native" const view = await createOnboardingView(onboarding); const unsubscribe = view.registerEventHandlers({ onClose(actionId, meta) { await view.dismiss(); return true; }, }); ``` </TabItem> </Tabs> <Details> <summary>イベントの例(クリックして展開)</summary> ```json { "action_id": "close_button", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "final_screen", "screen_index": 3, "total_screens": 4 } } ``` </Details> ### ペイウォールを開く \{#opening-a-paywall\} :::tip オンボーディング内でペイウォールを開きたい場合は、このイベントを処理してください。オンボーディングを閉じた後にペイウォールを開きたい場合は、より簡単な方法があります。閉じるアクションを処理してイベントデータに依存せずにペイウォールを開いてください。 ::: オンボーディングでペイウォールを扱う最もシームレスな方法は、アクションIDをペイウォールのプレースメントIDと同じにすることです。 <Tabs groupId="version" queryString> <TabItem value="new" label="SDK version 3.14 or later" default> <Tabs groupId="presentation-method" queryString> <TabItem value="platform" label="React component" default> ```typescript showLineNumbers title="React Native (TSX)" function MyOnboarding({ onboarding }) { const onPaywall = useCallback<OnboardingEventHandlers['onPaywall']>((actionId, meta) => { openPaywall(actionId); }, []); return ( <AdaptyOnboardingView onboarding={onboarding} style={styles.container} onPaywall={onPaywall} /> ); } const openPaywall = async (placementId) => { // Implement your paywall opening logic here }; ``` </TabItem> <TabItem value="standalone" label="Modal presentation"> iOSでは、一度に表示できるビュー(ペイウォールまたはオンボーディング)は1つのみです。オンボーディングの上にペイウォールを表示した場合、バックグラウンドのオンボーディングをプログラムで制御することはできません。オンボーディングを閉じようとすると、代わりにペイウォールが閉じられ、オンボーディングが表示されたままになります。これを避けるために、ペイウォールを表示する前に常にオンボーディングビューを閉じてください。 ```javascript showLineNumbers title="React Native" const view = await createOnboardingView(onboarding); const unsubscribe = view.setEventHandlers({ onPaywall(actionId, meta) { view.dismiss().then(() => { openPaywall(actionId); }); }, }); const openPaywall = async (placementId) => { // Implement your paywall opening logic here }; ``` </TabItem> </Tabs> </TabItem> <TabItem value="old" label="SDK version < 3.14"> iOSでは、一度に表示できるビュー(ペイウォールまたはオンボーディング)は1つのみです。オンボーディングの上にペイウォールを表示した場合、バックグラウンドのオンボーディングをプログラムで制御することはできません。オンボーディングを閉じようとすると、代わりにペイウォールが閉じられ、オンボーディングが表示されたままになります。これを避けるために、ペイウォールを表示する前に常にオンボーディングビューを閉じてください。 ```javascript showLineNumbers title="React Native" const view = await createOnboardingView(onboarding); const unsubscribe = view.registerEventHandlers({ onPaywall(actionId, meta) { view.dismiss().then(() => { openPaywall(actionId); }); }, }); const openPaywall = async (placementId) => { // Implement your paywall opening logic here }; ``` </TabItem> </Tabs> <Details> <summary>イベントの例(クリックして展開)</summary> ```json { "action_id": "premium_offer_1", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "pricing_screen", "screen_index": 2, "total_screens": 4 } } ``` </Details> ### ナビゲーションの追跡 \{#tracking-navigation\} オンボーディングフロー中にナビゲーション関連のイベントが発生すると、アナリティクスイベントを受け取ります: <Tabs groupId="version" queryString> <TabItem value="new" label="SDK version 3.14 or later" default> <Tabs groupId="presentation-method" queryString> <TabItem value="platform" label="React component" default> ```typescript showLineNumbers title="React Native (TSX)" function MyOnboarding({ onboarding }) { const onAnalytics = useCallback<OnboardingEventHandlers['onAnalytics']>((event, meta) => { trackEvent(event.name, meta.onboardingId); }, []); return ( <AdaptyOnboardingView onboarding={onboarding} style={styles.container} onAnalytics={onAnalytics} /> ); } ``` </TabItem> <TabItem value="standalone" label="Modal presentation"> ```javascript showLineNumbers title="React Native" const view = await createOnboardingView(onboarding); const unsubscribe = view.setEventHandlers({ onAnalytics(event, meta) { trackEvent(event.name, meta.onboardingId); }, }); ``` </TabItem> </Tabs> </TabItem> <TabItem value="old" label="SDK version < 3.14"> ```javascript showLineNumbers title="React Native" const view = await createOnboardingView(onboarding); const unsubscribe = view.registerEventHandlers({ onAnalytics(event, meta) { trackEvent(event.name, meta.onboardingId); }, }); ``` </TabItem> </Tabs> `event`オブジェクトは以下のいずれかのタイプになります: |タイプ | 説明 | |------------|-------------| | `onboardingStarted` | オンボーディングの読み込みが完了したとき | | `screenPresented` | いずれかの画面が表示されたとき | | `screenCompleted` | 画面が完了したとき。オプションの`elementId`(完了した要素の識別子)とオプションの`reply`(ユーザーからの回答)を含みます。ユーザーが画面を抜けるアクションを実行したときにトリガーされます。 | | `secondScreenPresented` | 2番目の画面が表示されたとき | | `userEmailCollected` | 入力フィールドからユーザーのメールアドレスが収集されたときにトリガーされます | | `onboardingCompleted` | ユーザーが`final` IDを持つ画面に到達したときにトリガーされます。このイベントが必要な場合は、[最後の画面に`final` IDを割り当て](design-onboarding)てください。 | | `unknown` | 認識されないイベントタイプの場合。`name`(未知のイベントの名前)と`meta`(追加のメタデータ)を含みます | 各イベントには以下の`meta`情報が含まれます: | フィールド | 説明 | |------------|-------------| | `onboardingId` | オンボーディングフローの一意の識別子 | | `screenClientId` | 現在の画面の識別子 | | `screenIndex` | フロー内の現在の画面の位置 | | `screensTotal` | フロー内の画面の総数 | <Details> <summary>イベントの例(クリックして展開)</summary> ```javascript // onboardingStarted { "name": "onboarding_started", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "welcome_screen", "screen_index": 0, "total_screens": 4 } } // screenPresented { "name": "screen_presented", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "interests_screen", "screen_index": 2, "total_screens": 4 } } // screenCompleted { "name": "screen_completed", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "profile_screen", "screen_index": 1, "total_screens": 4 }, "params": { "element_id": "profile_form", "reply": "success" } } // secondScreenPresented { "name": "second_screen_presented", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "profile_screen", "screen_index": 1, "total_screens": 4 } } // userEmailCollected { "name": "user_email_collected", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "profile_screen", "screen_index": 1, "total_screens": 4 } } // onboardingCompleted { "name": "onboarding_completed", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "final_screen", "screen_index": 3, "total_screens": 4 } } ``` </Details> --- # File: react-native-onboarding-input --- --- title: "React Native SDKでオンボーディングのデータを処理する" description: "Adapty SDKを使用してReact NativeアプリでオンボーディングからのデータをSaveし、活用する方法を紹介します。" --- ユーザーがクイズの質問に回答したり、入力フィールドにデータを入力したりすると、`onStateUpdatedAction` メソッドが呼び出されます。フィールドのタイプをコード内でSaveしたり、処理したりすることができます。 例: ```javascript // Full-screen presentation const unsubscribe = view.setEventHandlers({ onStateUpdated(action, meta) { // Process data }, }); // Embedded widget <AdaptyOnboardingView onboarding={onboarding} eventHandlers={{ onStateUpdated(action, meta) { // Process data }, }} /> ``` アクションのフォーマットについては[こちら](https://react-native.adapty.io/types/onboardingstateupdatedaction)を参照してください。 <Details> <summary>保存されたデータの例(実装によってフォーマットが異なる場合があります)</summary> ```javascript // Example of a saved select action { "elementId": "preference_selector", "meta": { "onboardingId": "onboarding_123", "screenClientId": "preferences_screen", "screenIndex": 1, "screensTotal": 3 }, "params": { "type": "select", "value": { "id": "option_1", "value": "premium", "label": "Premium Plan" } } } // Example of a saved multi-select action { "elementId": "interests_selector", "meta": { "onboardingId": "onboarding_123", "screenClientId": "interests_screen", "screenIndex": 2, "screensTotal": 3 }, "params": { "type": "multiSelect", "value": [ { "id": "interest_1", "value": "sports", "label": "Sports" }, { "id": "interest_2", "value": "music", "label": "Music" } ] } } // Example of a saved input action { "elementId": "name_input", "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 0, "screensTotal": 3 }, "params": { "type": "input", "value": { "type": "text", "value": "John Doe" } } } // Example of a saved date picker action { "elementId": "birthday_picker", "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 0, "screensTotal": 3 }, "params": { "type": "datePicker", "value": { "day": 15, "month": 6, "year": 1990 } } } ``` </Details> ## ユースケース \{#use-cases\} ### ユーザープロファイルにデータを付加する \{#enrich-user-profiles-with-data\} 入力データをユーザープロファイルとすぐに紐付けて、同じ情報を二度尋ねないようにするには、アクションを処理する際に入力データで[ユーザープロファイルを更新](react-native-setting-user-attributes)する必要があります。 たとえば、`name` というIDのテキストフィールドでユーザーに名前を入力してもらい、その値をユーザーのファーストネームとして設定したいとします。また、`email` フィールドでメールアドレスも入力してもらうとします。アプリのコードでは、次のようになります。 ```javascript showLineNumbers // Full-screen presentation const unsubscribe = view.setEventHandlers({ onStateUpdated(action, meta) { // Store user preferences or responses if (action.elementType === 'input') { const profileParams = {}; // Map elementId to appropriate profile field switch (action.elementId) { case 'name': if (action.value.type === 'text') { profileParams.firstName = action.value.value; } break; case 'email': if (action.value.type === 'email') { profileParams.email = action.value.value; } break; } // Update profile if we have data to update if (Object.keys(profileParams).length > 0) { adapty.updateProfile(profileParams).catch(error => { // handle the error }); } } }, }); // Embedded widget <AdaptyOnboardingView onboarding={onboarding} eventHandlers={{ onStateUpdated(action, meta) { // Store user preferences or responses if (action.elementType === 'input') { const profileParams = {}; // Map elementId to appropriate profile field switch (action.elementId) { case 'name': if (action.value.type === 'text') { profileParams.firstName = action.value.value; } break; case 'email': if (action.value.type === 'email') { profileParams.email = action.value.value; } break; } // Update profile if we have data to update if (Object.keys(profileParams).length > 0) { adapty.updateProfile(profileParams).catch(error => { // handle the error }); } } }, }} /> ``` ### アンケートの回答に基づいてペイウォールをカスタマイズする \{#customize-paywalls-based-on-answers\} オンボーディングでクイズを使用することで、オンボーディング完了後にユーザーに表示するペイウォールをカスタマイズすることもできます。 たとえば、スポーツの経験についてユーザーに質問し、ユーザーグループごとに異なるCTAやプロダクトを表示することができます。 1. オンボーディングビルダーで[クイズを追加](onboarding-quizzes)し、各選択肢に意味のあるIDを割り当てます。 2. IDに基づいてクイズの回答を処理し、ユーザーに[カスタム属性を設定](react-native-setting-user-attributes)します。 ```javascript showLineNumbers // Full-screen presentation const unsubscribe = view.setEventHandlers({ onStateUpdated(action, meta) { // Handle quiz responses and set custom attributes if (action.elementType === 'select') { const profileParams = {}; // Map quiz responses to custom attributes switch (action.elementId) { case 'experience': // Set custom attribute 'experience' with the selected value (beginner, amateur, pro) profileParams.codableCustomAttributes = { experience: action.value.value }; break; } // Update profile if we have data to update if (Object.keys(profileParams).length > 0) { adapty.updateProfile(profileParams).catch(error => { // handle the error }); } } }, }); // Embedded widget <AdaptyOnboardingView onboarding={onboarding} eventHandlers={{ onStateUpdated(action, meta) { // Handle quiz responses and set custom attributes if (action.elementType === 'select') { const profileParams = {}; // Map quiz responses to custom attributes switch (action.elementId) { case 'experience': // Set custom attribute 'experience' with the selected value (beginner, amateur, pro) profileParams.codableCustomAttributes = { experience: action.value.value }; break; } // Update profile if we have data to update if (Object.keys(profileParams).length > 0) { adapty.updateProfile(profileParams).catch(error => { // handle the error }); } } }, }} /> ``` 3. カスタム属性の値ごとに[セグメントを作成](segments)します。 4. [プレースメント](placements)を作成し、作成した各セグメントに対して[オーディエンス](audience)を追加します。 5. アプリのコードで、そのプレースメントに対する[ペイウォールを表示](react-native-paywalls)します。オンボーディングにペイウォールを開くボタンがある場合は、[このボタンのアクションへの応答](react-native-handling-onboarding-events#opening-a-paywall)としてペイウォールのコードを実装してください。 --- # File: react-native-sdk-call-order --- --- title: "React Native SDKの呼び出し順序" description: "Adapty SDKのメソッドを正しい順序で呼び出すことで、プレミアムアクセスの喪失、アトリビューションの欠落、断続的な#2002エラーを防ぎます。" --- `adapty.activate()` が完了してから、他のAdapty SDKメソッドを呼び出す必要があります。解決されるまで、SDKは状態を持ちません。`activate()` の前または並行して発行された呼び出しは、[`#2002 notActivated`](react-native-handle-errors#custom-network-codes) で失敗します。 アプリがユーザーを認証し、起動後にカスタマーユーザーIDを取得する場合は、その時点で `adapty.identify()` を呼び出してください。`identify` が解決されるまで、ユーザーアクションメソッドを呼び出さないでください。並行して実行される呼び出しは [`#3006 profileWasChanged`](react-native-handle-errors#custom-network-codes) で失敗するか、アクティベーション時に作成された匿名プロファイルに対して実行されます。これが起こると、アトリビューション、`appsflyer_id` などのMMP ID、インストールの所有権が識別済みプロファイルに常に転送されるとは限りません。アプリがユーザーを認証しない場合は、`identify` をスキップして匿名プロファイルで作業を続けてください。 MMP・アナリティクスSDK(AppsFlyer、Adjust、Branch、PostHog)も同じルールに従います。先に初期化してUID コールバックを待ってから `adapty.activate` を呼び出してください。そうしないと、MMP IDが短命の匿名プロファイルに紐付けられ、識別済みプロファイルに常に転送されるとは限りません。AppsFlyerの詳細については、[AppsFlyer](appsflyer) を参照してください。 ## 正しい順序 \{#the-correct-order\} どのパスを取るかは、カスタマーユーザーIDをいつ知るか、MMP・アナリティクスSDKを使用するかどうかの2点によって決まります。 - **ステップ2と5**: すべてのアプリで必須です。SDKをアクティベートしてから、SDKメソッドを呼び出します。 - **ステップ1と3**: MMP・アナリティクスSDK(AppsFlyer、Adjust、Branch、PostHog)を統合する場合のみ必要です。 - **ステップ4**: アプリがユーザーを認証し、起動後にカスタマーユーザーIDを収集する場合のみ必要です。 アプリ起動時にカスタマーユーザーIDがわかっている場合は、`activate()` に直接渡してください(ステップ2a)。このパスでは匿名プロファイルが作成されないため、ステップ4は不要です。 | ステップ | 呼び出し | タイミング | 備考 | |------|---------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------| | 1 | MMP・アナリティクスSDKを初期化する(AppsFlyer、Adjust、PostHog、Branch) | アプリ起動時、最初に | MMPのUIDコールバック(例: `getAppsFlyerUID`)を待ちます。 | | 2a | `adapty.activate('YOUR_PUBLIC_SDK_KEY', { customerUserId: 'YOUR_USER_ID' })` | アプリ起動時、ステップ1の後、カスタマーユーザーIDがある場合 | 推奨。匿名プロファイルは一切作成されません。 | | 2b | `adapty.activate('YOUR_PUBLIC_SDK_KEY')` (`customerUserId` なし) | アプリ起動時、ステップ1の後、カスタマーユーザーIDがない場合(または収集しない場合) | Adaptyが匿名プロファイルを作成します。 | | 3 | 各MMPに対して `adapty.updateAttribution(data, source, networkUserId)` | ステップ2の後、ユーザーアクション呼び出しの前 | MMP IDを正しいプロファイルに紐付けるために必要です。 | | 4 | `await adapty.identify('YOUR_USER_ID')` | ステップ3の後(MMPなしの場合はステップ2の後)、ステップ5の前 — 認証ありのパス2bのみ | 必ず `await` を使用してください。`identify` 中の並行呼び出しは `#3006 profileWasChanged` を発生させます。 | | 5 | `getPaywall`、`getPaywallProducts`、`restorePurchases`、`makePurchase`、`updateAttribution`、`updateProfile` | `identify` を呼び出す場合はステップ4の後、それ以外はステップ3の後(MMPなしの場合はステップ2の後) | これらの呼び出しには安定したプロファイルが必要です。 | :::important これらのステップをスキップすると、リピートユーザーのプレミアムアクセス喪失、プロファイルへの `appsflyer_id` の欠落、誤ったオーディエンスに対してペイウォールが返されるといった問題が発生します。 ::: ## Web2appおよびウェブファネルからのインストール \{#web2app-and-web-funnel-installs\} ユーザーがウェブチェックアウト(Stripe、Paddle)で購入し、その後ネイティブアプリをインストールした場合、デバイス最初の `activate()` が新しい匿名プロファイルを作成します。このプロファイルはウェブプロファイルとリンクされません。アプリ起動前にカスタマーユーザーIDを解決できる場合(認証フローやインストールリファラーから)、`activate()` に直接渡してください。そうでない場合、`identify('YOUR_USER_ID')` を呼び出してから `restorePurchases` を呼び出すまで、ウェブ購入はデバイス上で表示されません。 各ウェブチェックアウトで送信するメタデータについては、以下を参照してください: - [Stripe](stripe) - [Paddle](paddle) --- # File: react-native-optimize-paywall-fetching --- --- title: "React Native SDKでのペイウォール取得を最適化する" description: "Adaptyのペイウォールを確実に取得する:React Nativeのタイミング、キャッシュ、フォールバックのパターン。" --- React Nativeでペイウォールを確実に取得するには、高速なレンダリング、オーディエンスターゲティングが適用されたペイウォールの返却、そしてネットワークが遅い場合のグレースフルなフォールバックという3つの要件を満たす必要があります。以下のルールでは、それを実現するためのタイミング、キャッシュ、フォールバックのパターンを説明します。 :::tip これらのルールは、`adapty.activate()` と `adapty.identify()` がすでに解決済みであることを前提としています。詳しくは[React Native SDKのコール順序](react-native-sdk-call-order)をご覧ください。 ::: ## ルールと注意点 \{#rules-and-pitfalls\} | 推奨する方法 | 避けるべき方法 | 理由 | |---|---|---| | 表示しようとしているプレースメントのみを取得する。 | 起動時にすべてのプレースメントを並列で事前取得する。 | 一括事前取得はJSスレッドをブロックし、バーストの間にブラックスクリーンが発生する。 | | アトリビューションが解決される機会があった後に `getPaywall` を取得する — たとえば、`activate` の1〜2秒後、または `onProfileUpdate` が発火した後。 | ルートコンポーネントのマウント時に `getPaywall` を呼び出す。 | アトリビューションがまだ適用されていない。ペイウォールがデフォルトのオーディエンスに対して解決され、セグメントやASAのパーソナライゼーションが無効になる。 | | `loadTimeoutMs` を設定し、すべてのプレースメントに[フォールバックペイウォール](fallback-paywalls)を設定する。 | `getPaywall` を無期限に待機する。 | タイムアウトなしでは、接続状況が悪いユーザーはネットワークが解決されるまで空白の画面を見続けるか、アプリを閉じてしまう。 | `fetchPolicy` と `loadTimeoutMs` パラメーターのリファレンスは[ペイウォールとプロダクトの取得](fetch-paywalls-and-products-react-native)を、適切なプレースメントの選択は[プレースメント](placements)をご覧ください。 ## 接続状況が悪い場合のチューニング \{#tune-for-poor-connectivity\} 接続状況が継続的に悪い市場(農村部、乗り物での移動中、ルーティングの影響を受ける地域)向けには: - 最初の取得を除くすべての取得に `fetchPolicy: .returnCacheDataElseLoad` を設定する。 - Adaptyダッシュボードですべてのプレースメントに[フォールバックペイウォール](fallback-paywalls)を設定する。 - `loadTimeoutMs` を3〜5秒に設定し、タイムアウトが発火したときはフォールバックを受け入れる。 - `getProfile()` の完了をペイウォール表示の条件にしない。`getPaywall` を独立して呼び出すことで、プロファイルの遅延がUIをブロックしないようにする。 --- # File: react-native-show-aa-targeted-paywall --- --- title: "React Native SDKで初回起動時にAA対象のペイウォールを表示する" description: "React NativeでApple Ads向けのペイウォールをすぐに表示し、AdaptyProfile.appliedAttributionSourcesを使用してアトリビューションが適用されたときにApple Ads ユーザー向けにアップグレードする方法を解説します。" --- Apple Ads(AA)のアトリビューションは、`adapty.activate()` の後に非同期で届きます。初回起動時はまだ届いていないことが多いため、`getPaywall` はデフォルトのオーディエンスに対して解決され、Apple Ads ユーザーが AA セグメント対象のペイウォールを見逃してしまいます。アトリビューションが届くまでペイウォールの表示を遅らせるのではなく、まずすぐにペイウォールを表示し、AA アトリビューションが適用されたらリフレッシュするようにしましょう。これにより、Apple Ads ユーザーはターゲット向けのバリアントを受け取り、それ以外のユーザーは待たずにペイウォールを見ることができます。`AdaptyProfile.appliedAttributionSources` で AA アトリビューションが適用されたタイミングを確認できます。 ## 始める前に \{#before-you-start\} 以下が必要です: - Adapty React Native SDK **3.17.1** 以降。 - Adapty でアプリの Apple Ads が設定済みであること。[Apple Ads](apple-search-ads) を参照してください。 ## 仕組み \{#how-it-works\} `adapty.activate()` の後、SDK はバックグラウンドで Apple から Apple Ads のアトリビューションをリクエストし、その結果を Adapty のバックエンドに転送します。AA がプロファイルのアクティブなアトリビューションソースになると、SDK は `onLatestProfileLoad` リスナーに更新された `AdaptyProfile` を届けます。この時点で `appliedAttributionSources` 配列に `'apple_search_ads'` が含まれています。 これにより、ペイウォールの読み込みを2段階で行うことができます: 1. すぐに `getPaywall` を呼び出します。アトリビューションがまだ適用されていないため、Adapty はデフォルトのオーディエンスに対してリクエストを解決し、ユーザーはすぐにペイウォールを見ることができます。 2. `'apple_search_ads'` が現れたら、再度 `getPaywall` を呼び出します。Adapty は今度は Apple Ads のオーディエンスに対してリクエストを解決し、ターゲット向けのペイウォールを返します。これが最初のペイウォールと置き換わります。 `appliedAttributionSources` は空または存在しない場合があります。これは次のどちらかを意味します: - このプロファイルに対して Apple Ads のアトリビューションがまだ処理されていない、または - アトリビューションが全く届いていない。 いずれの場合でも、ステップ1は安全です。Adapty は現在のプロファイル状態に合致するオーディエンス(通常はデフォルトオーディエンス)に対してリクエストを解決します。ステップ2は `'apple_search_ads'` が現れたときだけ実行されます。 :::important その後の起動では、キャッシュされたプロファイルにすでに `appliedAttributionSources` に `'apple_search_ads'` が含まれているため、最初の `getPaywall` からすでに Apple Ads セグメント対象のペイウォールが返されます。2回目のフェッチや見た目の変化は発生しません。この2段階のフローが重要になるのは、アトリビューションがまだ処理中の初回起動時のみです。 ::: ## 実装 \{#implementation\} すぐにペイウォールを表示し、`'apple_search_ads'` を監視して届いたらペイウォールをリフレッシュします。 1. **SDKを有効化します。** [React Native SDKのインストールと設定](sdk-installation-reactnative)を参照してください。 2. **通常どおり `getPaywall` でペイウォールを読み込んで表示します。** アトリビューションを待たずに進めてください。 3. **`adapty.addEventListener('onLatestProfileLoad', …)` でプロファイルの更新を購読し**、`'apple_search_ads'` を監視します。現れたらペイウォールを再度フェッチし、更新されたものを表示します。リスナーをまだ設定していない場合は、[サブスクリプション更新のリッスン](react-native-check-subscription-status#listen-to-subscription-updates)を参照してください: ```typescript const subscription = adapty.addEventListener('onLatestProfileLoad', async profile => { if (!profile.appliedAttributionSources?.includes('apple_search_ads')) return; const targeted = await adapty.getPaywall(placementId); // present the targeted paywall in place of the first one }); // Call subscription.remove() after the upgrade, or after a timeout (see below). ``` 4. **タイムアウト後にリッスンを停止します。** ほとんどのユーザーは Apple Ads のアトリビューションを受け取らないため、セッション全体でリスナーを開き続けるのではなく、しばらくしたらリスナーを削除してください。リクエストが失敗した場合でもユーザーに常に何かが表示されるよう、そのプレースメントに[フォールバックペイウォール](react-native-use-fallback-paywalls)を設定してください。 ## 完全な実装例 \{#complete-example\} `onAppleAdsAttribution` は Apple Ads のアトリビューションが適用されると解決し、`timeoutMs` 以内に届かなければ拒否されます。以下の使用例では、すぐにペイウォールを読み込み、アトリビューションが届いたら再フェッチします。Apple Ads ユーザーはターゲット向けのペイウォールを受け取り、アトリビューションが届かなかった場合は最初のペイウォールがそのまま表示されます: ```typescript const APPLE_ADS_SOURCE = 'apple_search_ads'; const placementId = 'YOUR_PLACEMENT_ID'; function hasAppleAdsAttribution(profile: AdaptyProfile): boolean { return profile.appliedAttributionSources?.includes(APPLE_ADS_SOURCE) ?? false; } /** * Resolves once Apple Ads attribution is applied to the profile. * Rejects with a timeout error if attribution never arrives within `timeoutMs`. * Call after `adapty.activate()`. */ export function onAppleAdsAttribution(timeoutMs: number): Promise<void> { return new Promise((resolve, reject) => { let timer: ReturnType<typeof setTimeout> | undefined; let subscription: { remove: () => void } | undefined; const stop = () => { clearTimeout(timer); subscription?.remove(); }; subscription = adapty.addEventListener('onLatestProfileLoad', profile => { if (!hasAppleAdsAttribution(profile)) return; stop(); resolve(); }); timer = setTimeout(() => { stop(); reject(new Error(`Apple Ads attribution timed out after ${timeoutMs}ms`)); }, timeoutMs); }); } let paywall = await adapty.getPaywall(placementId); onAppleAdsAttribution(30_000) .then(() => adapty.getPaywall(placementId)) .then(updated => { paywall = updated; }) .catch(() => { console.log('Apple Ads attribution or loading failed'); }); ``` 初回起動時、Apple Ads ユーザーはデフォルトのペイウォールが置き換わる前に一瞬表示されることがあります。ペイウォールビルダーでペイウォールを表示している場合は、再表示が許容できるかどうかを検討するか、ペイウォールが表示される前にアップグレードを適用してください。`timeoutMs` は、どのくらいの間リッスンし続けるかに合わせて調整してください。届く場合のアトリビューションは通常、起動から数秒以内に届きます。 アプリがすでに別の目的(たとえば[サブスクリプションステータスの確認](react-native-check-subscription-status#listen-to-subscription-updates)など)で `onLatestProfileLoad` をリッスンしている場合は、変更の必要はありません。`adapty.addEventListener` は複数の独立したリスナーをサポートしているため、既存のリスナーに影響を与えることなく、このリスナーを追加できます。 --- # File: react-native-test --- --- title: "React Native SDK でのテストとリリース" description: "Adapty SDK を使って React Native アプリをテスト・リリースする方法を説明します。" --- Adapty SDK を React Native アプリに実装済みの場合、iOS と Android の両プラットフォームで SDK の統合とアプリ内課金のフローが正しく動作しているかをテストする必要があります。Apple のサンドボックス環境と Google Play のテスト環境を使って、購入フローを確認しましょう。 ## アプリのテスト \{#test-your-app\} アプリ内課金の詳細なテスト方法については、プラットフォーム別のテストガイドをご参照ください:[iOS テストガイド](test-purchases-in-sandbox)、[Android テストガイド](testing-on-android)。 ## リリースの準備 \{#prepare-for-release\} アプリをストアに申請する前に、[リリースチェックリスト](release-checklist)に従って以下の項目を確認してください: - ストアの接続とサーバー通知が設定されている - 購入が完了し、Adapty に正しく報告されている - アクセスレベルが正しくアンロック・復元される - プライバシー要件とレビュー要件を満たしている --- # File: InvalidProductIdentifiers-react-native --- --- title: "React Native SDK の Code-1000 noProductIDsFound エラーの修正" description: "Adapty でサブスクリプションを管理する際に発生する無効なプロダクト識別子エラーを解決します。" --- 1000 コードのエラー `noProductIDsFound` は、ペイウォールでリクエストしたプロダクトが App Store に登録されているにもかかわらず、購入できる状態にないことを示しています。このエラーには `InvalidProductIdentifiers` 警告が伴う場合があります。警告のみでエラーが発生していない場合は、無視しても問題ありません。 `noProductIDsFound` エラーが発生している場合は、以下の手順で解決してください。 ## ステップ 1. バンドル ID を確認する \{#step-2-check-bundle-id\} --- no_index: true --- 1. [App Store Connect](https://appstoreconnect.apple.com/apps) を開きます。アプリを選択し、**General** → **App Information** セクションに進みます。 2. **General Information** サブセクションで **Bundle ID** をコピーします。 <Zoom> <img src="/docs/img/afd5012-bundle_id_apple.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> </Zoom> 3. Adapty のトップメニューから [**App settings** -> **iOS SDK** タブ](https://app.adapty.io/settings/ios-sdk) を開き、コピーした値を **Bundle ID** フィールドに貼り付けます。 <Zoom> <img src="/docs/img/2d64163-bundle_id.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> </Zoom> 4. App Store Connect の **App information** ページに戻り、**Apple ID** をコピーします。 5. Adapty ダッシュボードの [**App settings** -> **iOS SDK**](https://app.adapty.io/settings/ios-sdk) ページで、**Apple app ID** フィールドにその ID を貼り付けます。 ## ステップ 2. プロダクトを確認する \{#step-3-check-products\} 1. **App Store Connect** を開き、左側のメニューから [**Monetization** → **Subscriptions**](https://appstoreconnect.apple.com/apps/6477523342/distribution/subscriptions) に移動します。 <img src="/assets/shared/img/subscription_group_open.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. サブスクリプショングループ名をクリックすると、**Subscriptions** セクションにプロダクトの一覧が表示されます。 3. テスト中のプロダクトが **Ready to Submit** になっていることを確認します。 <img src="/assets/shared/img/ready-to-submit.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. 表示されているプロダクト ID と、Adapty ダッシュボードの [**Products**](https://app.adapty.io/products) タブにある ID を照合します。ID が一致しない場合は、表からプロダクト ID をコピーして、Adapty ダッシュボードでその ID を使って[プロダクトを作成](create-product)してください。 <img src="/assets/shared/img/product-id-copy.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## ステップ 3. プロダクトの提供状況を確認する \{#step-4-check-product-availability\} 1. **App Store Connect** に戻り、同じ **Subscriptions** セクションを開きます。 <img src="/assets/shared/img/subscription_group_open.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. サブスクリプショングループ名をクリックしてプロダクト一覧を表示します。 3. テスト中のプロダクトを選択します。 <img src="/assets/shared/img/click-product.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **Availability** セクションまでスクロールし、必要な国・地域がすべて表示されていることを確認します。 <img src="/assets/shared/img/product-availability.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## ステップ 4. プロダクトの価格を確認する \{#step-5-check-product-prices\} 1. 再度 **App Store Connect** の **Monetization** → **Subscriptions** セクションに移動します。 <img src="/assets/shared/img/subscription_group_open.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. サブスクリプショングループ名をクリックします。 3. テスト中のプロダクトを選択します。 <img src="/assets/shared/img/click-product.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **Subscription Pricing** までスクロールし、**Current Pricing for New Subscribers** セクションを展開します。 <img src="/assets/shared/img/check-prices.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. 必要な価格がすべて表示されていることを確認します。 <img src="/assets/shared/img/product-pricing.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## ステップ 5. アプリの有料ステータス・銀行口座・税務書類がアクティブか確認する \{#step-5-check-app-paid-status-bank-account-and-tax-forms-are-active\} 1. [**App Store Connect**](https://appstoreconnect.apple.com/) のホームページで **Business** をクリックします。 <img src="/assets/shared/img/business.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. 会社名を選択します。 <img src="/assets/shared/img/business-name.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. 下にスクロールして、**Paid Apps Agreement**、**Bank Account**、**Tax forms** がすべて **Active** になっていることを確認します。 <img src="/assets/shared/img/appstore-connect-status.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> これらの手順を実行することで、`InvalidProductIdentifiers` 警告を解消し、プロダクトをストアで公開できるようになるはずです。 ## ステップ 6. スタックしているプロダクトを再作成する \{#step-6-recreate-the-product-if-its-stuck\} ステップ 1〜5 をすべてクリアしている場合(`Approved` ステータス、バンドル ID 一致、有効な API キー)でも、SDK が `1000 noProductIDsFound` を返すことがあります。その場合、プロダクトが Apple のレジストリ内でスタックしている可能性があります。App Store Connect の UI 上にプロダクトが存在しているにもかかわらず、StoreKit のルックアップパスに公開されていない状態になることが稀にあります。 App Store Connect でそのプロダクトを削除し、同じプロダクト ID で再作成してください。再作成後、反映されるまで最大 24 時間かかる場合があります。 --- # File: cantMakePayments-react-native --- --- title: "React Native SDKにおけるCode-1003 cantMakePaymentエラーの修正" description: "AdaptyでサブスクリプションManagerする際の決済エラーを解決する方法。" --- 1003エラー(`cantMakePayments`)は、このデバイスでアプリ内課金ができないことを示しています。 `cantMakePayments`エラーが発生している場合、通常は以下のいずれかの原因が考えられます: - デバイスの制限:このエラーはAdaptyとは無関係です。以下の解決方法を参照してください。 - オブザーバーモードの設定:`makePurchase`メソッドとオブザーバーモードは同時に使用できません。以下のセクションを参照してください。 ## 問題:デバイスの制限 \{#issue-device-restrictions\} | 問題 | 解決方法 | |-----------------------------|---------------------------------------------------------| | スクリーンタイムの制限 | [スクリーンタイム](https://support.apple.com/en-us/102470)でアプリ内課金の制限を無効にする | | アカウントの停止 | Appleサポートに連絡してアカウントの問題を解決する | | 地域の制限 | 対応地域のApp Storeアカウントを使用する | ## 問題:オブザーバーモードとmakePurchaseの併用 \{#issue-using-both-observer-mode-and-makepurchase\} 購入処理に`makePurchase`を使用している場合、オブザーバーモードを使用する必要はありません。[オブザーバーモード](observer-vs-full-mode)が必要なのは、購入ロジックを自分で実装する場合のみです。 したがって、`makePurchase`を使用している場合は、SDK有効化コードからオブザーバーモードの有効化を安全に削除できます。 --- # File: migration-react-native-314 --- --- title: "Adapty React Native SDK を v3.14 に移行する" description: "Adapty React Native SDK v3.14 に移行して、パフォーマンスの向上と新しいマネタイズ機能を活用しましょう。" --- Adapty React Native SDK 3.14.0 はメジャーリリースであり、以下の対応が必要な変更が含まれています: - `registerEventHandlers` メソッドが `setEventHandlers` メソッドに置き換えられました。 - `AdaptyOnboardingView` では、イベントハンドラーが `eventHandlers` オブジェクトではなく個別の props として渡されるようになりました。 - UI コンポーネント向けの新しいシンプルなインポート方法が導入されました。 - `logShowOnboarding` メソッドが削除されました。 - React Native の最低バージョンが 0.73.0 に更新されました。 - ペイウォールとオンボーディングの iOS デフォルト表示スタイルがページシートからフルスクリーンに変更されました。 ## `registerEventHandlers` を `setEventHandlers` に置き換える \{#replace-registereventhandlers-with-seteventhandlers\} Adapty ペイウォールビルダーおよびオンボーディングビルダーで使用されていた `registerEventHandlers` メソッドが `setEventHandlers` メソッドに置き換えられました。 Adapty ペイウォールビルダーやオンボーディングビルダーを使用している場合は、アプリのコード内で `registerEventHandlers` を見つけて `setEventHandlers` に置き換えてください。 この変更はメソッドの動作をより明確にするために行われました。ハンドラーは `true`/`false` を返すため、1 つずつ処理されます。1 つのイベントに複数のハンドラーを設定すると、結果の動作が不明確になっていたためです。 `AdaptyOnboardingView` や `AdaptyPaywallView` などの React コンポーネントを使用する場合、自分自身の状態管理でコンポーネントの表示を制御するため、イベントハンドラーから `true`/`false` を返す必要はありません。戻り値が必要なのは、SDK がビューのライフサイクルを管理するモーダル画面表示の場合のみです。 :::important `setEventHandlers` を複数回呼び出すと、指定したハンドラーが上書きされ、デフォルトおよびそれ以前に設定したハンドラーが置き換えられます。 ::: ```diff showLineNumbers - const unsubscribe = view.registerEventHandlers({ - // your event handlers - }) const unsubscribe = view.setEventHandlers({ // your event handlers }) ``` ## UI コンポーネントのインポートパスを更新する \{#update-import-paths-for-ui-components\} Adapty SDK 3.14.0 では、UI コンポーネント向けのシンプルなインポート方法が導入されました。`react-native-adapty/dist/ui` からインポートする代わりに、`react-native-adapty` から直接インポートできるようになりました。 新しいインポート方法は標準的な React Native の慣行に沿っており、インポート文がよりシンプルになります。`AdaptyPaywallView` や `AdaptyOnboardingView` などの UI コンポーネントを使用している場合は、以下のようにインポートを更新してください: ```diff showLineNumbers - import { AdaptyPaywallView } from 'react-native-adapty/dist/ui'; + import { AdaptyPaywallView } from 'react-native-adapty'; - import { AdaptyOnboardingView } from 'react-native-adapty/dist/ui'; + import { AdaptyOnboardingView } from 'react-native-adapty'; - import { createPaywallView } from 'react-native-adapty/dist/ui'; + import { createPaywallView } from 'react-native-adapty'; - import { createOnboardingView } from 'react-native-adapty/dist/ui'; + import { createOnboardingView } from 'react-native-adapty'; ``` :::note 後方互換性のため、旧インポート方法(`react-native-adapty/dist/ui`)は引き続きサポートされています。ただし、一貫性と明確さのために新しいインポート方法の使用を推奨します。 ::: ## React コンポーネントのオンボーディングイベントハンドラーを更新する \{#update-onboarding-event-handlers-in-the-react-component\} オンボーディングのイベントハンドラーが、`AdaptyOnboardingView` の `eventHandlers` オブジェクトの外に移動されました。`AdaptyOnboardingView` を使用してオンボーディングを表示している場合は、イベント処理の構造を更新してください。 :::important イベントハンドラーの実装方法に注意してください。レンダリングのたびにオブジェクトが再生成されないようにするため、イベントを処理する関数には `useCallback` を使用してください。 ::: ```diff showLineNumbers import React, { useCallback } from 'react'; - import { AdaptyOnboardingView } from 'react-native-adapty/dist/ui'; + import { AdaptyOnboardingView } from 'react-native-adapty'; + import type { OnboardingEventHandlers } from 'react-native-adapty'; + + function MyOnboarding({ onboarding }) { + const onAnalytics = useCallback<OnboardingEventHandlers['onAnalytics']>((event, meta) => {}, []); + const onClose = useCallback<OnboardingEventHandlers['onClose']>((actionId, meta) => {}, []); + const onCustom = useCallback<OnboardingEventHandlers['onCustom']>((actionId, meta) => {}, []); + const onPaywall = useCallback<OnboardingEventHandlers['onPaywall']>((actionId, meta) => {}, []); + const onStateUpdated = useCallback<OnboardingEventHandlers['onStateUpdated']>((action, meta) => {}, []); + const onFinishedLoading = useCallback<OnboardingEventHandlers['onFinishedLoading']>((meta) => {}, []); + const onError = useCallback<OnboardingEventHandlers['onError']>((error) => {}, []); + return ( <AdaptyOnboardingView onboarding={onboarding} style={styles.container} - eventHandlers={{ - onAnalytics(event, meta) { /* ... */ }, - onClose(actionId, meta) { /* ... */ }, - onCustom(actionId, meta) { /* ... */ }, - onPaywall(actionId, meta) { /* ... */ }, - onStateUpdated(action, meta) { /* ... */ }, - onFinishedLoading(meta) { /* ... */ }, - onError(error) { /* ... */ }, - }} + onAnalytics={onAnalytics} + onClose={onClose} + onCustom={onCustom} + onPaywall={onPaywall} + onStateUpdated={onStateUpdated} + onFinishedLoading={onFinishedLoading} + onError={onError} /> ); + } ``` :::note 後方互換性のため、`eventHandlers` プロパティは引き続きサポートされていますが、非推奨となっています。上記のように個別のイベントハンドラープロパティへの移行を推奨します。 ::: ## `logShowOnboarding` を削除する \{#delete-logshowonboarding\} Adapty SDK 3.14.0 では、`logShowOnboarding` メソッドが SDK から削除されました。 このメソッドを使用していた場合、SDK をバージョン 3.14 以降にアップグレードすると利用できなくなります。 代わりに、[Adapty のノーコードオンボーディングビルダーでオンボーディングを作成](onboardings)できます。これらのオンボーディングのアナリティクスは自動的に追跡され、多くのカスタマイズオプションも利用できます。 ## React Native を更新する \{#update-react-native\} Adapty SDK 3.14.0 以降、React Native の最低サポートバージョンは 0.73.0 となります。それ以前のバージョンを使用している場合は、React Native を 0.73.0 以降に更新して、Adapty SDK を安定して利用できるようにしてください。 ## モーダルペイウォールとオンボーディングの iOS 表示スタイルを更新する \{#update-ios-presentation-style-for-modal-paywalls-and-onboardings\} Adapty SDK 3.14.0 では、`view.present()` メソッドを使用して表示するペイウォールとオンボーディングの iOS デフォルト表示スタイルがページシートからフルスクリーンに変更されました。 以前のページシート表示スタイルを維持したい場合は、`present()` メソッドに `iosPresentationStyle` パラメーターを渡してください: ```typescript showLineNumbers title="React Native (TSX)" try { await view.present({ iosPresentationStyle: 'page_sheet' }); } catch (error) { // handle the error } ``` --- # File: react-native-migration-guide-380 --- --- title: "Adapty React Native SDK を v3.8 に移行する" description: "パフォーマンス向上と新しいマネタイズ機能のために Adapty React Native SDK v3.8 に移行する。" --- Adapty SDK 3.8.0 はメジャーリリースであり、いくつかの改善が含まれていますが、移行手順が必要になる場合があります。 ## プレースメント取得パラメータの入力型を更新する \{#update-input-type-for-getting-placement-params\} `GetPaywallParamsInput` は `GetPlacementParamsInput` に名称変更されました: ```diff showLineNumbers - type GetPaywallParamsInput = { + type GetPlacementParamsInput = { placementId: string; locale?: string; fetchPolicy?: AdaptyPlacementFetchPolicy; loadTimeoutMs?: number; } ``` ## フォールバックメソッドを更新する \{#update-fallback-method\} フォールバックを設定するメソッドが更新され、フォールバックの場所を指定する型の名前が変更されました: ```diff showLineNumbers - adapty.setFallbackPaywalls(paywallsLocation: Input.FallbackPaywallsLocation); + adapty.setFallback(fileLocation: Input.FileLocation); ``` ## ペイウォールプロパティへのアクセスを更新する \{#update-paywall-property-access\} 以下のプロパティが `AdaptyPaywall` から `AdaptyPlacement` に移動されました: ```diff showLineNumbers - paywall.abTestName - paywall.audienceName - paywall.revision - paywall.placementId + paywall.placement.abTestName + paywall.placement.audienceName + paywall.placement.revision + paywall.placement.id ``` --- # File: migration-to-react-native-sdk-34 --- --- title: "Adapty React Native SDK を v3.4 に移行する" description: "Adapty React Native SDK v3.4 に移行して、パフォーマンスの向上と新しいマネタイズ機能を活用しましょう。" --- Adapty SDK 3.4.0 はメジャーリリースであり、移行作業が必要な改善が含まれています。 ## フォールバックペイウォールファイルの更新 \{#update-fallback-paywall-files\} 新しい SDK バージョンとの互換性を確保するために、フォールバックペイウォールファイルを更新してください。 1. Adapty ダッシュボードから[更新されたフォールバックペイウォールファイルをダウンロード](fallback-paywalls)します。 2. モバイルアプリ内の既存のフォールバックペイウォールを[新しいファイルに置き換え](react-native-use-fallback-paywalls)ます。 ## Observer Mode の実装を更新する \{#update-implementation-of-observer-mode\} Observer Mode を使用している場合は、その実装を更新してください。 以前は、トランザクションを Adapty に報告するために異なるメソッドが使用されていました。新しいバージョンでは、Android と iOS の両方で `reportTransaction` メソッドを一貫して使用する必要があります。このメソッドは各トランザクションを Adapty に明示的に報告し、認識されるようにします。ペイウォールを使用した場合は、バリエーション ID を渡してトランザクションをそのペイウォールに紐付けてください。 :::warning **トランザクションの報告を省略しないでください!** `reportTransaction` を呼び出さない場合、Adapty はトランザクションを認識できず、アナリティクスに表示されず、インテグレーションにも送信されません。 ::: ```diff showLineNumbers - if (Platform.OS === 'android') { - try { - await adapty.restorePurchases(); - } catch (error) { - // handle the error - } - } const variationId = paywall.variationId; try { await adapty.reportTransaction(transactionId, variationId); } catch (error) { // handle the `AdaptyError` } ``` --- # File: migration-to-react-native330 --- --- title: "Adapty React Native SDK を v3.3 に移行する" description: "パフォーマンス向上と新しいマネタイズ機能のために Adapty React Native SDK v3.3 に移行する。" --- Adapty SDK 3.3.1 はメジャーリリースであり、いくつかの改善が加えられています。移行作業が必要な場合があります。 1. Adapty SDK v3.3.x にアップグレードする。 2. モデルを更新する。 3. `getProductsIntroductoryOfferEligibility` メソッドを削除する。 4. 購入処理を更新する。 5. ペイウォールビルダーのペイウォール表示を更新する。 6. 開発者定義タイマーの実装を修正する。 7. ペイウォールビルダーの購入イベント処理を更新する。 8. ペイウォールビルダーのカスタムアクションイベント処理を更新する。 9. `onProductSelected` コールバックを修正する。 10. `updateProfile` メソッドからサードパーティ連携パラメーターを削除する。 11. Adjust、AirBridge、Amplitude、AppMetrica、Appsflyer、Branch、Facebook Ads、Firebase と Google Analytics、Mixpanel、OneSignal、Pushwoosh の連携設定を更新する。 12. オブザーバーモードの実装を更新する。 ## Adapty React Native SDK を 3.3.x にアップグレードする \{#upgrade-adapty-react-native-sdk-to-33x\} バージョン 3.3.1 より前は、`react-native-adapty` SDK がアプリで Adapty を正しく動作させるためのコアかつ必須の SDK でした。`@adapty/react-native-ui` SDK はオプションであり、Adapty ペイウォールビルダーを使用する場合にのみ必要でした。 バージョン 3.3.1 以降、`@adapty/react-native-ui` SDK は非推奨となり、その機能は `react-native-adapty` SDK に統合されました。バージョン 3.3.1 にアップグレードするには、以下の手順に従ってください。 1. `react-native-adapty` パッケージをバージョン 3.3.1 に更新する。 2. プロジェクトの依存関係から `@adapty/react-native-ui` パッケージを削除する。 3. プロジェクトの依存関係を同期して変更を適用する。 ## モデルの変更点 \{#changes-in-models\} ### 新しいモデル \{#new-models\} 1. [AdaptySubscriptionOffer](https://react-native.adapty.io/interfaces/adaptysubscriptionoffer): ```typescript showLineNumbers export interface AdaptySubscriptionOffer { readonly identifier: AdaptySubscriptionOfferId; phases: AdaptyDiscountPhase[]; android?: { offerTags?: string[]; }; } ``` 2. [AdaptySubscriptionOfferId](https://react-native.adapty.io/types/adaptysubscriptionofferid): ```typescript showLineNumbers export type AdaptySubscriptionOfferId = | { id?: string; type: 'introductory'; } | { id: string; type: 'promotional' | 'win_back'; }; ``` ### 変更されたモデル \{#changed-models\} 1. [AdaptyPaywallProduct](https://react-native.adapty.io/interfaces/adaptypaywallproduct): - `subscriptionDetails` プロパティを `subscription` に名前変更しました。 <p> </p> ```diff showLineNumbers - subscriptionDetails?: AdaptySubscriptionDetails; + subscription?: AdaptySubscriptionDetails; ``` 2. [AdaptySubscriptionDetails](https://react-native.adapty.io/interfaces/adaptysubscriptiondetails): - `promotionalOffer` は削除されました。プロモーションオファーは、利用可能な場合にのみ `offer` プロパティ経由で提供されるようになりました。この場合、`offer?.identifier?.type` は `'promotional'` になります。 - `introductoryOfferEligibility` は削除されました(オファーはユーザーが対象の場合のみ返されます)。 - `offerId` は削除されました。オファー ID は `AdaptySubscriptionOffer.identifier` に格納されるようになりました。 - `offerTags` は `AdaptySubscriptionOffer.android` に移動されました。 <p> </p> ```diff showLineNumbers - introductoryOffers?: AdaptyDiscountPhase[]; + offer?: AdaptySubscriptionOffer; ios?: { - promotionalOffer?: AdaptyDiscountPhase; subscriptionGroupIdentifier?: string; }; android?: { - offerId?: string; basePlanId: string; - introductoryOfferEligibility: OfferEligibility; - offerTags?: string[]; renewalType?: 'prepaid' | 'autorenewable'; }; } ``` 3. [AdaptyDiscountPhase](https://react-native.adapty.io/interfaces/adaptydiscountphase): - `identifier` フィールドが `AdaptyDiscountPhase` モデルから削除されました。オファー識別子は `AdaptySubscriptionOffer.identifier` に格納されるようになりました。 <p> </p> ```diff showLineNumbers - ios?: { - readonly identifier?: string; - }; ``` ### 削除されたモデル \{#remove-models\} 1. `AttributionSource`: - `AttributionSource` が以前使用されていた箇所では、文字列が使用されるようになりました。 2. `OfferEligibility`: - このモデルは不要になったため削除されました。オファーはユーザーが対象の場合にのみ返されるようになりました。 ## `getProductsIntroductoryOfferEligibility` メソッドを削除する \{#remove-getproductsintroductoryoffereligibility-method\} Adapty SDK 3.3.1 より前は、プロダクトオブジェクトにはユーザーが対象外であってもオファーが常に含まれていました。そのため、オファーを使用する前に手動で対象資格を確認する必要がありました。 バージョン 3.3.1 以降、プロダクトオブジェクトにはユーザーが対象の場合にのみオファーが含まれます。これにより、オファーが存在する場合はユーザーが対象であると仮定できるため、処理が簡素化されます。 ## 購入処理を更新する \{#update-making-purchase\} 以前のバージョンでは、キャンセルされた購入と保留中の購入はエラーとして扱われ、それぞれコード `2: 'paymentCancelled'` と `25: 'pendingPurchase'` が返されていました。 バージョン 3.3.1 以降、キャンセルされた購入と保留中の購入は成功した結果として扱われ、それに応じて処理する必要があります。 ```typescript showLineNumbers try { const purchaseResult = await adapty.makePurchase(product); switch (purchaseResult.type) { case 'success': const isSubscribed = purchaseResult.profile?.accessLevels['YOUR_ACCESS_LEVEL']?.isActive; if (isSubscribed) { // Grant access to the paid features } break; case 'user_cancelled': // Handle the case where the user canceled the purchase break; case 'pending': // Handle deferred purchases (e.g., the user will pay offline with cash) break; } } catch (error) { // Handle the error } ``` ## ペイウォールビルダーのペイウォール表示を更新する \{#update-paywall-builder-paywall-presentation\} 更新されたコード例については、[React Native でのペイウォールビルダーペイウォールの表示](react-native-present-paywalls)ドキュメントをご参照ください。 ```diff showLineNumbers - import { createPaywallView } from '@adapty/react-native-ui'; + import { createPaywallView } from 'react-native-adapty/dist/ui'; const view = await createPaywallView(paywall); view.registerEventHandlers(); // handle close press, etc try { await view.present(); } catch (error) { // handle the error } ``` ## 開発者定義タイマーの実装を更新する \{#update-developer-defined-timer-implementation\} `timerInfo` パラメーターを `customTimers` に名前変更してください。 ```diff showLineNumbers - let timerInfo = { 'CUSTOM_TIMER_NY': new Date(2025, 0, 1) } + let customTimers = { 'CUSTOM_TIMER_NY': new Date(2025, 0, 1) } //and then you can pass it to createPaywallView as follows: - view = await createPaywallView(paywall, { timerInfo }) + view = await createPaywallView(paywall, { customTimers }) ``` ## ペイウォールビルダーの購入イベントを修正する \{#modify-paywall-builder-purchase-events\} 以前の動作: - キャンセルされた購入は `onPurchaseCancelled` コールバックをトリガーしていました。 - 保留中の購入はエラーコード `25: 'pendingPurchase'` を返していました。 現在の動作: - 両方とも `onPurchaseCompleted` コールバックで処理されます。 #### 移行手順: 1. `onPurchaseCancelled` コールバックを削除する。 2. `25: 'pendingPurchase'` のエラーコード処理を削除する。 3. `onPurchaseCompleted` コールバックを更新する。 ```typescript showLineNumbers const view = await createPaywallView(paywall); const unsubscribe = view.registerEventHandlers({ // ... other optional callbacks onPurchaseCompleted(purchaseResult, product) { switch (purchaseResult.type) { case 'success': const isSubscribed = purchaseResult.profile?.accessLevels['YOUR_ACCESS_LEVEL']?.isActive; if (isSubscribed) { // Grant access to the paid features } break; // highlight-start case 'user_cancelled': // Handle the case where the user canceled the purchase break; case 'pending': // Handle deferred purchases (e.g., the user will pay offline with cash) break; // highlight-end } // highlight-start return purchaseResult.type !== 'user_cancelled'; // highlight-end }, }); ``` ## ペイウォールビルダーのカスタムアクションイベントを修正する \{#modify-paywall-builder-custom-action-events\} 削除されたコールバック: - `onAction` - `onCustomEvent` 追加されたコールバック: - 新しい `onCustomAction(actionId)` コールバック。カスタムアクションに使用してください。 ## `onProductSelected` コールバックを修正する \{#modify-onproductselected-callback\} 以前は、`onProductSelected` は `product` オブジェクトを必要としていました。現在は文字列として `productId` を必要とします。 ## `updateProfile` メソッドからサードパーティ連携パラメーターを削除する \{#remove-third-party-integration-parameters-from-updateprofile-method\} サードパーティ連携の識別子は、`setIntegrationIdentifier` メソッドを使用して設定するようになりました。`updateProfile` メソッドはこれらを受け付けなくなりました。 ## サードパーティ連携 SDK の設定を更新する \{#update-third-party-integration-sdk-configuration\} Adapty React Native SDK 3.3.1 以降で連携が正しく機能するよう、以下のセクションで説明する各連携の SDK 設定を更新してください。 また、アトリビューション識別子の取得に `AttributionSource` を使用していた場合は、必要な識別子を文字列として提供するようにコードを変更してください。 ### Adjust \{#adjust\} 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[Adjust 連携の SDK 設定](adjust#connect-your-app-to-adjust)をご確認ください。 ```diff showLineNumbers import { Adjust, AdjustConfig } from "react-native-adjust"; import { adapty } from "react-native-adapty"; var adjustConfig = new AdjustConfig(appToken, environment); // Before submiting Adjust config... adjustConfig.setAttributionCallbackListener(attribution => { // Make sure Adapty SDK is activated at this point // You may want to lock this thread awaiting of `activate` adapty.updateAttribution(attribution, "adjust"); }); // ... Adjust.create(adjustConfig); + Adjust.getAdid((adid) => { + if (adid) + adapty.setIntegrationIdentifier("adjust_device_id", adid); + }); ``` ### AirBridge \{#airbridge\} 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[AirBridge 連携の SDK 設定](airbridge#connect-your-app-to-airbridge)をご確認ください。 ```diff showLineNumbers import Airbridge from 'airbridge-react-native-sdk'; import { adapty } from 'react-native-adapty'; try { const deviceId = await Airbridge.state.deviceUUID(); - await adapty.updateProfile({ - airbridgeDeviceId: deviceId, - }); + await adapty.setIntegrationIdentifier("airbridge_device_id", deviceId); } catch (error) { // handle `AdaptyError` } ``` ### Amplitude \{#amplitude\} 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[Amplitude 連携の SDK 設定](amplitude#sdk-configuration)をご確認ください。 ```diff showLineNumbers import { adapty } from 'react-native-adapty'; try { - await adapty.updateProfile({ - amplitudeDeviceId: deviceId, - amplitudeUserId: userId, - }); + await adapty.setIntegrationIdentifier("amplitude_device_id", deviceId); + await adapty.setIntegrationIdentifier("amplitude_user_id", userId); } catch (error) { // handle `AdaptyError` } ``` ### AppMetrica \{#appmetrica\} 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[AppMetrica 連携の SDK 設定](appmetrica#sdk-configuration)をご確認ください。 ```diff showLineNumbers import { adapty } from 'react-native-adapty'; import AppMetrica, { DEVICE_ID_KEY, StartupParams, StartupParamsReason } from '@appmetrica/react-native-analytics'; // ... const startupParamsCallback = async ( params?: StartupParams, reason?: StartupParamsReason ) => { const deviceId = params?.deviceId if (deviceId) { try { - await adapty.updateProfile({ - appmetricaProfileId: 'YOUR_ADAPTY_CUSTOMER_USER_ID', - appmetricaDeviceId: deviceId, - }); + await adapty.setIntegrationIdentifier("appmetrica_profile_id", 'YOUR_ADAPTY_CUSTOMER_USER_ID'); + await adapty.setIntegrationIdentifier("appmetrica_device_id", deviceId); } catch (error) { // handle `AdaptyError` } } } AppMetrica.requestStartupParams(startupParamsCallback, [DEVICE_ID_KEY]) ``` ### AppsFlyer \{#appsflyer\} 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[AppsFlyer 連携の SDK 設定](appsflyer#connect-your-app-to-appsflyer)をご確認ください。 ```diff showLineNumbers import { adapty, AttributionSource } from 'react-native-adapty'; import appsFlyer from 'react-native-appsflyer'; appsFlyer.onInstallConversionData(installData => { try { - const networkUserId = appsFlyer.getAppsFlyerUID(); - adapty.updateAttribution(installData, AttributionSource.AppsFlyer, networkUserId); + const uid = appsFlyer.getAppsFlyerUID(); + adapty.setIntegrationIdentifier("appsflyer_id", uid); + adapty.updateAttribution(installData, "appsflyer"); } catch (error) { // handle the error } }); // ... appsFlyer.initSdk(/*...*/); ``` ### Branch \{#branch\} 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[Branch 連携の SDK 設定](branch#connect-your-app-to-branch)をご確認ください。 ```diff showLineNumbers import { adapty, AttributionSource } from 'react-native-adapty'; import branch from 'react-native-branch'; branch.subscribe({ enComplete: ({ params, }) => { - adapty.updateAttribution(params, AttributionSource.Branch); + adapty.updateAttribution(params, "branch"); }, }); ``` ### Facebook Ads \{#facebook-ads\} 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[Facebook Ads 連携の SDK 設定](facebook-ads#connect-your-app-to-facebook-ads)をご確認ください。 ```diff showLineNumbers import { adapty } from 'react-native-adapty'; import { AppEventsLogger } from 'react-native-fbsdk-next'; try { const anonymousId = await AppEventsLogger.getAnonymousID(); - await adapty.updateProfile({ - facebookAnonymousId: anonymousId, - }); + await adapty.setIntegrationIdentifier("facebook_anonymous_id", anonymousId); } catch (error) { // handle `AdaptyError` } ``` ### Firebase と Google Analytics \{#firebase-and-google-analytics\} 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[Firebase と Google Analytics 連携の SDK 設定](firebase-and-google-analytics)をご確認ください。 ```diff showLineNumbers import analytics from '@react-native-firebase/analytics'; import { adapty } from 'react-native-adapty'; try { const appInstanceId = await analytics().getAppInstanceId(); - await adapty.updateProfile({ - firebaseAppInstanceId: appInstanceId, - }); + await adapty.setIntegrationIdentifier("firebase_app_instance_id", appInstanceId); } catch (error) { // handle `AdaptyError` } ``` ### Mixpanel \{#mixpanel\} 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[Mixpanel 連携の SDK 設定](mixpanel#sdk-configuration)をご確認ください。 ```diff showLineNumbers import { adapty } from 'react-native-adapty'; import { Mixpanel } from 'mixpanel-react-native'; // ... try { - await adapty.updateProfile({ - mixpanelUserId: mixpanelUserId, - }); + await adapty.setIntegrationIdentifier("mixpanel_user_id", mixpanelUserId); } catch (error) { // handle `AdaptyError` } ``` ### OneSignal \{#onesignal\} 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[OneSignal 連携の SDK 設定](onesignal#sdk-configuration)をご確認ください。 <Tabs groupId="current-os" queryString> <TabItem value="v5+" label="OneSignal SDK v5+ (current)" default> ```diff showLineNumbers import { adapty } from 'react-native-adapty'; import OneSignal from 'react-native-onesignal'; OneSignal.User.pushSubscription.addEventListener('change', (subscription) => { const subscriptionId = subscription.current.id; if (subscriptionId) { - adapty.updateProfile({ - oneSignalSubscriptionId: subscriptionId, - }); + adapty.setIntegrationIdentifier("one_signal_subscription_id", subscriptionId); } }); ``` </TabItem> <TabItem value="pre-v5" label="OneSignal SDK v. up to 4.x (legacy)" default> ```diff showLineNumbers import { adapty } from 'react-native-adapty'; import OneSignal from 'react-native-onesignal'; OneSignal.addSubscriptionObserver(event => { const playerId = event.to.userId; - adapty.updateProfile({ - oneSignalPlayerId: playerId, - }); + adapty.setIntegrationIdentifier("one_signal_player_id", playerId); }); ``` </TabItem> </Tabs> ### Pushwoosh \{#pushwoosh\} 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[Pushwoosh 連携の SDK 設定](pushwoosh#sdk-configuration)をご確認ください。 ```diff showLineNumbers import { adapty } from 'react-native-adapty'; import Pushwoosh from 'pushwoosh-react-native-plugin'; // ... try { - await adapty.updateProfile({ - pushwooshHWID: hwid, - }); + await adapty.setIntegrationIdentifier("pushwoosh_hwid", hwid); } catch (error) { // handle `AdaptyError` } ``` ## オブザーバーモードの実装を更新する \{#update-observer-mode-implementation\} ペイウォールとトランザクションのリンク方法を更新してください。以前は `setVariationId` メソッドを使用して `variationId` を割り当てていました。現在は、新しい `reportTransaction` メソッドを使用してトランザクションを記録する際に `variationId` を直接含めることができます。最終的なコード例については、[オブザーバーモードでペイウォールを購入トランザクションに関連付ける](report-transactions-observer-mode-react-native)をご確認ください。 :::warning `reportTransaction` メソッドを使用してトランザクションを記録することを忘れないでください。この手順をスキップすると、Adapty はトランザクションを認識できず、アクセスレベルの付与、アナリティクスへの反映、連携へのデータ送信が行われません。この手順は必須です! ::: :::note `reportTransaction` メソッドのパラメーターの順序は `setVariationId` メソッドの順序と異なることにご注意ください。 ::: ```diff showLineNumbers const variationId = paywall.variationId; try { - await adapty.setVariationId(variationId, transactionId); + await adapty.reportTransaction(transactionId, variationId); } catch (error) { // handle the `AdaptyError` } ``` --- # File: migration-to-react-native-sdk-v3 --- --- title: "Adapty React Native SDK を v3.0 に移行する" description: "パフォーマンス向上と新しいマネタイズ機能のために Adapty React Native SDK v3.0 に移行します。" --- Adapty SDK v3.0 では、ペイウォールをノーコードで作成できる使いやすいツールの新バージョン [Adapty ペイウォールビルダー](adapty-paywall-builder) に対応しました。最大限の柔軟性と豊富なデザイン機能により、ペイウォールの効果と収益性を大幅に高められます。 ## バージョン 3.0.1 へのアップグレード \{#upgrade-to-version-301\} 1. 通常の手順でバージョン 3.0.1 にアップグレードします。 2. フォールバックペイウォールのファイルを差し替えます。 1. Adapty ダッシュボードから[最新バージョンをダウンロード](fallback-paywalls)します。 2. [こちら](react-native-use-fallback-paywalls)の手順に従って、ファイルをユーザーのデバイスに保存し、`.setFallbackPaywalls` メソッドに渡します。 --- # End of Documentation _Generated on: 2026-06-24T14:36:28.606Z_ _Successfully processed: 44/44 files_ # TUTORIAL - Adapty Documentation (Full Content) This file contains the complete content of all documentation pages for this platform. Locale: ja Generated on: 2026-06-24T14:36:28.608Z Total files: 265 --- # File: is-adapty-right-for-me --- --- title: "Adaptyは自分に合っていますか?" description: "Adaptyがあなたのユースケースに適しているかを確認しましょう。新しいアプリのローンチ、収益の最適化、他ツールからの移行など — まずはここから始めてください。" --- Adaptyはモバイルアプリ向けのアプリ内課金プラットフォームです。サブスクリプション、買い切り購入、消耗型アイテムに対応し、購入処理・レシート検証からアナリティクス、A/B テスト、インテグレーションまでをカバーします。 さまざまなシナリオでのAdaptyの活用方法をご紹介します。 ## アプリ内課金を含む新しいアプリをリリースする場合 \{#im-launching-a-new-app-with-in-app-purchases\} サブスクリプション、買い切り購入、消耗型アイテムのいずれを販売する場合でも、Adaptyはフルスタックをカバーします。 - **7プラットフォーム対応のSDK**: iOS、Android、React Native、Flutter、Unity、Kotlin Multiplatform、Capacitor。 - **購入処理**: 更新・リトライロジック付きのサブスクリプション、買い切り購入、消耗型アイテム、レシート検証 — すべて自動管理。 - **ノーコードのペイウォールビルダー**: UIコードを書かずにペイウォールのデザインとリリースが可能。 - **初日からのアナリティクス**: 最初のユーザーが来た瞬間から、収益・トライアル・コンバージョンなどを追跡。 さっそく始めましょう。[クイックスタートガイド](quickstart)をご覧ください。 ## A/B テスト、アナリティクス、インテグレーションを活用したい場合 \{#i-want-ab-tests-analytics-and-integrations\} Adaptyはすでに機能しているものをさらに最適化するのに役立ちます。 - **A/B テスト**: 価格、ペイウォールのデザイン、トライアル期間、プロモーションオファーをテストして、最もコンバージョンが高い組み合わせを見つけましょう。[Growth Autopilot](autopilot)を使えば、2万以上のサブスクリプションアプリのデータをもとに、あなたのアプリに最適化されたA/B テストの提案を受け取れます。 - **アナリティクスチャート**: MRR、LTV、チャーン、リテンション、その他数十種類の指標を追跡。 - **オーディエンスセグメンテーション**: 特定のユーザーグループに合わせたペイウォールとオファーを提供。 - **ペイウォールのリモート設定**: アプリの新バージョンをリリースせずにペイウォールを改善。 - **サードパーティ連携**: 購入イベントをAmplitude、AppsFlyer、Adjust、Mixpanelなど既存ツールに送信。 [A/B テスト](ab-tests)、[アナリティクス](analytics)、[アナリティクスサービスインテグレーション](analytics-integration)、[アトリビューションサービスインテグレーション](attribution-integration)をご確認ください。 ## LLMを使ってアプリ内課金を実装したい場合 \{#i-want-to-implement-in-app-purchases-with-an-llm\} AdaptyのドキュメントはCursor、Claude、ChatGPTなどのAIコーディングアシスタントに最適化されています。すべてのページがプレーンMarkdownで提供されており、各プラットフォーム向けのLLM支援による実装ガイドも用意しています。 - **コピペ対応のガイド**: ガイドをLLMに渡すだけで、実装の各ステップをサポートしてもらえます。 - **Markdownアクセス**: ドキュメントのURLに`.md`を追加するか、**Copy for LLM**をクリックしてクリーンなテキスト版を取得。 - **Context7 MCPサポート**: AdaptyのドキュメントをLLM対応のIDEに直接接続。 プラットフォームを選んで始めましょう: [AIアシスタントでAdaptyを統合する](adapty-cursor)。 ## Apple Ads キャンペーンを運用・最適化したい場合 \{#i-want-to-run-and-optimize-apple-ads-campaigns\} Apple Search Adsを運用している場合、AdaptyのApple Ads Managerを使えばMMPなしでキャンペーンパフォーマンスと収益指標を直接連携できます。 - **リアルタイムのパフォーマンスデータ**: キャンペーン、広告グループ、キーワードを追跡。 - **エンドツーエンドの収益追跡**: 検索からインストール、トライアル、サブスクリプション、LTVまでの流れを把握。 - **AI予測とレコメンデーション**: リターンを予測し、スケールアップの提案を受け取れます。 - **ルールベースの自動化**: CPAとROASの目標を安定して維持。 [Apple Ads Manager](adapty-ads-manager)を使って始めましょう。 ## ユーザーの流入元を把握したい場合 \{#i-want-to-track-where-my-users-come-from\} Adapty User Acquisitionは広告費とアプリのインストール・サブスクリプション収益を結びつける組み込みのアトリビューションソリューションです。 - **統合マーケティングダッシュボード**: すべてのチャネルのROAS、インストール数、収益を一画面で確認。 - **組み込みアトリビューション**: 外部のMMPに依存せず、広告キャンペーンとインストール・収益を連携。 - **トラッキングリンク**: Adaptyでリンクを生成してキャンペーンに追加するだけで、正確なアトリビューションを実現。 - **遅延ディープリンク**: クリック時にアプリが未インストールでも、インストール後に正しいコンテンツへ誘導。 - **コホート分析**: 時系列でのユーザー獲得パフォーマンスと行動を分析。 [Adapty User Acquisition](adapty-user-acquisition)について詳しく見る。 ## アプリのリリースなしに素早くイテレーションしたい場合 \{#i-want-to-iterate-fast-without-app-releases\} Adaptyを一度統合すれば、日常業務のほとんどはダッシュボード上で完結します — 新しいアプリバージョンは不要です。 - **ノーコードのペイウォールビルダー**: ビジュアルエディタでペイウォールをデザイン・更新し、即時公開。 - **ダッシュボードからのA/B テスト**: コードを触らずに実験を開始し、価格の調整やオファーの入れ替えが可能。 - **ダッシュボードアナリティクス**: 収益、チャーン、トライアル、コンバージョンをリアルタイムで監視。 - **SlackとEmailのレポート**: チームにとって重要な指標の自動レポートを受信。 [ペイウォールビルダー](adapty-paywall-builder)を試すか、[アナリティクス](charts)をご覧ください。 ## Webで販売しており、モバイルアプリも追加したい場合 \{#i-sell-on-the-web-and-need-a-mobile-app\} ユーザーがすでにWebサイトで支払いをしていて、モバイルアプリを追加する場合、Adaptyはプラットフォーム間で購入を同期します。 - **StripeとPaddle連携**: Web上の購入を自動的にAdaptyに同期。 - **WebからモバイルへのSync**: Webで支払ったユーザーはアプリでもアクセスでき、逆も同様。 - **統合されたクロスプラットフォームアナリティクス**: WebとモバイルのRevenueを1つのダッシュボードで確認。 [Stripe連携](stripe)、[Paddle連携](paddle)のセットアップ、または[WebとモバイルのサブスクライバーのSync方法](sync-subscribers-from-web)をご覧ください。 ## 他のツールから移行したい場合 \{#im-migrating-from-another-tool\} Adaptyは他のサブスクリプションプラットフォームからの移行を簡単にします。 - **移行ガイド**: 他のサブスクリプションプラットフォームからの移行手順をステップバイステップで解説。 - **オブザーバーモード**: 既存の課金コードをそのまま使いながら、[オブザーバーモード](observer-vs-full-mode)でAdaptyを段階的に導入 — まずアナリティクスとA/B テストから始め、準備ができたら拡張。 - **過去データのインポート**: 既存の取引履歴をAdaptyに取り込んで、アナリティクスを継続。 [Adaptyへの移行](migrate-to-adapty-from-another-solutions)と[過去データのインポート](importing-historical-data-to-adapty)について確認する。 --- まだ検討中ですか?[クイックスタートガイド](quickstart)から始めるのが一番おすすめです。 --- # File: integrate-payments --- --- title: "ストアまたは決済プラットフォームとの連携" description: "AdaptyをApp Store、Google Play、カスタムストア、Stripe、Paddleと連携します。" --- Adaptyを使い始めるには、まずユーザーがプロダクトを購入するストアとの連携を行います。Adaptyはさまざまなアプリストアやウェブ決済プロバイダーに対応しており、すべてのアプリ内課金とアナリティクスを一か所にまとめることができます。 ## ストアおよびウェブ決済との連携 \{#integrate-with-stores-and-web-payments\} 以下から対象のストアを選んで、詳細な連携手順を確認してください: - [App Store](initial_ios) - [Google Play](initial-android) - ウェブ決済: - [Stripe](stripe) - [Paddle](paddle) - [その他のストア](custom-store) ## 次のステップ \{#next-steps\} ストアまたは決済プラットフォームとの連携が完了したら、[プロダクトの追加](quickstart-products)に進みましょう。 --- # File: quickstart-products --- --- title: "プロダクトを追加する" description: "アプリ内プロダクトやサブスクリプションをAdaptyに追加し、App Store、Google Play、Stripe、Paddle、またはカスタムストアのリストにリンクします。" --- :::tip プログラムでAdaptyを設定しますか?[Developer CLI](developer-cli-quickstart)を使ってこのステップを完了できます。 ::: Adaptyのコア機能を使うには、販売する各プロダクトを追加し、対応するストアや決済プラットフォームにリンクする必要があります。この設定により、ユーザーのデバイスにプロダクトを提供し、後で分析でも追跡できるようになります。 Adaptyでは、アプリで販売するものはすべて**プロダクト**です。同じアイテムがApp Store、Google Play、Stripeに存在する場合、Adaptyで1つのプロダクトにまとめることができます。一度設定すれば、すべてのプラットフォームを一か所から管理できます。 さっそく最初のプロダクトを追加してみましょう。 <Tabs groupId="products" queryString> <TabItem value="no-products" label="ストアにプロダクトがまだない場合" default> <div style={{ maxWidth: '560px', margin: '0 auto 2rem', position: 'relative', aspectRatio: '16/9', width: '100%' }}> <iframe style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%' }} src="https://www.youtube.com/embed/qUpC2XG-r5E?si=7Komyv4_PUQ4FaEH" title="YouTube video player" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerPolicy="strict-origin-when-cross-origin" allowFullScreen /> </div> </TabItem> <TabItem value="products-in-stores" label="ストアにすでにプロダクトがある場合"> <div style={{ maxWidth: '560px', margin: '0 auto 2rem', position: 'relative', aspectRatio: '16/9', width: '100%' }}> <iframe style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%' }} src="https://www.youtube.com/embed/nlkdKCF0SwY?si=VVigzHcpv3waKJmI" title="YouTube video player" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerPolicy="strict-origin-when-cross-origin" allowFullScreen /> </div> </TabItem> </Tabs> ## 最初のプロダクトを追加する \{#add-your-first-product\} :::tip このクイックスタートではプロダクト作成の基本を説明します。詳細は[プロダクトの作成](create-product)のガイドをご覧ください。 ::: 例として、月額サブスクリプションをプロダクトとして追加してみましょう。 1. Adaptyのメインメニューから[Products](https://app.adapty.io/products)に移動します。 2. 右上の **Create product** をクリックします。 <img src={require('./img/products-tab.webp').default} style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> :::important **次のステップは、App StoreやGoogle Playにすでにプロダクトがあるかどうかによって異なります:** ::: <Tabs groupId="products" queryString> <TabItem value="no-products" label="ストアにプロダクトがまだない場合" default> :::important 開始する前に、[App Store](initial_ios)および/または[Google Play](initial-android)との連携を設定済みであることを確認してください。App Storeの場合は、AdaptyがプロダクトをプッシュできるよるようにApp Store Connect APIキーを[追加](app-store-connection-configuration#step-6-add-app-store-connect-api-key)しておいてください。 ::: 3. **Create a new product and push to stores** を選択します。 4. プロダクトの詳細を入力します: - **Product name**:Adaptyダッシュボード内でのみ表示される名前です。 - **Access Level**:購入後にどの機能がアンロックされるかを決める識別子です。アプリの有料ユーザー全員が同じ機能にアクセスできる場合は、デフォルトのアクセスレベル `premium` を使用できます。より複雑な設定の場合は、追加の[アクセスレベル](access-level)を作成してください。 - **Subscription duration**:リストからサブスクリプションの期間を選択します。 - **Weekly/Monthly/2 Months/3 Months/6 Months/Annual**:サブスクリプションの期間です。 - **Lifetime**:アプリのプレミアム機能を永久にアンロックするプロダクトにはLifetimeを使用します。 - **Non-Subscriptions**:サブスクリプションではなく期間のないプロダクトにはNon-Subscriptionsを使用します。追加機能のアンロックや消耗型アイテムなどに利用できます。 - **Consumables**:消耗型アイテムは複数回購入できます。アプリ内で使い切るアイテムで、ゲーム内通貨やエクストラなどが例として挙げられます。消耗型プロダクトはアクセスレベルに影響しない点に注意してください。 - **Price (USD)**:USD建てのプロダクト価格です。この価格をベースに全国の価格が自動計算・設定されます。後から[国や地域ごとに価格をカスタマイズ](edit-product#set-country-specific-prices)することもできます。 <img src={require('./img/create-product-push.webp').default} style={{ border: '1px solid #727272', /* border width and color */ width: '400px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. **Save & Continue** をクリックし、**App Store** または **Google Play** タブに切り替えてストア向けのプロダクト詳細を入力します。 <Tabs> <TabItem value="App Store" label="App Store" default> - **Product ID**:プロダクトの永続的な一意のIDを作成します。 - **Product group**:App Store Connectで作成した既存のプロダクトグループを選択するか、**Create new Product Group** をクリックして名前とIDを設定します。Adaptyが作成した後、ドロップダウンから選択できます。 - **Screenshot**:提供するアイテムやサービスが明確にわかるアプリ内購入のスクリーンショットをアップロードします。このスクリーンショットはApp Storeの審査にのみ使用され、App Storeには表示されません。スクリーンショットのサイズとフォーマットの要件は[こちら](https://developer.apple.com/help/app-store-connect/reference/app-information/screenshot-specifications/)をご覧ください。 :::warning このアプリで初めてのプロダクトの場合は、App Store Connectで手動で審査に提出する必要があります。以降は不要です。審査が完了すると、Adapty上のプロダクトステータスが自動的に更新されます。 ::: </TabItem> <TabItem value="Google Play" label="Google Play" default> - **Base Product ID**:プロダクトの永続的な一意のIDを作成します。 - **Subscription**:Google Play Consoleで作成した既存のサブスクリプショングループを選択するか、**Create new Product Group** をクリックして名前とIDを設定します。Adaptyが作成した後、ドロップダウンから選択できます。 </TabItem> </Tabs> 6. iOSの場合は、ドロップダウンから **Free duration** を選択して初回オファー(無料トライアル)を設定します。この初期設定では無料トライアルの初回オファーを追加できます。メインプロダクトがストアに承認された後、ストアコンソールの既存IDをリンクすることで[さらにオファーを追加](offers)できます(プロモーションオファー、ウィンバックオファーなど)。 :::important 初回オファーはGoogle Playと自動同期されません。App Storeとは異なり、Google Playには独立した「初回オファー」タイプがなく、無料トライアルや割引オファーはすべてベースプランの**オファー**として設定します。[Google Play Consoleでオファーを作成し、Adaptyのプロダクトにリンク](google-play-offers)してください。 ::: </TabItem> <TabItem value="products-in-stores" label="ストアにすでにプロダクトがある場合"> 3. **Connect an existing store product** を選択します。 4. プロダクトの詳細を入力します: - **Product name**:Adaptyダッシュボード内でのみ表示される名前です。 - **Access level ID**:購入後にどの機能がアンロックされるかを決める識別子です。アプリの有料ユーザー全員が同じ機能にアクセスできる場合は、デフォルトのアクセスレベル `premium` を使用できます。より複雑な設定の場合は、追加の[アクセスレベル](access-level)を作成してください。 - **Subscription duration**:リストからサブスクリプションの期間を選択します。 - **Weekly/Monthly/2 Months/3 Months/6 Months/Annual**:サブスクリプションの期間です。 - **Lifetime**:アプリのプレミアム機能を永久にアンロックするプロダクトにはLifetimeを使用します。 - **Non-Subscriptions**:サブスクリプションではなく期間のないプロダクトにはNon-Subscriptionsを使用します。追加機能のアンロックや消耗型アイテムなどに利用できます。 - **Consumables**:消耗型アイテムは複数回購入できます。アプリ内で使い切るアイテムで、ゲーム内通貨やエクストラなどが例として挙げられます。消耗型プロダクトはアクセスレベルに影響しない点に注意してください。 - **Price (USD)**:USD建てのプロダクト価格です。プロダクトがすでにストアにある場合、この値は実際のストア価格に影響しませんので、リストから任意の値を選択できます。後から、Adaptyダッシュボード上で[地域ごとの価格をカスタマイズ](edit-product#set-country-specific-prices)することもできます。 <img src={require('./img/product-info.webp').default} style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> <br /> 5. ストアの詳細を追加します。ストアを選択してください: <Tabs> <TabItem value="App Store" label="App Store" default> - **App Store Product ID**:デバイス上でプロダクトにアクセスするための一意の識別子です。見つからない場合は、IDが正しく、正しいアプリのものであることを確認してください。 </TabItem> <TabItem value="Google Play" label="Google Play" default> - **Google Play Product ID**:Play Storeのプロダクト識別子です。既存のプロダクトIDのリストから選択します。見つからない場合は、IDが正しく、正しいアプリのものであることを確認してください。 - **Base plan ID**:Play Storeでプロダクトのベースプランを定義するIDです。 - **Legacy fallback product**:フォールバックプロダクトは、古いバージョンのAdapty SDK(バージョン2.5以下)を使用するアプリ専用です。`<subscription_id>:<base_plan_id>` の形式で値を指定してください。 :::important 初回オファーはGoogle Playと自動同期されません。App Storeとは異なり、Google Playには独立した「初回オファー」タイプがなく、無料トライアルや割引オファーはすべてベースプランの**オファー**として設定します。[Google Play Consoleでオファーを作成し、Adaptyのプロダクトにリンク](google-play-offers)してください。 ::: <details> <summary>Google PlayのProduct IDとBase plan IDの確認方法はこちらをクリックしてください。</summary> 1. [Google Play Console](https://play.google.com/console/developers/android/app)アカウントで **Monetize with Play > Products > Subscriptions** に移動します。 2. 対象の購入に関する **Subscription** を開きます。 3. **Subscription details** セクションにProduct IDが、**Base plans and offers** セクションの **ID and duration** 列にBase plan IDが表示されます。 <img src={require('./img/play-store-id.png').default} style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> </details> </TabItem> <TabItem value="Stripe" label="Stripe" default> - **Stripe Product ID**:Stripeの一意のプロダクト識別子です。 - **Stripe Price ID**:プロダクトに関連付けられた価格のStripe固有の識別子です。 <details> <summary>StripeのProduct IDとPrice IDの確認方法はこちらをクリックしてください。</summary> 1. Stripeの[Product Catalog](https://dashboard.stripe.com/products?active=true)に移動します。 2. 対象のプロダクトを開きます。 3. 以下が確認できます: - Stripe Product ID(`prod_...` の形式)は右上に表示されます。 - Stripe Price ID(`price_...` の形式)は **Pricing** セクションの **API ID** 列に表示されます。 <img src={require('./img/product-stripe.png').default} style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> </details> </TabItem> <TabItem value="Paddle" label="Paddle" default> - **Paddle Product ID**:Paddleの一意のプロダクト識別子です。 - **Paddle Price ID**:プロダクトに関連付けられた価格のPaddle固有の識別子です。 <details> <summary>PaddleのProduct IDとPrice IDの確認方法はこちらをクリックしてください。</summary> 1. Paddleの[Product Catalog](https://vendors.paddle.com/products-v2)に移動します。 2. 対象のプロダクトを開きます。 3. 以下が確認できます: - Paddle Product ID(`pro_...` の形式)は **Additional details** セクションに表示されます。 - Paddle Price ID(`pri_...` の形式)は **Prices** セクションの **ID** 列に表示されます。 <img src={require('./img/paddle-product-price.webp').default} style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> </details> </TabItem> <TabItem value="Custom" label="Custom store" default> 既存のカスタムストアを選択するか、新しいストアを追加してプロダクトを関連付けることができます。 Adaptyがトランザクションを追跡できるのはApp Store、Google Play、Stripeのみです。カスタムストアの場合は、Adaptyのサーバーサイドapi [Set transaction method](api-adapty/operations/setTransaction)を使ってトランザクションを送信する必要があります。 </TabItem> </Tabs> 6. 必要に応じてプロダクトの[オファーを作成](create-offer)できます。オファーを追加する場合は **Yes, add offers** を、不要な場合は **No, thanks** をクリックします。 プロダクトがプロダクト一覧に表示されます。 <img src={require('./img/created-product.png').default} style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> </TabItem> </Tabs> ## 次のステップ \{#next-steps\} Adaptyにプロダクトを追加したら、[ペイウォールの設定](quickstart-paywalls)に進みましょう。プロダクトを販売するにはペイウォールが必要です。 --- # File: quickstart-paywalls --- --- title: "購入を有効にする" description: "Adapty でフローまたはペイウォールを追加してプロダクトを表示し、プレースメントに紐付けます。" --- :::info このガイドを進める前に、[ストア連携](integrate-payments) を完了し、前の[プロダクト追加ガイド](quickstart-products)に従って少なくとも 1 つのプロダクトを作成していることを確認してください。 ::: プロダクトが用意できたら、次はユーザーに見せる方法が必要です。Adapty には 3 つの選択肢があります。 - **Flow Builder(推奨)**: 購入フロー全体をノーコードで視覚的に構築できるエディターです。Adapty SDK がネイティブにレンダリングするため、UI コードを書く必要はありません。 - **手動ペイウォール**: ペイウォールを作成してプロダクトを紐付け、UI はアプリコードで自分でレンダリングします。 - **Adapty ペイウォールビルダー(レガシー)**: ノーコードのペイウォールエディターです。 どちらの方法も最終的には同じ手順になります。作成したものを[プレースメント](placements)に紐付けます。プレースメントは、アプリが実行時に適切なコンテンツを取得するために呼び出す仕組みです。 <Tabs groupId="purchase-setup" queryString> <TabItem value="flow-builder" label="Use the Flow Builder" default> :::important Flow Builder は現在 iOS SDK v4 以降のみをサポートしています。他のプラットフォームへの対応は近日公開予定です。 ::: フローは、プロダクトが直接埋め込まれた 1 つ以上の画面で構成されます。[Flow Builder](adapty-flow-builder) でデザインできます — コードは不要です。 Adapty SDK は各プラットフォームでフローをネイティブにレンダリングします。アプリが `getFlow` を呼び出すと、SDK が画面を表示し、購入を処理してイベントを記録します。別途 UI コードを書く必要はなく、ペイウォールを別に管理する手間もありません。 ## 1. フローを作成する \{#1-build-the-flow\} 1. Adapty のメインメニューから [**Flows**](https://app.adapty.io/flows) に移動します。 2. **Create flow** をクリックし、フローをデザインします。 [Adapty Flow Builder](adapty-flow-builder) の詳細をご覧ください。 以下のテンプレートガイドでは、よく使われるパターンをステップバイステップで解説しています。 <CustomDocCardList ids={['basic-paywall-screen', 'show-plans-bottom-sheet', 'paywall-with-tabs', 'paywall-features-per-product', 'onboarding-flow-tutorial']} /> フローを保存して公開したら、プレースメントへの紐付けに進みます。 :::warning フローを公開するのを忘れないようにしてください!公開しないと、プレースメントに追加できません。 ::: ### 2. フローをプレースメントに追加する \{#2-add-the-flow-to-a-placement\} <InlineTooltip tooltip="プレースメント">プレースメントとは、フロー、ペイウォール、オンボーディング、または A/B テストを表示するアプリ内の特定のポイントです。プレースメントを使うと、特定の[オーディエンス](audience)に向けてコンテンツをターゲティングできます。[プレースメント](placements)の詳細をご覧ください。</InlineTooltip>を作成することで、アプリが実行時にフローをリクエストできるようになります。 まずは最も基本的なオンボーディングのプレースメントから始めましょう。後でユーザージャーニー全体にわたって[意味のあるプレースメント](choose-meaningful-placements)を追加できます。 1. Adapty のメインメニューから [**Placements**](https://app.adapty.io/placements) に移動し、**Flows** タブに切り替えます。 2. **Create placement** をクリックします。 3. **Placement name**(例: `main` または `onboarding`)を入力します。これは Adapty ダッシュボード内部の識別子です。 4. **Placement ID** を入力します。この ID を Adapty SDK でプレースメントのフローを読み込む際に使用します。 5. **Run flow** をクリックし、先ほど作成したフローを選択します。 6. **Save & publish** をクリックします。 アプリコードにはプレースメント ID のみをハードコードします。どのフローが動くか、どのプロダクトを販売するか、見た目はどうするか — これらはすべて Adapty ダッシュボードで設定でき、アプリのアップデートなしにいつでも変更できます。 :::tip Adapty では、さまざまなユーザーグループに異なるフローを表示し、パフォーマンスを分析できます。[オーディエンス](audience)と [A/B テスト](ab-tests)の詳細をご覧ください。 ::: </TabItem> <TabItem value="manual-paywall" label="Implement paywall manually"> <div style={{ maxWidth: '560px', margin: '0 auto 2rem', position: 'relative', aspectRatio: '16/9', width: '100%' }}> <iframe style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%' }} src="https://www.youtube.com/embed/e4o7Z2tUGL8?si=ipwbW3VVN0fIg0R0" title="YouTube video player" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerPolicy="strict-origin-when-cross-origin" allowFullScreen /> </div> ペイウォールは、1 つ以上のプロダクトをリモートで設定するコンテナです。Adapty がプロダクトリストとオプションの[リモートコンフィグ](customize-paywall-with-remote-config) JSON ペイロードを提供し、アプリコードがそれを読み取って UI を描画します。 :::tip Adapty をプログラムで設定しますか? この手順は [Developer CLI](developer-cli-quickstart) を使って完了できます。 ::: ### 1. ペイウォールを作成する \{#1-create-a-paywall\} 1. Adapty のメインメニューから [**Paywalls**](https://app.adapty.io/paywalls) に移動します。 2. **Create paywall** をクリックします。 3. **Paywall name** を入力します。これは Adapty ダッシュボード内部の識別子です。 4. **Add product** をクリックし、ペイウォールに表示するプロダクトを選択します。 5. (任意)**Remote config** タブを開き、アプリが必要とする JSON ペイロード(タイトル、コピー、フィーチャーフラグなど)を追加します。詳細は[リモートコンフィグでペイウォールをデザインする](customize-paywall-with-remote-config)をご覧ください。 6. **Create as a draft** をクリックし、準備ができたら公開します。 <img src="/assets/shared/img/quickstart-paywall.gif" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> このペイウォールはアプリコードでレンダリングします。<InlineTooltip tooltip="ペイウォールを手動で実装する">プラットフォームごとのガイドに従ってください: [iOS](ios-implement-paywalls-manually)、[Android](android-implement-paywalls-manually)、[React Native](react-native-implement-paywalls-manually)、[Flutter](flutter-implement-paywalls-manually)、[Unity](unity-implement-paywalls-manually)。</InlineTooltip> ### 2. ペイウォールをプレースメントに追加する \{#2-add-the-paywall-to-a-placement\} <InlineTooltip tooltip="プレースメント">プレースメントとは、フロー、ペイウォール、オンボーディング、または A/B テストを表示するアプリ内の特定のポイントです。プレースメントを使うと、特定の[オーディエンス](audience)に向けてコンテンツをターゲティングできます。[プレースメント](placements)の詳細をご覧ください。</InlineTooltip>を作成することで、アプリが実行時にペイウォールをリクエストできるようになります。 まずは最も基本的なオンボーディングのプレースメントから始めましょう。後でユーザージャーニー全体にわたって[意味のあるプレースメント](choose-meaningful-placements)を追加できます。 1. Adapty のメインメニューから [**Placements**](https://app.adapty.io/placements) に移動し、**Paywalls** タブに切り替えます。 2. **Create placement** をクリックします。 3. **Placement name**(例: `main` または `onboarding`)を入力します。これは Adapty ダッシュボード内部の識別子です。 4. **Placement ID** を入力します。この ID を Adapty SDK でプレースメントのペイウォールを読み込む際に使用します。 5. **Run paywall** をクリックし、先ほど作成したペイウォールを選択します。 6. **Save & publish** をクリックします。 <img src="/assets/shared/img/add-placement.gif" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> アプリコードにはプレースメント ID のみをハードコードします。どのペイウォールが動くか、どのプロダクトを販売するか、リモートコンフィグの内容 — これらはすべて Adapty ダッシュボードで設定でき、アプリのアップデートなしにいつでも変更できます。 :::tip Adapty では、さまざまなユーザーグループに異なるペイウォールを表示し、パフォーマンスを分析できます。[オーディエンス](audience)と [A/B テスト](ab-tests)の詳細をご覧ください。 ::: </TabItem> <TabItem value="paywall-builder" label="Adapty Paywall Builder (Legacy)"> [ペイウォールビルダー](adapty-paywall-builder)で作成したペイウォールは、プロダクトが直接埋め込まれたノーコードの画面です。Adapty SDK がネイティブにレンダリングするため、UI コードを書く必要はありません。 :::warning ペイウォールビルダーは引き続き利用できますが、Adapty は新機能の追加やアップデートの提供を終了しています。新規プロジェクトには代わりに [Flow Builder](adapty-flow-builder) をご利用ください。 ::: ### 1. ペイウォールを作成する \{#1-build-the-paywall\} 1. Adapty のメインメニューから [**Paywalls**](https://app.adapty.io/paywalls) に移動します。 2. **Create paywall** をクリックします。 3. **Paywall name** を入力します。これは Adapty ダッシュボード内部の識別子です。 4. **Add product** をクリックし、ペイウォールに表示するプロダクトを選択します。 5. **Builder & Generator** タブを開きます。テンプレートからペイウォールを作成するか、AI を使って生成します。 6. **Show on device** トグルをオンにすると、SDK がレンダリングできるようになります。 ### 2. ペイウォールをプレースメントに追加する \{#2-add-the-paywall-to-a-placement-1\} <InlineTooltip tooltip="プレースメント">プレースメントとは、フロー、ペイウォール、オンボーディング、または A/B テストを表示するアプリ内の特定のポイントです。プレースメントを使うと、特定の[オーディエンス](audience)に向けてコンテンツをターゲティングできます。[プレースメント](placements)の詳細をご覧ください。</InlineTooltip>を作成することで、アプリが実行時にペイウォールをリクエストできるようになります。 1. Adapty のメインメニューから [**Placements**](https://app.adapty.io/placements) に移動し、**Paywalls** タブに切り替えます。 2. **Create placement** をクリックします。 3. **Placement name**(例: `main` または `onboarding`)を入力します。これは Adapty ダッシュボード内部の識別子です。 4. **Placement ID** を入力します。この ID を Adapty SDK でプレースメントのペイウォールを読み込む際に使用します。 5. **Run paywall** をクリックし、作成したペイウォールを選択します。 6. **Save & publish** をクリックします。 アプリコードにはプレースメント ID のみをハードコードします。どのペイウォールが動くか、どのプロダクトを販売するか、見た目はどうするか — これらはすべて Adapty ダッシュボードで設定でき、アプリのアップデートなしにいつでも変更できます。 </TabItem> </Tabs> ## 次のステップ \{#next-steps\} SDK が配信するコンテンツの準備が整いました。次は、アプリに [Adapty SDK を組み込み](quickstart-sdk)、プレースメントの取得を始めましょう。 --- # File: quickstart-sdk --- --- title: "アプリコードへの Adapty SDK の統合" description: "App Store、Google Play、カスタムストア、Stripe、Paddle と Adapty を統合します。" --- Adapty SDK をアプリに統合すると、次のことができます。 - 購入処理、レシート検証、サブスクリプション管理をすぐに利用可能 - アプリのアップデートなしにペイウォールを作成・テスト - 設定不要で詳細な購入アナリティクスを取得(コホート、LTV、チャーン、ファネル分析を含む) - アプリセッションやデバイスをまたいでユーザーのサブスクリプション状態を常に最新に保つ - たった一行のコードでマーケティングアトリビューションやアナリティクスサービスとアプリを統合 ## 仕組み \{#how-does-it-work\} Adapty SDK の基本実装に必要なのは、次の 3 つだけです。 1. SDK のインストールと初期化 2. アプリ内課金の処理を Adapty に委任 3. プロファイルでサブスクリプション状態を監視。サブスクリプションのステータス、種類、有効期限は Adapty が判断し、SDK はその情報を受け取るだけです。 順序や詳細はアプリによって異なりますが、基本的にはこれだけです。 ## はじめる \{#get-started\} プラットフォームを選んでさっそく始めましょう。 **iOS** - **[SDK クイックスタート](ios-sdk-overview)** - **[サンプルアプリ](https://github.com/adaptyteam/AdaptySDK-iOS/tree/master/Examples)** **Android** - **[SDK クイックスタート](android-sdk-overview)** - **[サンプルアプリ](https://github.com/adaptyteam/AdaptySDK-Android/tree/master/app)** **React Native** - **[SDK クイックスタート](react-native-sdk-overview)** - **[サンプルアプリ](https://github.com/adaptyteam/AdaptySDK-React-Native/tree/master/examples/)** **Flutter** - **[SDK クイックスタート](flutter-sdk-overview)** - **[サンプルアプリ](https://github.com/adaptyteam/AdaptySDK-Flutter/tree/master/example)** **Unity** - **[SDK クイックスタート](unity-sdk-overview)** - **[サンプルアプリ](https://github.com/adaptyteam/AdaptySDK-Unity/tree/main/Assets)** **Capacitor** - **[SDK クイックスタート](capacitor-sdk-overview)** - **[サンプルアプリ](https://github.com/adaptyteam/AdaptySDK-Capacitor/tree/master/examples)** **Kotlin Multiplatform**: - **[SDK クイックスタート](kmp-sdk-overview)** - **[サンプルアプリ](https://github.com/adaptyteam/AdaptySDK-KMP/tree/main/example)** ## 次のステップ \{#next-steps\} アプリコードで Adapty SDK の設定が完了したら、[実装のテスト](quickstart-test)に進みましょう。 --- # File: quickstart-test --- --- title: "Adaptyとの統合をテストする" description: "SDKのアクティベーション、ペイウォールの取得、App Store・Google Play・Stripe・Paddleでのアプリ内課金をテストして、Adaptyの統合を素早く確認しましょう。" --- 準備完了です!統合が意図した通りに動作しているか確認し、購入がAdaptyダッシュボードに表示されるかチェックしましょう。 テスト購入を実施することが、統合をエンドツーエンドで検証する最善の方法です。アプリ内課金から始めて、結果を確認してください。 ## 1. アプリ内課金をテストする \{#1-test-in-app-purchases\} ご利用のストアや決済プラットフォームに応じたガイドに従ってください。 ### App Store \{#app-store\} テストアカウント(Sandbox Apple ID)を使用し、実機でテストすることをお勧めします。テストの全手順については、[App Store Sandboxテスト](test-purchases-in-sandbox)の詳細記事をご覧ください。 :::warning 最も信頼性の高い結果を得るには、実機でテストしてください。シミュレーターでのテストも可能ですが、信頼性が低いためお勧めしません。 ::: ### Google Play Store \{#google-play-store\} テストユーザーを作成し、実機でアプリをテストしてください。テストの全手順については、[Google Play Storeのテスト](testing-on-android)の詳細記事をご覧ください。 :::note Googleはテストに[実機の使用を推奨](https://support.google.com/googleplay/android-developer/answer/14316361)しています。エミュレーターを使用する場合は、アプリが正常に動作するようGoogle Playがインストールされていることを確認してください。 ::: ### Stripe \{#stripe\} StripeでのテストにはStripeのテストモード用APIキーを使ってAdaptyにStripeを接続する必要があります。StripeのTestモードで行ったトランザクションは、AdaptyではSandboxとして扱われます。 接続の全手順については、[Stripe連携の記事](stripe#6-test-your-integration)をご覧ください。 ### Paddle \{#paddle\} PaddleでのテストにはPaddleのテスト環境用APIキーを使ってAdaptyにPaddleを接続する必要があります。Paddleのテスト環境で行ったトランザクションは、AdaptyではTestとして扱われます。 接続の全手順については、[Paddle連携の記事](paddle#4-test-your-integration)をご覧ください。 ## 2. テスト購入を検証する \{#2-validate-test-purchases\} テスト購入を行った後、Adaptyダッシュボードの[**Event Feed**](https://app.adapty.io/event-feed)で対応するトランザクションを確認してください。購入が**Event Feed**に表示されない場合、Adaptyはその購入をトラッキングできていません。 詳細は[テスト購入の検証](validate-test-purchases)ガイドをご覧ください。 <img src="/assets/shared/img/test-event-feed.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## 次のステップ \{#next-steps\} Adaptyへのオンボーディングが完了しました!これでアプリ内課金を伸ばす準備が整いました。 本番リリースの準備をしましょう: <Button id="release-checklist"> リリースチェックリスト </Button> または、以下に進むこともできます: - **[A/Bテスト](ab-tests)**:価格、サブスクリプション期間、トライアル期間、ビジュアル要素をさまざまに試して、最も効果的な組み合わせを見つけましょう。 - **[アナリティクス](how-adapty-analytics-works)**:詳細なマネタイズ指標を分析し、ユーザー行動を理解して収益パフォーマンスを最適化しましょう。 - **インテグレーション**:Adaptyはサブスクリプションイベントを[Amplitude](amplitude)、[AppsFlyer](appsflyer)、[Adjust](adjust)、[Branch](branch)、[Mixpanel](mixpanel)、[Facebook Ads](facebook-ads)、[AppMetrica](appmetrica)、カスタム[Webhook](webhook)などのサードパーティ分析・アトリビューションツールに[サブスクリプションイベント](events)として送信します。 --- no_index: true --- import Callout from '../../../components/Callout.astro'; <Callout type="tip"> ご質問やお困りのことがあれば、[サポートフォーラム](https://adapty.featurebase.app/)をご覧ください。よくある質問への回答を見つけたり、ご自身の質問を投稿することができます。チームとコミュニティがサポートいたします! </Callout> --- # File: release-checklist --- --- title: "リリースチェックリスト" description: "Adaptyのリリースチェックリストに従って、スムーズなアプリのアップデートプロセスを確保しましょう。" --- Adaptyをご利用いただきありがとうございます!実装がうまくいったことを願っています。このガイドでは、アプリをストアに公開する準備が整っているか確認するための手順を説明します。これにより、マネタイゼーションフローが正しく機能していることを安心して確認できます。 ## 事前確認事項 \{#pre-flight-essentials\} バリデーションを始める前に必要なもの: - サンドボックスアカウントを持つ実機デバイス - Adapty ダッシュボードへのアクセス - App Store Connect / Google Play Console へのアクセス :::note サンドボックス購入はシミュレーターでも実行できますが、支払いダイアログや生体認証プロンプトを含むすべてのフローを完全にテストするには実機デバイスが必要です。 ::: <Button id="test-purchases-in-sandbox"> App Store向けテストガイド </Button> <Button id="testing-on-android"> Google Play向けテストガイド </Button> ## 共通バリデーション \{#universal-validations\} - [ ] **ストア接続**: AdaptyをApp StoreおよびGoogle Playに接続していることを確認してください: - [ ] [App Store](initial_ios) - [ ] [Google Play](initial-android) - [ ] **サブスクリプションイベントの配信**: サーバー通知が設定されていることを確認してください: - [ ] [App Serverサーバー通知](enable-app-store-server-notifications) - [ ] [リアルタイム開発者通知(RTDN)](enable-real-time-developer-notifications-rtdn) - [ ] **プロファイルの識別**: ユーザー識別ロジックを検証し、購入が正しいプロファイルに紐付けられていることを確認してください: - [ ] [アプリコードの識別ロジックがユースケースに合っているか確認する](ios-quickstart-identify) - [ ] [ユーザープロファイル間で有料アクセスを共有するための親/継承ロジックを理解しているか確認する](sharing-paid-access-between-user-accounts) - [ ] **オファー**: アプリにApp Storeのプロモーションオファーがある場合、[アプリ内購入キー](app-store-connection-configuration#step-4-for-trials-and-special-offers--set-up-promotional-offers)をメインフィールドと **App Store promotional offers** セクションの両方に追加していることを確認してください。 - [ ] **データ収集**: プライバシーへの準拠を確保してください: - [ ] GDPRやCCPAなどのプライバシー規制に準拠する必要がある場合、またはアプリが子供向けの場合は、[IDFAおよびIPの収集と共有を有効にするかどうか](sdk-installation-ios#data-policies)を制御してください。 - [ ] アプリがAppTrackingTransparencyを使用している場合は、[認証ステータスをAdaptyに送信](ios-deal-with-att)していることを確認してください。 - [ ] **プライバシーラベル**: Adaptyが収集するデータとレビューに必要なフラグについては、[詳細はこちら](apple-app-privacy)をご覧ください。 ## 購入バリデーション \{#purchase-validations\} --- no_index: true --- import Callout from '../../../components/Callout.astro'; <Callout type="tip"> ご質問やお困りのことがあれば、[サポートフォーラム](https://adapty.featurebase.app/)をご覧ください。よくある質問への回答を見つけたり、ご自身の質問を投稿することができます。チームとコミュニティがサポートいたします! </Callout> 公開前に、アプリ内購入が正しく機能し、ペイウォールがストアレビューの準備ができていることを確認してください。 アプリ内購入のバリデーション方法は、実装方法によって異なります: - Adapty ペイウォールビルダーで作成したペイウォールを表示する - 独自のペイウォールを実装し、その中で `makePurchase` メソッドを使用して購入を処理する - オブザーバーモードでAdaptyを使用する(Adapty ペイウォールビルダーまたはカスタムペイウォールのどちらでも) <Tabs groupId="paywall" queryString> <TabItem value="builder" label="Adapty Paywall Builder" default> **目標**: Adaptyがペイウォールをレンダリングし、ユーザーがプロダクトを購入でき、アクセスがアンロックされ、購入復元フローが機能すること。 - [ ] アプリが[ペイウォールを表示する](ios-present-paywalls)際、実際にリリースするのと同じプレースメントを使用している。 - [ ] ペイウォールが画面に表示される。読み込みに時間がかかりすぎる場合(不安定なインターネット環境など)は、[フェッチポリシーの調整](get-pb-paywalls#fetch-paywall-designed-with-paywall-builder)を検討してください。 - [ ] ペイウォールが期待するバリアント(該当する場合はオーディエンス/ロケール)と一致している。必要に応じて[オーディエンスの優先順位を変更](change-audience-priority)できます。 - [ ] プロダクトと価格がペイウォールに表示される。テスト中(特に異なるリージョン設定の場合)にAppleのAPIが不正確な価格を提供することがあります。AdaptyはStoreの価格に影響を与えないため、価格の正確さよりも購入フローの機能テストを優先してください。 - [ ] サンドボックス購入が正常に完了する。購入成功のコールバックが受信される。 - [ ] アクセスがアンロックされ、維持される。[現在のAdaptyプロファイルに基づいて有料アクセスが付与されていること](ios-check-subscription-status#connect-profile-with-paywall-logic)を確認する。 - [ ] 購入後、Adaptyプロファイルにアクティブなアクセスレベルがある。 - [ ] プロファイルにそのアクセスレベルが含まれている場合に有料機能がアンロックされる(購入コールバックだけでなく)。 - [ ] 購入の復元が機能する。アプリを再インストールするか新しいデバイスにインストールした場合、[有料アクセスの共有](sharing-paid-access-between-user-accounts)設定に従って購入の自動復元が機能する。バックエンド認証がない場合は、設定に関係なく購入が自動的に復元される。それ以外の場合は、アプリの再インストール後にユーザーが購入を復元できることを確認する。 - [ ] ストアレビュー要件: - [ ] **Restore purchases** ボタンがペイウォールに表示されている。ペイウォールビルダーで追加でき、タップ時に購入復元を自動的に処理します。 - [ ] 利用規約とプライバシーポリシーがペイウォール画面からアクセスでき、これらのリンクをクリックするとブラウザで開く。 </TabItem> <TabItem value="makepurchase" label="カスタムペイウォール(makePurchase)" default> **目標**: UIをレンダリングし、AdaptyがPurchase処理、プロファイル更新、および復元を担当する。 - [ ] プロダクトIDがアプリコードにハードコードされていない。ハードコードするのは[プレースメント](placements)IDのみ。 - [ ] アプリが[プロダクトを取得する](fetch-paywalls-and-products)際、実際にリリースするのと同じプレースメントを使用している。 - [ ] プロダクトリストが正常に読み込まれる。読み込みに時間がかかりすぎる場合(不安定なインターネット環境など)は、[フェッチポリシーの調整](fetch-paywalls-and-products#fetch-paywall-information)を検討してください。 - [ ] 取得したプロダクトが期待するバリアント(該当する場合はオーディエンス/ロケール)と一致している。必要に応じて[オーディエンスの優先順位を変更](change-audience-priority)できます。 - [ ] プロダクトと価格がペイウォールに表示される。テスト中(特に異なるリージョン設定の場合)にAppleのAPIが不正確な価格を提供することがあります。AdaptyはStoreの価格に影響を与えないため、価格の正確さよりも購入フローの機能テストを優先してください。 - [ ] [makePurchase](making-purchases)を使用したサンドボックス購入が正常に完了する: - [ ] 購入成功の結果が処理される。 - [ ] 保留中/失敗/キャンセルの結果が適切に処理される。 - [ ] [リモートコンフィグを使用する](present-remote-config-paywalls)場合、その値がペイウォールに正しく反映されている。 - [ ] ペイウォールが表示されたとき、[`logShowFlow`(iOS SDK v4+)/ `logShowPaywall` メソッド](present-remote-config-paywalls#track-paywall-view-events)が呼び出される。 - [ ] サンドボックス購入が正常に完了する。購入成功のコールバックが受信される。 - [ ] アクセスがアンロックされ、維持される。[現在のAdaptyプロファイルに基づいて有料アクセスが付与されていること](ios-check-subscription-status#connect-profile-with-paywall-logic)を確認する。 - [ ] 購入後、Adaptyプロファイルにアクティブなアクセスレベルがある。 - [ ] プロファイルにそのアクセスレベルが含まれている場合に有料機能がアンロックされる(購入コールバックだけでなく)。 - [ ] 購入の復元が機能する。アプリを再インストールするか新しいデバイスにインストールした場合、[有料アクセスの共有](sharing-paid-access-between-user-accounts)設定に従って購入の自動復元が機能する。バックエンド認証がない場合は、設定に関係なく購入が自動的に復元される。それ以外の場合は、アプリの再インストール後にユーザーが購入を復元できることを確認する。 - [ ] ストアレビュー要件: - [ ] **Restore purchases** ボタンがアクセス可能で、[購入復元を処理](restore-purchase)している。 - [ ] 利用規約とプライバシーポリシーがペイウォール画面からアクセスでき、これらのリンクをクリックするとブラウザで開く。 </TabItem> <TabItem value="observer" label="オブザーバーモード"> **目標**: 購入処理、プロファイル更新、復元を自身で行い、Adaptyがトランザクションレポートを受け取る。 - [ ] **アプリが独自の購入フロー(StoreKit / BillingClient / バックエンド)を使用して購入を完了する**: - [ ] サンドボックス購入がストアUIで成功する。 - [ ] 保留中/失敗/キャンセルの結果がアプリ内で適切に処理される。 - [ ] **トランザクションがAdaptyに報告される**。 - [ ] オブザーバーモードが[アプリコードで有効になっている](implement-observer-mode)。 - [ ] 購入がAdaptyのイベントフィードに表示される。 - [ ] 更新、キャンセル、返金が時間の経過とともに反映される(該当する場合)。 - [ ] **ペイウォールビューが追跡される**。ペイウォールが表示されたとき、[`logShowFlow`(iOS SDK v4+)/ `logShowPaywall` メソッド](present-remote-config-paywalls#track-paywall-view-events)が呼び出される。 - [ ] **実装に合わせた購入復元が機能する**。アプリの再インストールやデバイスの切り替えで、アクセスが正しく復元される。 - [ ] **ストアレビュー要件**: - [ ] **Restore purchases** アクションがアクセス可能で、独自の復元フローがトリガーされる。 - [ ] 利用規約とプライバシーポリシーがペイウォールまたは購入画面からアクセスでき、ブラウザで開く。 </TabItem> </Tabs> Adapty SDKの統合についてご不明な点がある場合は、右下のAIチャットボットをご利用いただくか、[support@adapty.io](mailto:support@adapty.io)までお問い合わせください。 --- # File: observer-vs-full-mode --- --- title: "オブザーバーモード" description: "Adaptyのオブザーバーモードとフルモードをサブスクリプション管理の観点から比較します。" --- Adaptyは、収益とサブスクライバー数の拡大を支援する、強力で柔軟なアプリ内課金プラットフォームです。特定のユーザーセグメントに合わせたカスタマイズ可能なペイウォール、価格・期間・トライアル期間・ビジュアル要素のA/B テスト、アプリのマネタイズに向けた充実した分析ツール、そしてサードパーティ連携など、Adaptyはあなたの成長戦略を力強くサポートします。 ただし、すでに独自の購入インフラを持っており、Adaptyのシステムへの移行を検討していない場合は、Adaptyのオブザーバーモードを活用できます。この限定的なモードでは、Adaptyのペイウォール機能(ユーザーオーディエンスへのターゲティング、更新・請求リトライを含むサブスクリプション管理など)は利用できず、分析機能に特化しています。制限はあるものの、アトリビューションシステムとの連携、高度な分析、メッセージング、CRMプロファイルなど、充実した分析機能を引き続き利用できます。 両モードとも料金は同じで、モバイルアプリのアップデートが必要です。したがって、選択の本質は「Adaptyのインフラに移行してフル機能を使うか」「現在のインフラを維持しつつサードパーティ連携と分析機能のみを活用するか」という点にあります。 | 機能 | オブザーバーモード | フルモード | |-------------|-------------|---------| | **充実した分析機能** | ✅ | ✅ | | **サードパーティ連携** | ✅ | ✅ | | **購入イベントへの対応(有料コンテンツのアクセス付与・制限)** | ❌ | ✅ | | **購入インフラの管理者** | お客様 | Adapty | | **A/B テスト** | <p>実施可能ですが、フルモードに比べて追加の実装や設定が大幅に必要になります。</p> | ✅ | | **実装にかかる時間** | <p>分析・連携のみ:1時間未満</p><p>A/B テストあり:十分なテストを含めて最大1週間</p> | 数時間 | ## オブザーバーモードの仕組み \{#how-observer-mode-works\} オブザーバーモードでは、Apple/Googleからの新しいトランザクションをAdapty SDKに報告し、Adapty SDKがそれをAdaptyバックエンドに転送します。有料コンテンツへのアクセス管理、トランザクションの完了、更新処理、請求問題への対応などは、すべてお客様が担当します。 ## オブザーバーモードのセットアップ方法 \{#how-to-set-up-observer-mode\} 1. Adaptyの初期連携を[Google Play](initial-android)および[App Store](initial_ios)と設定します。 2. Adapty SDKの設定時に`observerMode`パラメーターを`true`に設定してオブザーバーモードを有効化します。各プラットフォームの設定手順([iOS](sdk-installation-ios#activate-adapty-module-of-adapty-sdk)、[Android](sdk-installation-android#activate-adapty-module-of-adapty-sdk)、[React Native](sdk-installation-reactnative)、[Flutter](sdk-installation-flutter#activate-adapty-module-of-adapty-sdk)、[Kotlin Multiplatform](sdk-installation-kotlin-multiplatform#activate-adapty-sdk)、[Unity](sdk-installation-unity#activate-adapty-module-of-adapty-sdk))に従ってください。 3. iOSおよびiOSベースのクロスプラットフォームフレームワークの場合、既存の購入インフラからAdaptyへ[トランザクションを報告](report-transactions-observer-mode)します。 4. (任意)サードパーティ連携を利用する場合は、[サードパーティ連携の設定](configuration)トピックの手順に従って設定してください。 :::warning オブザーバーモードで動作している場合、Adapty SDKはトランザクションを完了させません。この処理はお客様自身で行う必要があります。 ::: ## オブザーバーモードでのペイウォールとA/Bテストの使い方 \{#how-to-use-paywalls-and-ab-tests-in-observer-mode\} オブザーバーモードでは、Adapty SDKは購入の発生元を特定できません(購入処理はお客様独自のインフラ上で行われるため)。そのため、オブザーバーモードでペイウォールやA/B テストを使用する場合は、トランザクションを報告する際に、アプリストアからのトランザクションをモバイルアプリのコード内で対応するペイウォールに紐付ける必要があります。 また、ペイウォールビルダーで作成したペイウォールをオブザーバーモードで使用する際は、特別な表示方法が必要です。 - オブザーバーモードでのペイウォール表示については、[iOS](implement-observer-mode)または[Android](android-present-paywall-builder-paywalls-in-observer-mode)の手順を参照してください。 - トランザクション報告時のペイウォールと購入トランザクションの紐付けについては、[オブザーバーモードでのトランザクション報告](report-transactions-observer-mode)を参照してください。 --- # File: migration-from-revenuecat --- --- title: "RevenueCatからの移行" description: "ステップバイステップガイドでRevenueCatからAdaptyに移行しましょう。" --- 移行は5つのステップで構成されており、平均所要時間は約2時間です。移行の90%は1営業日以内に完了します。 1. 主要な違いを理解し、Adaptyアカウントを作成・準備する _(5分)_; 2. RevenueCat SDKの代わりに、各プラットフォーム向けのAdapty SDKをインストールする([iOS](sdk-installation-ios)、[Android](sdk-installation-android)、[React Native](sdk-installation-reactnative)、[Flutter](sdk-installation-flutter)、[Kotlin Multiplatform](sdk-installation-kotlin-multiplatform)、[Unity](sdk-installation-unity))_(1時間)_; 3. AdaptyへのApple App Storeサーバー通知を設定し、オプションで[rawイベント転送](enable-app-store-server-notifications#raw-events-forwarding)を設定する _(5分)_; 4. アプリのアップデートをテストしてリリースする _(30分)_; 5. (オプション)RevenueCatサポートにCSV形式の過去データをリクエストする _(5分)_; 6. (オプション)Adaptyサポート経由で過去データをインポートする _(30分)_。 :::info サブスクライバーは自動的に移行されます サブスクリプションを有効にしたことがあるすべてのユーザーは、Adapty SDKを搭載した新しいバージョンのアプリを開いた瞬間に自動的にAdaptyへ移行されます。サブスクリプションのステータス検証とプレミアムアクセスは自動的に復元されます。 ::: Adapty SDKを搭載したアプリの新バージョンをリリースする前に、必ず[リリースチェックリスト](release-checklist)を確認してください。 ## 主要な違いを理解し、Adaptyアカウントを作成・準備する \{#learn-the-core-differences-create-and-prepare-an-adapty-account\} AdaptyとRevenueCatのSDKは設計が似ています。最大の違いはネットワーク使用量とスピードです。Adapty SDKは、必要な情報をリクエスト時にできる限り高速に提供するよう設計されています。たとえば、ペイウォールをリクエストする際、オンボーディングやペイウォールの事前構築に使える[リモートコンフィグ](customize-paywall-with-remote-config)がまず返され、その後プロダクトが専用リクエストで取得されます。 名称は少し異なります: | RevenueCat | Adapty | | :---------- | :-------------- | | Package | Product | | Offering | Paywall | | Paywall | Paywall Builder | | Entitlement | Access level | Adaptyには[プレースメント](placements)というコンセプトがあります。これはアプリ内でユーザーが購入できる論理的な場所です。ほとんどの場合、プレースメントは1〜2つです: - オンボーディング(全購入の80%がここで発生するため); - 全般(オンボーディング後の設定画面やアプリ内で表示)。 <img src="/assets/shared/img/2406d97-image.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '300px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Adapty SDKのインストールとRevenueCat SDKの置き換え \{#install-adapty-sdk-and-replace-revenuecat-sdk\} 各プラットフォーム向けのAdapty SDKをアプリにインストールしてください([iOS](sdk-installation-ios)、[Android](sdk-installation-android)、[React Native](sdk-installation-reactnative)、[Flutter](sdk-installation-flutter)、[Kotlin Multiplatform](sdk-installation-kotlin-multiplatform)、[Unity](sdk-installation-unity))。 アプリ側でいくつかのSDKメソッドを置き換える必要があります。よく使われる関数とAdapty SDKでの置き換え方法を見ていきましょう。 ### SDKのアクティベーション \{#sdk-activation\} `Purchases.configure` を `Adapty.activate` に置き換えてください。 ### ペイウォール(オファリング)の取得 \{#getting-paywalls-offerings\} `Purchases.shared.getOfferings` を [`Adapty.getPaywall`](fetch-paywalls-and-products#fetch-paywall-information) に置き換えてください。 Adaptyでは、常に[プレースメントID](placements)を使ってペイウォールをリクエストします。実際には1〜2個のペイウォールしか取得しないため、SDKの高速化とネットワーク使用量の削減を目的として意図的にこのような設計にしています。 ### ユーザー(カスタマープロファイル)の取得 \{#getting-a-user-customer-profile\} `Purchases.shared.getCustomerInfo` を `Adapty.getProfile` に置き換えてください。 ### プロダクトの取得 \{#getting-products\} RevenueCatでは、`Purchases.shared.getOfferings`を使い、その後`self.offering?.availablePackages`で取得します。 Adaptyでは、まずペイウォールをリクエストして(上記参照)Adaptyの[リモートコンフィグ](customize-paywall-with-remote-config)にすぐアクセスし、その後[`Adapty.getPaywallProducts`](fetch-paywalls-and-products#fetch-products)でプロダクトを取得します。 ### 購入する \{#making-a-purchase\} `Purchases.shared.purchase` を [`Adapty.makePurchase`](making-purchases#make-purchase) に置き換えてください。 ### アクセスレベル(エンタイトルメント)の確認 \{#checking-access-level-entitlement\} カスタマープロファイルを取得し(上記参照)、 `customerInfo?.entitlements["premium"]?.isActive == true` を以下に置き換えてください: [`profile.accessLevels["premium"]?.isActive == true`](subscription-status#retrieving-the-access-level-from-the-server) ### 購入の復元 \{#restore-purchase\} `Purchases.shared.restorePurchases` を [`Adapty.restorePurchases`](restore-purchase) に置き換えてください。 ### ユーザーのログイン状態を確認する \{#check-if-the-user-is-logged-in\} `Purchases.shared.isAnonymous` を `if profile.customerUserId == nil` に置き換えてください。 ### ユーザーのログイン \{#log-in-user\} `Purchases.shared.logIn` を [`Adapty.identify`](identifying-users#set-customer-user-id-after-configuration) に置き換えてください。 ### ユーザーのログアウト \{#log-out-user\} `Purchases.shared.logOut` を [`Adapty.logout`](identifying-users#logging-out-and-logging-in) に置き換えてください。 ## App Storeのサーバーサイド通知をAdaptyに切り替える \{#switch-app-store-server-side-notifications-to-adapty\} 手順は[こちら](migrate-to-adapty-from-another-solutions#changing-apple-server-notifications)をご覧ください。 ## アプリの新バージョンをテストしてリリースする \{#test-and-release-a-new-version-of-your-app\} ここまで読んでいるということは、すでに以下の作業が完了しているはずです: - [x] Adapty ダッシュボードの設定 - [x] Adapty SDKのインストール - [x] SDKロジックのAdapty関数への置き換え - [x] App StoreのサーバーサイドサービスをAdaptyに切り替え(オプションでRevenueCatへのrawイベント転送を有効化) - [ ] サンドボックスでの購入テスト - [ ] 新しいアプリのリリース 上記の項目を確認したら、サンドボックスでテスト購入を行い、アプリをリリースしてください。 :::info [リリースチェックリスト](release-checklist)を確認してください。 リストを使って既存のインテグレーションを検証し、[アトリビューション](attribution-integration)や[アナリティクス](analytics-integration)インテグレーションなどの追加機能の設定も行いましょう。 ::: ## (オプション)RevenueCatの過去データをCSV形式でエクスポートする \{#optional-export-your-revenuecat-historical-data-in-csv-format\} :::warning 過去データのインポートは慌てないでください 過去データのインポートを行う前に、SDK搭載バージョンのリリース後、少なくとも1週間は待つ必要があります。その間にSDKから購入金額に関する情報がすべて取得されるため、インポートされるデータがより正確になります。 ::: [RevenueCatの公式ドキュメント](https://www.revenuecat.com/docs/integrations/scheduled-data-exports)の手順に従って、RevenueCatからCSV形式で過去データをエクスポートしてください。 ## (オプション)RevenueCatサポートにGoogle Purchase Tokensをリクエストする \{#optional-ask-revenuecat-support-for-google-purchase-tokens\} Google Playのトランザクションをインポートする場合は、RevenueCatの[サポートページ](https://app.revenuecat.com/settings/support)からGoogle Purchase Tokensが含まれたCSVファイルをリクエストしてください。Google Purchase Tokenは、Google Playが各トランザクションに付与する一意の識別子で、Adaptyで購入を正確に追跡・検証するために必要です。この情報は標準のエクスポートファイルには含まれていません。ファイルには以下の3つの列が含まれます: - `user_id` - `google_purchase_token` - `google_product_id` ## 過去データのインポートをご依頼ください \{#write-us-to-import-your-historical-data\} ウェブサイトのメッセンジャーまたは[support@adapty.io](mailto:support@adapty.io)にCSVファイルを添付してご連絡ください。 1. RevenueCatからエクスポートしたCSVファイルをサポートチームに直接送付してください。 2. Google Playのトランザクションをインポートする場合は、RevenueCatサポートから受け取ったGoogle Purchase Tokensが含まれたCSVファイルも添付してください。 3. Customer User ID(AdaptyのメインユーザーID)として使用するユーザーIDをお知らせください:`rc_original_app_user_id` または `rc_last_seen_app_user_id_alias` のいずれかです。 サポートチームがトランザクションをAdaptyにインポートします。各トランザクションについて以下のデータがインポートされます: | パラメータ | 説明 | | ----------------------------- | ------------------------------------------------------------ | | user_id | Customer User ID。Adaptyおよびあなたのシステムにおけるユーザーのメイン識別子。 | | apple_original_transaction_id | サブスクリプションチェーンの場合、`store_original_transaction_id`でリンクされた元のトランザクションの購入日。 | | google_product_id | Google Play StoreのプロダクトID。 | | google_purchase_token | 各トランザクションに対してGoogle Playが発行する一意の識別子。検証に必要。 | | country | ユーザーの国。 | | created_at | ユーザー作成日時。 | | subscription_expiration_date | サブスクリプションの有効期限日時。 | | email | エンドユーザーのメールアドレス。 | | phone_number | エンドユーザーの電話番号。 | | idfa | Appleがユーザーのデバイスに割り当てる広告識別子(IDFA)。 | | idfv | 1人の開発者の全アプリに割り当てられ、デバイス上でそれらのアプリ間で共有されるベンダー識別子(IDFV)。 | | advertising_id | 広告トラッキングのためにAndroid OSが提供する一意の識別子。 | | attribution_channel | マーケティングチャネル名。 | | attribution_campaign | マーケティングキャンペーン名。 | | attribution_ad_group | アトリビューションの広告グループ。 | | attribution_ad_set | アトリビューションの広告セット。 | | attribution_creative | アトリビューションのクリエイティブキーワード。 | また、Amplitude、Mixpanel、AppsFlyer、Adjust、FacebookAdsのインテグレーション識別子もインポートされます。 ## よくある質問 \{#faq\} ### Adapty SDKのインストールとAdapty SDK搭載の新バージョンのリリースが完了しました。Adapty SDKを含む新バージョンにアップデートしていない既存のサブスクライバーはどうなりますか? \{#i-successfully-installed-adapty-sdk-and-released-a-new-app-version-with-it-what-will-happen-to-my-legacy-subscribers-who-did-not-update-to-a-version-with-adapty-sdk\} ほとんどのユーザーは夜間に充電する際にApp Storeが全アプリを自動更新するため、問題にはならないでしょう。アップデートしていない有料サブスクライバーが若干残る可能性はありますが、引き続きプレミアムコンテンツにアクセスできます。強制的にアップデートさせる必要はありません。 ### RevenueCatから過去データをできるだけ早くエクスポートする必要がありますか?それとも失ってしまいますか? \{#do-i-need-to-export-my-historical-data-from-revenuecat-as-quickly-as-possible-or-will-i-lose-it\} 急ぐ必要はありません。まずAdapty SDKでリリースを行い、その後に過去データをご提供ください。ユーザーの支払い履歴を復元し、[プロファイル](profiles-crm)と[チャート](charts)に反映します。 ### MMP(AppsFlyer、Adjustなど)やアナリティクス(Mixpanel、Amplitudeなど)を使用しています。すべて正常に動作するか確認するにはどうすればいいですか? \{#i-use-mmp-appsflyer-adjust-etc-and-analytics-mixpanel-amplitude-etc-how-do-i-make-sure-that-everything-will-work\} まず、データを送信したいサードパーティサービスのIDをSDK経由でAdaptyに渡す必要があります。[アトリビューションインテグレーション](attribution-integration)と[アナリティクスインテグレーション](analytics-integration)のガイドをご参照ください。過去データや既存ユーザーについては、**RevenueCatからエクスポートしたデータからそれらのIDを必ず渡してください。** --- # File: migration-from-superwall --- --- title: "Superwallからの移行" description: "SuperwallからAdaptyへの移行を、SDKの全コールとコンセプトをマッピングしたステップバイステップガイドで行いましょう。" --- SuperwallからAdaptyへの移行は、ほとんどの場合2時間程度で完了します。SDKを入れ替え、ストアのサーバー通知をAdaptyに向け直し、新しいアプリリリースを公開するだけです。有料サブスクライバーはアクセスを維持できます — Adaptyは初回起動時にApp StoreとGoogle Playのレシートからアクセスを復元します。 :::info サブスクライバーは自動的に移行されます サブスクリプションを有効化したことがあるすべてのユーザーは、Adapty SDKを搭載した新バージョンのアプリを開いた時点でAdaptyに移行されます。サブスクリプション状態の検証とプレミアムアクセスは自動的に復元されます。 ::: ## このガイドの構成 \{#how-this-guide-is-organized\} 移行は6つのステップで進みます: 1. [SuperwallのコンセプトをAdaptyにマッピングする](#map-your-superwall-concepts-to-adapty) 2. [Adapty SDKをインストールする](#install-the-adapty-sdk) 3. [SDKの呼び出しを置き換える](#replace-sdk-calls) 4. [App StoreとGoogle Playのサーバー通知を切り替える](#switch-app-store-and-google-play-server-notifications) 5. [テストとリリース](#test-and-release) 6. [(オプション) 過去のデータをインポートする](#optional-import-historical-data) ## SuperwallのコンセプトをAdaptyにマッピングする \{#map-your-superwall-concepts-to-adapty\} Superwallのコンセプトのほとんどは、Adaptyに直接対応するものがあります: | Superwall | Adapty | 変更点 | | :------------------- | :------------------------------------------------ | :--------------------------------------------------------------------------- | | Campaign | [プレースメント](placements) + [オーディエンス](audience) | キャンペーンのロジックは、プレースメント(場所)とオーディエンス(ルール)に分かれます。 | | Placement | [プレースメント](placements) | 同じコンセプト、同じ名前。 | | Audience filter | [オーディエンス](audience) | ルールセットはプレースメント内に存在します。 | | Entitlement | [アクセスレベル](access-level) | 名前付き識別子(例:`premium`)。 | | WebView paywall | [ペイウォールビルダーのペイウォール](adapty-paywall-builder) | `WKWebView`ではなく、Adapty SDKがネイティブにレンダリングします。 | | `PurchaseController` | 組み込み | 実装すべきプロトコルなし — Adaptyが購入処理を担当します。 | | Feature gating | [アクセスレベル](access-level)チェック | `profile.accessLevels["premium"]?.isActive`を確認します。 | コードに触れる前に、2つの考え方の転換を理解しておきましょう: - **フェッチと表示は別ステップです**: Superwallの`register`は、ペイウォールのフェッチ、キャンペーンの評価、UIの表示を1回の呼び出しで行います。Adaptyはこれらのステップを分けています — ペイウォールをフェッチし、その設定を取得してから表示します。手順は増えますが、設定のプリロード、カスタムローディング状態の表示、独自ロジックに基づいた表示のキャンセルが可能になります。 - **サブスクリプション状態はアクセスレベルごとです**: Superwallは単一の`subscriptionStatus`パブリッシュプロパティを公開します。Adaptyは名前付きアクセスレベルを持つ[`AdaptyProfile`](https://swift.adapty.io/documentation/adapty/adaptyprofile)を返すため、1人のユーザーが`sports`と`science`のアクセスレベルを独立して持つことができます。同期的な読み取りには、ビューの読み込みごとに`getProfile()`を呼び出すのではなく、`AdaptyDelegate`からプロファイルをキャッシュしてください。 ## Adapty SDKをインストールする \{#install-the-adapty-sdk\} お使いのプラットフォーム向けのAdapty SDKをインストールしてください — [iOS](sdk-installation-ios)、[Android](sdk-installation-android)、[React Native](sdk-installation-reactnative)、[Flutter](sdk-installation-flutter)、[Kotlin Multiplatform](sdk-installation-kotlin-multiplatform)、[Unity](sdk-installation-unity)、または[Capacitor](sdk-installation-capacitor) — そして同時にSuperwalKitをプロジェクトから削除してください。 ## SDKの呼び出しを置き換える \{#replace-sdk-calls\} インテグレーションの各部分を確認しながら、SupwallのコールをAdaptyの対応するものに置き換えてください。各サブセクションの末尾にあるリンクは7つのプラットフォームSDKすべてをカバーしています — アプリに合うものを参照してください。 ### SDKを初期化する \{#initialize-the-sdk\} `Superwall.configure`を`Adapty.activate`に置き換えます。 お使いのプラットフォームのインストールガイドを参照してください — [iOS](sdk-installation-ios)、[Android](sdk-installation-android)、[React Native](sdk-installation-reactnative)、[Flutter](sdk-installation-flutter)、[Kotlin Multiplatform](sdk-installation-kotlin-multiplatform)、[Unity](sdk-installation-unity)、または[Capacitor](sdk-installation-capacitor)。 ### ユーザーの識別とログアウト \{#identify-and-log-out-users\} `Superwall.shared.identify`を`Adapty.identify`に、`Superwall.shared.reset`を`Adapty.logout`に置き換えます。両SDKとも初回起動時に匿名プロファイルを生成するため、これらの呼び出しはユーザーのサインインまたはサインアウト時のみ必要です。識別後はペイウォールを再フェッチしてください — 新しいユーザーは別のオーディエンスに解決される可能性があります。 お使いのプラットフォームの識別ガイドを参照してください — [iOS](identifying-users)、[Android](android-identifying-users)、[React Native](react-native-identifying-users)、[Flutter](flutter-identifying-users)、[Kotlin Multiplatform](kmp-identifying-users)、[Unity](unity-identifying-users)、または[Capacitor](capacitor-identifying-users)。 ### ペイウォールのフェッチと表示 \{#fetch-and-present-a-paywall\} `Superwall.shared.register`を2ステップのフローに置き換えます:`Adapty.getPaywall`でペイウォールをフェッチし、`AdaptyUI.getPaywallConfiguration`でビュー設定を読み込み、それから表示します。 2つの違いに注目してください: - **`feature:`クロージャに代わるフィーチャーゲーティング**: ペイウォールが閉じた後、返されたプロファイル(または`Adapty.getProfile`)のアクティブなアクセスレベルを確認し、そこから分岐します。 - **ペイウォールはSDKによってレンダリングされます**: Superwallは`WKWebView`内でペイウォールをレンダリングします。Adaptyはペイウォールビルダーのペイウォールをネイティブにレンダリングします — フォント、プロダクト情報、ボタンはSDKによって描画されます。 お使いのプラットフォームのペイウォールクイックスタートを参照してください — [iOS](ios-quickstart-paywalls)、[Android](android-quickstart-paywalls)、[React Native](react-native-quickstart-paywalls)、[Flutter](flutter-quickstart-paywalls)、[Kotlin Multiplatform](kmp-quickstart-paywalls)、[Unity](unity-quickstart-paywalls)、または[Capacitor](capacitor-quickstart-paywalls)。 ### サブスクリプション状態を確認する \{#check-subscription-status\} `Superwall.shared.subscriptionStatus`を、プロファイルの名前付きアクセスレベルのチェックに置き換えます:`profile.accessLevels["premium"]?.isActive`。変更の監視は`@Published`プロパティパターンの代わりに`AdaptyDelegate.didLoadLatestProfile(_:)`を使用し、同期的な読み取りのためにプロファイルをキャッシュしてください。 お使いのプラットフォームのサブスクリプション状態確認ガイドを参照してください — [iOS](ios-check-subscription-status)、[Android](android-check-subscription-status)、[React Native](react-native-check-subscription-status)、[Flutter](flutter-check-subscription-status)、[Kotlin Multiplatform](kmp-check-subscription-status)、[Unity](unity-check-subscription-status)、または[Capacitor](capacitor-check-subscription-status)。 ### 購入と復元を処理する \{#handle-purchases-and-restores\} ペイウォールビルダーを使用する場合、両SDKともペイウォールUI内で購入を自動的に処理します — **このステップはスキップできます**。 カスタムペイウォールの場合、Superwallは`PurchaseController`の実装を必要とします。Adaptyは不要です:`PurchaseController.purchase`を`Adapty.makePurchase`に、`PurchaseController.restorePurchases`を`Adapty.restorePurchases`に置き換えてください。SDKが自動的に検証を処理します。 お使いのプラットフォームのカスタムペイウォールクイックスタートを参照してください — [iOS](ios-quickstart-manual)、[Android](android-quickstart-manual)、[React Native](react-native-quickstart-manual)、[Flutter](flutter-quickstart-manual)、[Kotlin Multiplatform](kmp-quickstart-manual)、[Unity](unity-quickstart-manual)、または[Capacitor](capacitor-quickstart-manual)。 ### ユーザー属性を設定する \{#set-user-attributes\} `Superwall.shared.setUserAttributes`を`Adapty.updateProfile`に置き換えます。 お使いのプラットフォームのユーザー属性ガイドを参照してください — [iOS](setting-user-attributes)、[Android](android-setting-user-attributes)、[React Native](react-native-setting-user-attributes)、[Flutter](flutter-setting-user-attributes)、[Kotlin Multiplatform](kmp-setting-user-attributes)、[Unity](unity-setting-user-attributes)、または[Capacitor](capacitor-setting-user-attributes)。 ## App StoreとGoogle Playのサーバー通知を切り替える \{#switch-app-store-and-google-play-server-notifications\} ストアのサーバー通知をAdaptyに向け直してください。Adaptyはそれなしでも動作しますが、アナリティクス、サードパーティインテグレーション、A/Bテストの指標はこれに依存しています: - **App Store**: [App Storeサーバー通知を有効にする](enable-app-store-server-notifications)の手順に従ってください。 - **Google Play**: [リアルタイム開発者通知を有効にする](enable-real-time-developer-notifications-rtdn)の手順に従ってください。 ロールアウト中にSuperwallとAdaptyを並行して動かしたい場合は、[rawイベントフォワーディング](enable-app-store-server-notifications#raw-events-forwarding)を使用してください — AdaptyがストアイベントをそのままのかたちでSuperwallに転送する一方で、新しいインテグレーションを検証できます。 ## テストとリリース \{#test-and-release\} リリース前に、各項目を確認してください: - [x] Adapty ダッシュボードを設定済み(プロダクト、ペイウォール、プレースメント、アクセスレベル) - [x] Adapty SDKをインストール済み - [x] Superwall SDKの呼び出しをAdaptyの対応するものに置き換え済み - [x] App StoreとGoogle PlayのサーバーNotificationsをAdaptyに向け直し済み - [ ] サンドボックス購入を実施済み - [ ] 新しいアプリリリースを提出済み 最終検証として[リリースチェックリスト](release-checklist)を確認してください。 ## (オプション) 過去のデータをインポートする \{#optional-import-historical-data\} Superwallはサブスクリプション状態を所有していません — それはApp StoreとGoogle Playが所有しています。Adaptyは初回起動時にレシートを検証するため、有料ユーザーはインポートなしでアクセスを維持できます。 過去のトランザクションをAdaptyアナリティクスにバックフィルしたい場合は、[Adaptyへの過去データのインポート](importing-historical-data-to-adapty)の手順に従ってください。SDKが新しい購入価格を収集する時間を確保するため、SDKリリース後少なくとも1週間待ってください。 ## よくある質問 \{#faq\} ### アプリを更新しないサブスクライバーはどうなりますか? \{#what-happens-to-subscribers-who-dont-update-the-app\} ほとんどのユーザーは夜間に自動更新するため、旧バージョンを使用しているユーザーの割合は急速に減少します。旧バージョンのサブスクライバーは、App StoreまたはGoogle Playを通じて直接アクセスを維持します — 強制更新は必要ありません。 ### Superwallのキャンペーンオーディエンスは引き継がれますか? \{#do-my-superwall-campaign-audiences-carry-over\} いいえ。SuperwallのオーディエンスフィルターとAdaptyのオーディエンスは異なるダッシュボードで設定され、異なる識別子を使用します。ターゲティングをAdaptyの[プレースメント](placements)内の[オーディエンス](audience)として再作成してください。ほとんどのアプリは1〜2つのプレースメント(オンボーディングと一般的なアプリ内トリガー)を使用しているため、再構築は通常短時間で完了します。 ### `getPresentationResult`に相当するものはAdaptyにありますか? \{#does-adapty-have-an-equivalent-to-getpresentationresult\} 単一の呼び出しとしては存在しません。プレースメントがペイウォールを表示するかどうかを確認するには、`Adapty.getPaywall(placementId:)`を呼び出し、結果に基づいて分岐します。呼び出しが成功すれば、そのユーザーのオーディエンスにペイウォールが割り当てられています。ペイウォールが設定されていないために失敗した場合は、表示をスキップしてフォールバックロジックを実行してください。 --- # File: importing-historical-data-to-adapty --- --- title: "Adaptyへの過去データのインポート" description: "詳細なアナリティクスのためにAdaptyへ過去データをインポートします。" --- Adapty SDKをインストールしてアプリをリリースすると、[Profiles](profiles-crm)セクションでユーザーとサブスクライバーを確認できます。しかし、レガシーインフラを持っていてAdaptyへ移行したい場合や、既存のデータをAdaptyで確認したい場合はどうすればよいでしょうか? :::note データのインポートは必須ではありません Adapty SDKが組み込まれたアプリをユーザーが開くと、Adaptyは自動的に過去ユーザーへアクセスレベルを付与し、購入イベントを復元します。このユースケースでは、過去データのインポートは不要です。ただし、大量の過去トランザクションがある場合、データのインポートによってアナリティクスの精度が上がります。移行に際して一般的には必須ではありません。 ::: Adaptyにデータをインポートするには: 1. トランザクションをCSVファイルにエクスポートします(iOS、Android、Stripeごとに別々のファイルを用意してください)。詳細な要件については、下記の[インポートファイルの形式](importing-historical-data-to-adapty#import-file-format)セクションを参照してください。 2. ファイルが1 GBを超える場合は、約100行のデータサンプルを準備してください。 3. すべてのファイルをGoogle Driveにアップロードします(圧縮してもかまいませんが、それぞれ別々のファイルのままにしてください)。 4. iOSトランザクションについては、StoreKit 1を使用している場合でも、[**App settings**](https://app.adapty.io/settings/ios-sdk)の**In-app purchase API**セクションに**Issuer ID**、**Key ID**、**Private key**(.P8ファイル)が入力されていることを確認してください。詳細な手順については、[Issuer IDとKey IDの入力](app-store-connection-configuration#step-2-provide-issuer-id-and-key-id)および[アプリ内購入キーファイルのアップロード](app-store-connection-configuration#step-3-upload-in-app-purchase-key-file)セクションを参照してください。 5. [メール](mailto:support@adapty.io)またはAdapty Dashboardのオンラインチャットでチームにリンクを共有してください。 過去データのインポートは、Adaptyの既存エントリと重複する場合でも、重複が発生することはありませんのでご安心ください。 ## Androidの既知の制限事項 \{#known-limitations-for-android\} 1. アクティブなサブスクリプションのみが復元されます。期限切れのトランザクションは復元されません。 2. サブスクリプションの最新の更新のみが復元されます。購入の全チェーンは復元されません。 3. 購入後にプロダクト価格が変更された場合、現在の価格が使用されるため、価格が正しく表示されないことがあります。 :::note Androidトランザクションの件数が多い場合、デフォルトのAPI制限を超えないよう、インポートを開始する前に[Google Play Developer APIのクォータ増加をリクエスト](google-play-quota-increase)する必要があるかもしれません。 ::: ## インポートファイルの形式 \{#import-file-format\} :::tip RevenueCatから移行する場合、RevenueCatのエクスポートファイルをそのまま送信できます。変換は不要です。エクスポート手順については[RevenueCatのドキュメント](https://www.revenuecat.com/docs/integrations/scheduled-data-exports)を参照してください。 ::: 以下のルールに従ったファイルでデータを準備してください: - [ ] ファイル形式は.CSVです。 - [ ] Android、iOS、Stripeのインポートはそれぞれ別々のファイルを使用します。 - [ ] すべてのインポートファイルに[必須カラム](importing-historical-data-to-adapty#required-fields)がすべて含まれています。 - [ ] インポートファイルのカラムにヘッダーがあります。 - [ ] カラムヘッダーは下記の表の**Column name**列に記載されているものと完全に一致します。タイポがないか確認してください。 - [ ] 必須でないカラムはファイルに含めなくてもかまいません。データがない場合、空のカラムを追加しないでください。 - [ ] インポートファイルには、表に記載されていない余分なカラムを含めないでください。含まれている場合は削除してください。 - [ ] 値はカンマで区切られています。 - [ ] 値は引用符で囲まれていません。 - [ ] 1人のユーザーに対して複数の**apple_original_transaction_id**がある場合、それぞれの**apple_original_transaction_id**ごとに別の行として追加してください。そうしないと、消耗型アイテムの購入を復元できない場合があります。 サンプルファイルとして、[iOS](https://raw.githubusercontent.com/adaptyteam/adapty-docs/refs/heads/main/Downloads/adapty_import_ios_sample.csv)および[Android](https://raw.githubusercontent.com/adaptyteam/adapty-docs/refs/heads/main/Downloads/adapty_import_android_sample.csv)のファイルをご利用ください。 ### インポートファイルの利用可能なカラム \{#available-import-file-columns\} | カラム名 | 必須/任意 | 説明 | |-----------|--------|-----------| | **user_id** | 必須 | ユーザーのID | | **apple_original_transaction_id** | iOSで必須 | <p>オリジナルトランザクションIDまたはOTID([詳細](https://developer.apple.com/documentation/appstoreserverapi/originaltransactionid))。StoreKit 2のインポートメカニズムで使用されます。1人のユーザーが複数のOTIDを持つ場合、インポートを成功させるには少なくとも1つを提供すれば十分です。</p><p></p><p>**注意:** このインポートにはAdapty Dashboardでアプリ内購入APIの資格情報を設定する必要があります。設定方法は[こちら](app-store-connection-configuration#step-3-upload-in-app-purchase-key-file)をご覧ください。</p> | | **google_product_id** | Googleで必須 | Google Play StoreのプロダクトID | | **google_purchase_token** | Googleで必須 | ユーザーと購入したアプリ内プロダクトのプロダクトIDを表す一意の識別子 | | **google_is_subscription** | Googleで必須 | 使用可能な値は `1` \| `0` | | **stripe_token** | Stripeで必須 | 一意の購入を表すStripeオブジェクトのトークン。StripeのSubscription(`sub_...`)またはPayment Intent(`pi_...`)のトークンのいずれかを使用できます。 | | **subscription_expiration_date** | 任意 | サブスクリプションの有効期限日(次の課金日)。タイムゾーン付きの日時(2020-12-31T23:59:59-06:00) | | **created_at** | 任意 | プロファイル作成日時(2019-12-31 23:59:59-06:00) | | **birthday** | 任意 | ユーザーの誕生日(形式:2000-12-31) | | **email** | 任意 | ユーザーのメールアドレス | | **gender** | 任意 | ユーザーの性別 | | **phone_number** | 任意 | ユーザーの電話番号 | | **country** | 任意 | 形式:[ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) | | **first_name** | 任意 | ユーザーの名 | | **last_name** | 任意 | ユーザーの姓 | | **last_seen** | 任意 | タイムゾーン付きの日時(2020-12-31T23:59:59-06:00) | | **idfa** | 任意 | IDFA(広告識別子)は、Appleがユーザーのデバイスに割り当てるランダムなデバイス識別子です。iOSアプリのみに適用されます | | **idfv** | 任意 | IDFV(ベンダー識別子)は、1人の開発者が開発したすべてのアプリに割り当てられる一意のコードです。iOSアプリのみに適用されます | | **advertising_id** | 任意 | 広告IDは、AndroidのOSによって割り当てられる一意のコードで、広告主がユーザーのデバイスを一意に識別するために使用することがあります | | **amplitude_user_id** | 任意 | AmplitudeのユーザーID | | **amplitude_device_id** | 任意 | AmplitudeのデバイスID | | **mixpanel_user_id** | 任意 | MixpanelのユーザーID | | **appmetrica_profile_id** | 任意 | AppMetricaのユーザープロファイルID | | **appmetrica_device_id** | 任意 | AppMetricaのデバイスID | | **appsflyer_id** | 任意 | AppsFlyerの一意識別子 | | **adjust_device_id** | 任意 | AdjustのデバイスID | | **facebook_anonymous_id** | 任意 | Facebookがアプリやウェブサイトに匿名でアクセスするユーザー(Facebookにログインしていない状態)に対して生成する一意識別子 | | **branch_id** | 任意 | Branchの一意識別子 | | **attribution_source** | 任意 | アトリビューションのソースインテグレーション(例:appsflyer) | | **attribution_status** | 任意 | organic | | **attribution_channel** | 任意 | トランザクションをもたらしたアトリビューションチャネル | | **attribution_campaign** | 任意 | トランザクションをもたらしたアトリビューションキャンペーン | | **attribution_ad_group** | 任意 | トランザクションをもたらしたアトリビューション広告グループ | | **attribution_ad_set** | 任意 | トランザクションをもたらしたアトリビューション広告セット | | **attribution_creative** | 任意 | 広告やマーケティングキャンペーンで使用される特定のビジュアルまたはテキスト要素。クリック、コンバージョン、インストールなどの目的のアクションを促進する効果を測定するために追跡されます | | **custom_attributes** | 任意 | キーと値の形式のJSON辞書として最大30個のカスタム属性を定義します:<ul><li>**key**:(文字列)カスタム属性の名前</li><li>**value**:(文字列、整数、浮動小数点数、またはブール値)カスタム属性の値</li></ul><p>形式:`"{'string_value': 'some_value', 'float_value': 123.0, 'int_value': 456}"`</p><p>形式内のダブルクォートとシングルクォートの使い方に注意してください。ブール値と整数は浮動小数点数に変換されることにご注意ください。</p> | ### 必須フィールド \{#required-fields\} 各プラットフォームには、**user_id**と対応するプラットフォーム固有の購入を識別するデータという2つの必須フィールドグループがあります。プラットフォームごとの必須フィールドは下記の表を参照してください。 | プラットフォーム | 必須フィールド | |--------|---------------| | iOS | <p>user_id</p><p>apple_original_transaction_id</p> | | Android | <p>user_id</p><p>google_product_id</p><p>google_purchase_token</p><p>google_is_subscription</p> | | Stripe | <p>user_id</p><p>stripe_token</p> | これらのフィールドがなければ、Adaptyはトランザクションを取得できません。 正確なコホートアナリティクスのために、`created_at`を指定してください。指定しない場合、インストール日は最初の購入日と同じとみなされます。 ### Adaptyへのデータインポート \{#import-data-to-adapty\} [support@adapty.io](mailto:support@adapty.io)または[Adapty Dashboard](https://app.adapty.io/overview)のオンラインチャットからお問い合わせいただき、インポートファイルを共有してください。 --- # File: migrate-integrations-to-adapty --- --- title: "Adaptyへのインテグレーション移行" description: "レガシーソリューションからAdaptyへのアナリティクスおよびアトリビューションインテグレーションの切り替えを、イベントの重複やキャンペーンの中断なく行う方法。" --- Adaptyへの移行はSDKの切り替えだけでは完結しません。AmplitudeやAdjustなどのサードパーティのアナリティクス・アトリビューションインテグレーションも、並行して切り替える必要があります。慎重に進めれば、重複や欠落イベントを最小限に抑え、キャンペーンを中断させることなく移行できます。 ## イベントのマッピング \{#map-your-events\} ほとんどのAdaptyインテグレーションでは、イベント名をカスタマイズできます。ダッシュボードやキャンペーンですでに使用しているイベント名に合わせて設定することが可能です。これにより、切り替え後も同じイベント名でアナリティクスやキャンペーンのレポートを継続して利用できます。Adaptyで利用可能なイベントの一覧は、[イベント](events)をご確認ください。 Adjustの場合、インテグレーションではカスタムイベント名の代わりにイベントIDを使用します。AdjustダッシュボードのイベントIDをAdaptyのインテグレーション設定に移行してください。詳細は[Adjustインテグレーションガイド](adjust)を参照してください。 ## Adaptyによるインテグレーションイベントの作成方法 \{#how-adapty-creates-integration-events\} インテグレーションにイベントを送信するには、Adaptyにユーザーのプロファイルが必要です。プロファイルは以下のいずれかの方法で作成されます: - **過去データのインポート**:SDKが稼働する前に[過去のトランザクションデータをインポート](importing-historical-data-to-adapty)した際にプロファイルが作成されます。 - **SDKとのインタラクション**:ユーザーが初めてAdapty SDKを搭載したアプリを開いたときに自動的にプロファイルが作成されます。 Adaptyはレガシーシステムで行われた購入をリアルタイムで把握しますが、購入者のプロファイルが存在して初めてインテグレーションイベントを送信できます。プロファイルはユーザーがAdapty SDKを搭載したアプリを開いたときに作成されます。新バージョンにアップデートしないユーザーは、インテグレーションイベントを生成しません。 ## 移行前の準備 \{#prepare-before-migration-day\} ### 過去イベントの除外 \{#exclude-historical-events\} [インテグレーション設定](configuration)で **Exclude Historical Events** を有効にしてください。これにより、ユーザーの最初のAdapty SDKセッション以前のイベントがインテグレーションに送信されるのを防ぎます。 この設定は、大量の過去トランザクションをまとめて処理する[過去データのインポート](importing-historical-data-to-adapty)時に特に重要です。有効にしないと、それらのトランザクションがアナリティクスツールに大量のイベントを生成してしまいます。 ### インテグレーションを事前にセットアップする \{#set-up-the-integration-in-advance\} Adaptyでは、インテグレーションを無効のままテストや設定を行うことができます。認証情報、イベントのマッピング、フィルターを設定しておき、準備が整うまでインテグレーションを有効化しないことが可能です。設定は保存されるため、移行当日まで無効にしておいても何も失われません。 インテグレーションの確認方法については、[アトリビューションインテグレーション](attribution-integration)、[アナリティクスインテグレーション](analytics-integration)、[メッセージングサービスインテグレーション](messaging)、または[WebhookおよびETLインテグレーション](webhook-and-etl)を参照してください。 ## 移行当日の切り替え \{#switch-on-migration-day\} レガシーソリューションのインテグレーションを無効にすると同時に、Adaptyのインテグレーションを有効にしてください。両方を同時に動かすと、イベントが重複して送信されます。 移行当日は大規模な獲得キャンペーンを一時停止してください。これにより、切り替えのタイミングで発生するイベントのオーバーラップによるキャンペーン最適化エラーのリスクを軽減できます。 ## 移行後に想定されること \{#what-to-expect\} 移行中にインテグレーションイベントの欠落や重複がある程度発生するのは避けられません。ただし、正しく切り替えを行えば、影響を受けるイベントの数はごくわずかです。 欠落の主な原因は前述のタイミングの問題です。Adaptyは購入者のプロファイルが作成されて初めて、その購入に対するインテグレーションイベントを送信できます。レガシーシステムで行われた購入は、購入者がAdapty SDKを搭載したアプリを開くまでAdaptyのインテグレーションイベントを生成しません。 ## インテグレーションとサーバー間通知の違い \{#integrations-vs-server-to-server-notifications\} Adaptyは、ストアからの生のサーバー間通知をアナリティクスやアトリビューションツールに直接転送するのではなく、インテグレーションを使用することを推奨しています。 インテグレーションを利用するメリット: - **統一されたフォーマット**:App Store、Google Play、Stripeなど、すべてのストアからのイベントが同じイベントフォーマットで送信されます。 - **データの充実**:イベントにはサブスクリプションの状態やユーザー属性など、Adaptyが収集するデータが含まれます。生の通知にはこれらは含まれません。 --- # File: whats-new --- --- title: "最新情報" description: "Adaptyの最新機能と改善内容をご確認ください" --- 最新機能、改善内容、SDKアップデート、ドキュメントの更新情報をまとめています。アプリのマネタイズ戦略を最適化するのに役立つ、毎月の主要リリースをご紹介します。 :::note 新機能へのフィードバックをお聞かせください! ぜひご意見をお寄せください。[プロダクトフィードバックボード](https://adapty.featurebase.app/en?b=69831ba5e82e7a3391632ec2)からお気軽にご連絡ください。 ::: ## 2026年6月 \{#june-2026\} - **Apple Ads Manager の CPP A/B テスト**: Apple Ads 内でカスタムプロダクトページを相互に比較できます。現在のデフォルトを含む2〜4ページを選択すると、Apple Ads がトラフィックをローテーションし、どのページが最もコンバージョン率が高いかをレポートします。[詳細はこちら](ads-manager-cpp-ab-tests) - **Adapty Mail API**: SDK を経由せずに、サーバーから直接 Adapty Mail にユーザープロファイルとトランザクションを送信できます。サブスクライバーベースの初期データ投入、他のアプリのサブスクライバーの再利用、またはバックエンドをデータの正規ソースとして維持するのに活用できます。[詳細はこちら](mail-send-data-via-api) - **初回起動時にApple Ads向けペイウォールを表示する**: Apple AdsのアトリビューションはSDKのアクティベーション後に届くため、早すぎるタイミングでペイウォールをリクエストするとApple Ads向けオーディエンスを見逃す可能性があります。`AdaptyProfile.appliedAttributionSources`を使って、アトリビューションデータが届いた時点でApple Ads向けペイウォールをすぐに表示しましょう。[iOS](ios-show-aa-targeted-paywall) | [React Native](react-native-show-aa-targeted-paywall) | [Capacitor](capacitor-show-aa-targeted-paywall) - **フロービルダーの自動保存**: フロービルダーが1分ごとに進行状況を自動保存するようになりました。ページを離れても未保存の作業が失われる心配はありません。**Cmd/Ctrl + S** で手動ドラフト保存も引き続き利用できます。[詳細はこちら](builder-save-publish) - **フロービルダーの新しい動画チュートリアル**: フロー画面間のナビゲーション構築と、選択済み・アクティブ・無効などの要素ステートのデザインを解説する2本のウォークスルー動画を追加しました。[フロー内のナビゲーション](onboarding-navigation-branching) | [要素のステート](builder-element-states) - **日本語とベトナム語のドキュメント**: Adaptyのドキュメントが日本語(日本語)とベトナム語(Tiếng Việt)で利用可能になりました。上部ナビゲーションの言語セレクターで切り替えができます。 ## 2026年5月 \{#may-2026\} - **フロー(ベータ)**: ビジュアルなノーコードビルダーで画面シーケンス全体を作成できます — 単一画面のペイウォール、マルチステップのオンボーディング、そしてその間のあらゆるものを1つのフローで実現。画面はWebビューを使わずネイティブにレンダリングされ、アプリのリリースなしにコピー、デザイン、ロジックを更新できます。現在、iOS SDK v4以降をサポートしています。[詳細を見る](adapty-flow-builder) - **オートパイロットがテスト結果に自動で適応するようになりました**: AI成長マネージャーとして機能し、ラウンドが完了するたびに成長計画を更新します。次の仮説は、実施した実験、勝利した実験、そしてまだ探索する価値のある方向性を踏まえて構築されます。固定のシーケンスに従うのではなく、結果に基づいて進化します。[詳しくはこちら](autopilot-how-it-works#how-autopilot-decides-what-to-recommend) - **Autopilot マーケットインサイトのアクティベーション ARPU**: 新しいチャートで、アプリの新規インストールあたりの平均収益をカテゴリ平均と比較できます。コンバージョンファネルと組み合わせて使うと効果的で、コンバージョンが高いのにアクティベーション ARPU が低い場合は、価格が低すぎる可能性を示している可能性があります。[詳細を見る](autopilot-analysis#activation-arpu) - **Adapty Mail のアナリティクス**: 各キャンペーンの配信指標とメール経由の収益を一画面で比較できます。キャンペーン、セグメント、A/B バリアント、メッセージ、トリガーでグループ化・絞り込み・内訳表示が可能で、任意の行をドリルダウンすることもできます。[詳細を見る](mail-analytics) - **Adapty Mailにおけるブランドプロファイル**: メールのコピー、トーン、ビジュアル、ウェブペイウォールのコンテンツを一元管理するプロファイルです。アプリのストアリスティング、ランディングページ、法的ページ、ソーシャルプロファイルをもとにAdaptyが構築し、各セクションをインラインで確認・編集できます。[詳細を見る](mail-brand) - **Adapty UA の予測**: 各コホートの予測収益、ROAS、広告利益、ARPU、ARPPU を確認できるため、キャンペーンが成熟する前に比較できます。予測はアプリ独自の過去のコホートデータから構築され、毎日更新され、D0 から D360 または任意の日のコホート期間で利用できます。[詳細を見る](ua-predicted-metrics) - **Adapty UA カスタム S3 エクスポートの新しいフィールド**: カスタム S3 エクスポートに `bundle_id`、`device_brand`、`device_model`、`os_version`、`app_version`、`sdk_version` が追加されました。デバイスやアプリバージョンごとにアトリビューションデータをスライス・結合できます。[詳しくはこちら](ua-custom-s3) - **CLI でのプレースメントオーディエンス**: `adapty placements create` および `adapty placements update` コマンドに `--audiences` フラグが追加されました。`{segment_ids, paywall_id, priority}` エントリの JSON 配列を指定することで、ターミナルから異なるセグメントに異なるペイウォールをターゲティングできます。新しい `adapty paywalls placements` コマンドは、指定したペイウォールを使用しているすべてのプレースメントを一覧表示するため、切り替え前に影響を確認できます。[詳細はこちら](developer-cli-reference#placements) - **スペイン語版ドキュメント**: Adapty ドキュメントがスペイン語(Español)でもご利用いただけるようになりました。上部ナビゲーションの言語セレクターから切り替えてください。 ## 2026年4月 \{#april-2026\} - **Adapty Mail**: トライアルユーザーを有料サブスクライバーへ転換するAI生成メールキャンペーン。Adaptyプロジェクトからキャンペーンの作成・送信・アトリビューションをすべて管理でき、別途メールプラットフォームは不要です。[詳細を見る](adapty-mail) - **Autopilot でのペイウォール診断**: テストを始める前に、ペイウォールの改善点を把握できます。スクリーンショットをアップロードすると、Autopilot が同カテゴリの上位アプリのベンチマークに基づく推奨事項と、AI が生成したレイアウト・コピーの提案を返します。ベンチマーク結果はグロースプランの A/B テストラウンドになります。[詳細はこちら](autopilot-analysis#paywall-analysis) - **すべての Autopilot 提案がわかりやすくなりました**: 各仮説に、なぜそれが重要なのか(ペイウォールが確立されたパターンからどう外れているかをデータで説明)、何を変更すべきか・A/B テストの設定方法、そして結果の読み方を解説する「How to interpret your results」セクションが追加されました。[詳細を見る](autopilot-execute-plan#step-1-view-the-hypothesis) - **Autopilot成長プランを最新の状態に保つ**: 分析を更新して最新の市場データや新しい提案を取り込み、バージョン履歴から過去の提案を見直すこともできます。仮説はTop priority、All、Pricing、Visual、Geo-pricing、Archivedタブに分類されています。[詳しくはこちら](autopilot-growth-plan) - **Autopilot の期間別収益分布**: サブスクリプション期間が一つに偏っていないか確認できます。新しい Market Insights チャートでは、カテゴリーと国ごとの業界平均と並べて、期間別の収益構成を表示します。[詳細を見る](autopilot-analysis#revenue-distribution-by-duration) - **LTV と収益予測の更新**: 予測 LTV および収益は、十分な履歴データがある場合はアプリ独自のコホートリテンションデータを使用し、そうでない場合はクロスアプリの平均値を使用するようになりました。これにより、新しいアプリでも分析や A/B テストで実用的な予測が得られます。[詳細はこちら](predicted-ltv-and-revenue) - **Adapty UA でのすべてのイベント送信**: Meta と TikTok にコンバージョンの全体像を提供し、オーディエンスモデリングの精度を高めます。Adapty では、キャンペーンにマッチしたユーザーだけでなく、オーガニックや未アトリビューションユーザーのインストールおよびトランザクションをピクセルに転送できるようになりました。[Meta](ua-facebook#send-all-events) | [TikTok](ua-tiktok#send-all-events) - **ロシア語とトルコ語のドキュメント**: Adapty ドキュメントがロシア語(Русский)とトルコ語(Türkçe)で利用できるようになりました。上部ナビゲーションの言語セレクターで切り替えてください。 ## 2026年3月 \{#march-2026\} - **Developer CLI**: ダッシュボードを開かずにターミナルからAdaptyアカウントを管理できます。CLIを使うと、アプリの作成、アクセスレベルの定義、プロダクトのセットアップ、ペイウォールの作成、プレースメントの設定を行うことができ、自動化された環境でスクリプト化することも可能です。AIコーディングアシスタントがCLIを使いやすくなるための[Adapty CLIスキル](https://github.com/adaptyteam/adapty-cli/tree/main/skills/adapty-cli)も利用できます。[詳細を見る](developer-cli) - **Apple Ads ManagerのOverviewページ**: 主要なApple Ads指標をすべて1か所で確認でき、各指標にはトレンドチャートが表示されます。ヘッダーのドロップダウンでアプリを絞り込み、表示する指標のカスタマイズやチャートの種類・収益表示の調整も可能です。[詳細はこちら](ads-manager-overview) - **Apple Ads ManagerのMarket Intelligence**: 競合他社が50か国以上でどのキーワードに広告を出稿しているかを確認し、パフォーマンスの高いキーワードをキャンペーンに直接追加できます。[詳細はこちら](ads-manager-market-intelligence) - **Apple Ads Managerにおけるキーワードの完全サイクル自動化**: 定義したパフォーマンスルールに基づき、入札額の調整、キーワードの一時停止・有効化、広告グループ間の移動を自動で行えます。[詳細を見る](ads-manager-automations-keyword-rules) - **Apple Ads Managerにおける入札履歴**: 任意のキーワードのCPT入札額の変更ログ(変更日時、変更前後の値、トリガーとなった自動化ルール)を確認できます。[詳細を見る](ads-manager-manage-keywords#bid-history) - **Autopilotのビジュアルラウンド**: ペイウォールデザインの提案が、グロースプランのファーストクラスのラウンドとして追加されました。収益化ラウンドと並んでサイドバーに表示され、各ビジュアルラウンドにはデザインのモックアップ、そのパターンが最も効果的な場面の説明、および対象となる主要な指標が含まれています。[詳しくはこちら](autopilot-growth-plan#view-the-growth-plan) - **Autopilot に独自の仮説を追加する**: カスタムラウンドを追加して成長プランを拡張できます。タイトル、説明、ラウンドタイプ(マネタイゼーションまたはビジュアル)、目標指標、そしてマネタイゼーションラウンドの場合は関連プロダクトを設定できます。[詳細はこちら](autopilot-growth-plan#add-your-own-hypothesis) - **Autopilot ラウンドの並べ替え**: 成長プランのステージをドラッグして並べ替え、戦略に最適な順序で実験を実行できます。[詳細はこちら](autopilot) - **Autopilot のジオプライシングラウンド**: 成長プランの新しいラウンドタイプとして、国別の価格変更をテストできます。Market Insights のデータをもとに、Autopilot が各国で価格を上げるか、下げるか、維持するかを推奨します。推奨事項をジオプライシングラウンドとして追加すると、A/B テストとして実行できます(最大5件を同時実行可能)。[詳細はこちら](autopilot-growth-plan#geo-pricing-hypotheses) - **Apple Ads Managerの検索語句オートメーション**: 手動でレポートをダウンロードすることなく、勝利した検索語句を完全一致キーワードに自動的にプロモートし、ソースで除外できます。ルールはテンプレートから作成することも、カスタム条件やスケジュールを使って一から作成することもできます。[詳しくはこちら](ads-manager-automations-search-terms) - **Apple Ads ManagerのMaximize Conversions入札**: キャンペーン作成時に、入札戦略としてMaximize Conversionsを選択できるようになりました。Appleのアルゴリズムが、オプションの目標CPAをガイドラインとして、予算内でダウンロード数を最大化します。[詳細はこちら](ads-manager-create-campaign) - **Adapty UAでのFunnelFoxインテグレーション**: Adapty UAにFunnelFoxとの新しいインテグレーションが追加されました。[FunnelFox](ua-funnelfox) - **中国語ドキュメント**: Adaptyのドキュメントが中国語(中文)で利用できるようになりました。上部ナビゲーションの言語セレクターで言語を切り替えてください。 ## 2026年2月 \{#february-2026\} - **国別プロダクト価格設定**: Adapty ダッシュボードから直接、国ごとに異なる価格を設定できます。変更は App Store Connect と Google Play に自動で同期され、すべての価格更新は監査ログに記録されるため、変更を見逃すことはありません。[詳細を見る](edit-product) - **Autopilot における国レベルの競合価格比較**: 主要市場での競合他社のサブスクリプション価格と自社の価格を比較できます。[詳細を見る](autopilot-analysis#market-and-competitor-analysis) - **オンボーディングのバージョン管理**: オンボーディングのバージョンを完全な変更履歴とともに管理できます。変更内容を確認し、必要に応じてロールバックも可能です。 - **アナリティクスのペイウォールコンバージョンチャート**: 「ペイウォール表示 → トライアル」と「ペイウォール表示 → 有料」の2つの新しいコンバージョンチャートにより、ペイウォールが閲覧者をサブスクリプション登録者へどのように転換しているかを把握できます。[詳しくはこちら](analytics-conversion) - **セグメントの複製**: 既存のセグメントをすべてのフィルターごとコピーして、類似したセグメントをゼロから作り直す手間を省けます。重複するオーディエンスで複数のキャンペーンや A/B テストを実行する場合に便利です。[詳細を見る](segments#duplicate-segments) - **Adapty モバイルアプリでのプッシュ通知**: Adapty iOS アプリで 14 種類のイベントに対するプッシュ通知を設定することで、ダッシュボードを開かなくてもサブスクリプションの状況を把握できます。[詳細を見る](push-notifications) - **Kotlin Multiplatform SDK 3.15**: オンボーディングサポート、Webペイウォール、APIの改善を追加。[詳細はこちら](migration-to-kmp-315) - **Capacitor SDK 3.16**: Capacitor 8サポートを追加。Capacitor 7を使用しているプロジェクトはSDK v3.15のままにしてください。[詳細はこちら](migration-to-capacitor-316) - **LLM支援SDKインテグレーションガイド**: AIコーディングアシスタントの助けを借りてAdaptyを統合するためのステップバイステップガイド。ダッシュボードのセットアップから購入まで、実装全体をLLMと一緒に進められます。[iOS](adapty-cursor) | [Android](adapty-cursor-android) | [React Native](adapty-cursor-react-native) | [Flutter](adapty-cursor-flutter) | [Unity](adapty-cursor-unity) | [Kotlin Multiplatform](adapty-cursor-kmp) | [Capacitor](adapty-cursor-capacitor)。ワンコマンドの自動フローには、新しい**adapty-sdk-integration skill**(ベータ版)をお試しください: [iOS](adapty-sdk-integration-skill) | [Android](adapty-sdk-integration-skill-android) | [React Native](adapty-sdk-integration-skill-react-native) | [Flutter](adapty-sdk-integration-skill-flutter) | [Unity](adapty-sdk-integration-skill-unity) | [Kotlin Multiplatform](adapty-sdk-integration-skill-kmp) | [Capacitor](adapty-sdk-integration-skill-capacitor) ## 2026年1月 \{#january-2026\} - **Capacitor SDKが正式リリース**: Capacitor SDKが十分なテストを経て、プロダクション対応になりました。Adaptyとの完全な統合サポートにより、CapacitorでiOSおよびAndroid向けのサブスクリプションアプリを構築できます。[詳細はこちら](capacitor-sdk-overview) - **新規アプリ向けオートパイロット**: トランザクション履歴が少ないアプリでも、オートパイロット分析が利用できるようになりました。データに基づく価格最適化の提案を受け取り、初日から成長プランを作成できます。[詳細はこちら](autopilot) - **Autopilot のグローバル価格設定機会**: 国別の価格設定の推奨事項により、主要市場での収益ポテンシャルを把握できます。Autopilot は次の上位 5 か国のコンバージョン率と購買力を分析し、Adapty Pricing Index に基づいて価格を上げるべきか、下げるべきか、据え置くべきかについてデータに基づいたインサイトを提供します。[詳しくはこちら](autopilot) - **支払い回収のコンバージョン指標**: 支払い問題やグレース期間から回収された収益を追跡する新しいアナリティクスチャートが追加されました。「Billing issue converted」「Billing issue converted revenue」「Grace period converted」「Grace period converted revenue」の各指標で、リテンション回復の取り組みを測定できます。 - **Apple Ads Manager での広告管理**: プラットフォームを切り替えることなく、Adapty 内で直接 Apple Ads キャンペーンを作成・管理できます。[詳細を見る](ads-manager-manage-ads) - **Apple Ads Manager analytics**: Adapty 内で広告レベルの詳細なパフォーマンス指標とアトリビューションデータにアクセスできます。キャンペーンのパフォーマンス、広告グループのアナリティクス、アトリビューションのインサイトを統合ダッシュボードで確認できます。[詳細はこちら](adapty-ads-manager-analytics) - **Apple Ads アトリビューションチャート**: 複数のアトリビューション指標をカスタマイズ可能なチャートに組み合わせて、サブスクリプションデータと合わせて Apple Ads のパフォーマンスを分析できます。[詳細はこちら](adapty-ads-manager-analytics#charts) - **Apple Ads アトリビューション セグメント**: Apple Ads のアトリビューションデータをもとに、2クリックで素早くユーザーセグメントを作成できます。キャンペーン、広告グループ、またはキーワードでユーザーをターゲティングし、より精度の高い分析や実験を行いましょう。[詳しくはこちら](ads-manager-create-segments) - **新しいドキュメントプラットフォーム**: ドキュメントサイトを新しいプラットフォームに移行しました。検索・ナビゲーション・コンテンツ構成が強化され、機能の更新が迅速に行えるようになり、ユーザー体験が向上しています。 ## 2025年12月 \{#december-2025\} - **Apple Ads Manager ドキュメント**: Apple Search Ads のキャンペーンデータと収益指標を1つのアナリティクスダッシュボードで確認できます。新しいドキュメントでは、キャンペーンの作成、広告グループの管理、サブスクリプションのパフォーマンスと広告費用対効果のトラッキング方法を解説しています。[詳しく見る](ads-manager) - **アプリ内ウェブペイウォール**: アプリ内ブラウザを使ってウェブベースのペイウォールをアプリ内に表示し、外部へのリダイレクトなしでシームレスな体験を提供します。[iOS](ios-web-paywall#open-web-paywalls-in-an-in-app-browser) | [Android](android-web-paywall#open-web-paywalls-in-an-in-app-browser) | [React Native](react-native-web-paywall#open-web-paywalls-in-an-in-app-browser) | [Flutter](flutter-web-paywall#open-web-paywalls-in-an-in-app-browser) - **ローリングセグメント**: 動的なオーディエンスセグメントを作成できます。移動する時間ウィンドウに基づいて自動的に更新されるため、たとえば「過去7日以内にアプリをインストールしたユーザー」というセグメントを作成すると、常に最新のユーザーが表示された状態に保たれます。[詳細はこちら](segments#available-attributes) - **MetaおよびTikTokキャンペーン設定ガイド**: Meta(Facebook & Instagram)およびTikTokでキャンペーンを作成・追跡するためのステップバイステップのドキュメントです。コンバージョントラッキングやアナリティクス連携についても説明しています。[Meta](meta-create-campaign) | [TikTok](tiktok-create-campaign) - **手動ペイウォール実装クイックスタートガイド**: カスタムペイウォール UIにAdapty SDKを組み込む手順をステップバイステップで解説するクイックスタートガイドで、アプリ内課金をすばやく実装できます。[iOS](ios-implement-paywalls-manually) | [Android](android-implement-paywalls-manually) | [React Native](react-native-implement-paywalls-manually) | [Flutter](flutter-implement-paywalls-manually) | [Unity](unity-implement-paywalls-manually) | [Kotlin Multiplatform](kmp-quickstart-manual) | [Capacitor](capacitor-quickstart-manual) - **オンボーディングリンクのアプリ内ブラウザ対応**: オンボーディング内の外部リンクは、デフォルトでアプリ内ブラウザで開くようになり、ユーザーがアプリを離れません。必要に応じて外部ブラウザを使用するよう動作をカスタマイズすることも可能です。 [iOS](ios-present-onboardings#customize-how-links-open-in-onboardings) | [Android](android-present-onboardings#customize-how-links-open-in-onboardings) | [React Native](react-native-present-onboardings#customize-how-links-open-in-onboardings) - **Autopilot の提案が改善されました**: Autopilot がサブスクリプションデータをより詳細に分析し、価格最適化の提案精度が向上しました。[Autopilot を試す](autopilot) - **ドキュメントのダークモード対応**: ドキュメントがダークモードに対応しました。システム設定に合わせて自動切替、または右上のボタンで手動切替ができます。 --- # File: generate-in-app-purchase-key --- --- title: "App Store ConnectでIn-App Purchase Keyを生成する" description: "安全な取引のためのアプリ内課金キーを生成します。" --- **In-App Purchase Key**は、購入の正当性を確認することで購入を検証するために、App Store Connect内で作成される専用のAPIキーです。 :::note App Store Server APIのAPIキーを生成するには、App Store ConnectでAdminまたはAccount Holderのロールを持っている必要があります。APIキーの生成方法については、[Apple Developer Documentation](https://developer.apple.com/documentation/appstoreserverapi/creating-api-keys-to-authorize-api-requests)でも確認できます。 ::: 1. **App Store Connect**を開きます。[**Users and Access** → **Integrations** → **In-App Purchase**](https://appstoreconnect.apple.com/access/integrations/api/subs)セクションに進みます。 2. **Active**タイトルの横にある追加ボタン **(+)** をクリックします。 <img src="/assets/shared/img/6d737db-generate_in-app_key.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. 表示された **Generate In-App Purchase Key** ウィンドウで、後から参照しやすいようにキーの名前を入力します。この名前はAdaptyでは使用されません。 4. **Generate** ボタンをクリックします。**Generate in-App Purchase Key** ウィンドウが閉じると、作成されたキーが **Active** リストに表示されます。 <img src="/assets/shared/img/fac066b-download_inapp_file.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. APIキーを生成したら、**Download In-App Purchase Key** ボタンをクリックして、キーをファイルとして取得します。 <img src="/assets/shared/img/d59faff-download_in-app_purchase_key.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 6. **Download in-App Purchase Key** ウィンドウで、**Download** ボタンをクリックします。ファイルがコンピューターに保存されます。 このファイルは、後でAdapty ダッシュボードにアップロードするために安全に保管することが非常に重要です。生成されたファイルはダウンロードが1回しかできないため、アップロードするまで安全に保管してください。**In-App Purchase**セクションで生成した.p8キーは、[AdaptyとApp Storeの初期連携設定](app-store-connection-configuration#step-3-upload-in-app-purchase-key-file)の際に使用されます。 **次のステップ:** - [App Store連携を設定する](app-store-connection-configuration) --- # File: app-store-connection-configuration --- --- title: "App Store 連携を設定する" description: "シームレスなサブスクリプション追跡のために App Store 接続を設定します。" --- <div style={{ maxWidth: '560px', margin: '0 auto 2rem', position: 'relative', aspectRatio: '16/9', width: '100%' }}> <iframe style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%' }} src="https://www.youtube.com/embed/VJQbzoTCkqs?si=l7BPX9mIu6GVGZ0Z" title="YouTube video player" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerPolicy="strict-origin-when-cross-origin" allowFullScreen /> </div> このセクションでは、iOS アプリの App Store と Adapty の接続を確立する方法について説明します。これは、サブスクリプション分析の表示と購入の検証を行うために必要です。インテグレーションは初回オンボーディング時、または後から Adapty ダッシュボードの **App Settings** で完了できます。 オンボーディング中にモバイルアプリと Adapty のインテグレーションを設定していた場合でも、**App settings** で後からこれらの設定を変更できます。 :::danger 設定の変更は、Adapty SDK をインストールしたモバイルアプリが公開される前のサンドボックスフェーズ中であれば安全に行えます。リリース後に変更すると、アプリの購入フローが壊れる可能性があります。 ::: ## ステップ 1. Bundle ID と Apple app ID を入力する \{#step-1-provide-bundle-id-and-apple-app-id\} **Bundle ID** と **Apple app ID** はどちらも必須です。**Bundle ID** は App Store におけるアプリの一意の識別子で、サブスクリプション処理などの Adapty のコア機能を有効にします。**Apple app ID** は、**Products** ページから[新しいプロダクトを作成してストアにプッシュする](create-product#create-product-and-push-to-store)際にも必要です。 :::note **Apple app ID** がない場合、**Products** ページの **Create a new product and push to stores** オプションは無効になりますが、ダッシュボードにはその理由が表示されません。 ::: --- no_index: true --- 1. [App Store Connect](https://appstoreconnect.apple.com/apps) を開きます。アプリを選択し、**General** → **App Information** セクションに進みます。 2. **General Information** サブセクションで **Bundle ID** をコピーします。 <Zoom> <img src="/docs/img/afd5012-bundle_id_apple.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> </Zoom> 3. Adapty のトップメニューから [**App settings** -> **iOS SDK** タブ](https://app.adapty.io/settings/ios-sdk) を開き、コピーした値を **Bundle ID** フィールドに貼り付けます。 <Zoom> <img src="/docs/img/2d64163-bundle_id.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> </Zoom> 4. App Store Connect の **App information** ページに戻り、**Apple ID** をコピーします。 5. Adapty ダッシュボードの [**App settings** -> **iOS SDK**](https://app.adapty.io/settings/ios-sdk) ページで、**Apple app ID** フィールドにその ID を貼り付けます。 ## ステップ 2. Issuer ID と Key ID を入力する \{#step-2-provide-issuer-id-and-key-id\} **In-app purchase Issuer ID**(App Store Connect では **Issuer ID** と表記)は、認証トークンを作成した発行者を識別する特別な ID です。**In-App Purchase Key ID**(App Store Connect では **Key ID** と表記)は、[App Store Connect でアプリ内購入キーを生成する](generate-in-app-purchase-key)セクションで生成した暗号化キーに関連付けられた一意の識別子です。 1. **App Store Connect** を開きます。[**Users and Access** → **Integrations** → **In-App Purchase**](https://appstoreconnect.apple.com/access/integrations/api/subs) セクションに進みます。 2. **Active** リストで、[App Store Connect でアプリ内購入キーを生成する](generate-in-app-purchase-key)セクションで作成したキーを見つけます。 <img src="/assets/shared/img/19a2868-issuer_apple.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. **Issuer ID** をコピーして、Adapty ダッシュボードの **In-app purchase Issuer ID** フィールドに貼り付けます。 <img src="/assets/shared/img/c2b42e7-issuer_id.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **Key ID** をコピーして、Adapty ダッシュボードの **In-app purchase Key ID** フィールドに貼り付けます。 ## ステップ 3. アプリ内購入キーファイルをアップロードする \{#step-3-upload-in-app-purchase-key-file\} [App Store Connect でアプリ内購入キーを生成する](generate-in-app-purchase-key)セクションでダウンロードした **In-App Purchase Key** ファイルを <img src="/assets/shared/img/88cdfff-download_inapp_file.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Adapty ダッシュボードの **Private key (.p8 file)** フィールドにアップロードします。 <img src="/assets/shared/img/253b840-in-app_file_upload.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## ステップ 4. トライアルと特別オファー向け – プロモーションオファーを設定する \{#step-4-for-trials-and-special-offers--set-up-promotional-offers\} :::important このステップは、アプリに[トライアルやその他のプロモーションオファー](offers)がある場合に必要です。 ::: 1. [ステップ 2](#step-2-provide-issuer-id-and-key-id) で使用したのと同じキー ID を、**App Store promotional offers** セクションの **Subscription key ID** フィールドにコピーします。 2. [ステップ 3](#step-3-upload-in-app-purchase-key-file) で使用したのと同じ **In-App Purchase Key** ファイルを、**App Store promotional offers** セクションの **Subscription key (.p8 file)** エリアにアップロードします。 <img src="/assets/shared/img/promo-key.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## ステップ 5. App Store 共有シークレットを入力する \{#step-5-enter-app-store-shared-secret\} **App Store shared secret**(App Store Connect Shared Secret とも呼ばれます)は、アプリ内購入とサブスクリプションのレシート検証に使用される 32 文字の16進数文字列です。 1. [App Store Connect](https://appstoreconnect.apple.com/apps) を開きます。アプリを選択し、**General** → **App Information** セクションに進みます。 2. **App-Specific Shared Secret** サブセクションまでスクロールします。 <img src="/assets/shared/img/2bd112a-shared_secret_apple.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> :::info **App-Specific Shared Secret** サブセクションが表示されない場合は、Account Holder または Admin ロールを持っているか確認してください。Admin ロールを持っているにもかかわらず **App-Specific Shared Secret** サブセクションが表示されない場合は、アプリの Account Holder(App Store Connect でアプリケーションを作成した人)に App Store 共有シークレットを生成するよう依頼してください。その後、Admin にもサブセクションが表示されるようになります。 ::: 3. **Manage** ボタンをクリックします。 <img src="/assets/shared/img/2d8b4c0-shared_secret_apple_copy.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. 開いた **App-Specific Shared Secret** ウィンドウで、**Shared Secret** をコピーします。共有シークレットが表示されていない場合は、まず **Manage** または **Generate** のどちらか利用可能なボタンをクリックしてから、**Shared Secret** をコピーします。 5. コピーした **Shared Secret** を、Adapty ダッシュボードの **App Store shared secret** フィールドに貼り付けます。 <img src="/assets/shared/img/4f9624d-shared_secret.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 6. Adapty ダッシュボードの **Save** ボタンをクリックして変更を確定します。 ## ステップ 6. App Store Connect API キーを追加する \{#step-6-add-app-store-connect-api-key\} App Store Connect API キーを生成して Adapty に追加すると、[Adapty ダッシュボードから App Store のプロダクトを管理](create-product#create-product-and-push-to-store)できるようになります。 1. App Store Connect で [**Users and Access > Integrations > Team keys**](https://appstoreconnect.apple.com/access/integrations/api) に移動し、**+** をクリックします。 <img src="/assets/shared/img/app-store-connect-api.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. **Generate API key** ウィンドウで、キーの名前を入力し、**Admin** アクセス権を付与します。 <img src="/assets/shared/img/generate-api-key.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. キーの横にある **Download** をクリックします。ダウンロードは一度しか行えません。 <img src="/assets/shared/img/download-api-key.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. Adapty ダッシュボードで [**App settings > iOS SDK**](https://app.adapty.io/settings/ios-sdk) に移動し、**Connect API key** をクリックします。 <img src="/assets/shared/img/connect-api-key.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. ウィンドウの各フィールドに入力します: - **Issuer ID**:[**Users and Access > Integrations > Team keys**](https://appstoreconnect.apple.com/access/integrations/api) からコピーします。**API keys** テーブルの上に表示されています。 <img src="/assets/shared/img/issuer-id.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> - **Key ID**:[**Users and Access > Integrations > Team keys**](https://appstoreconnect.apple.com/access/integrations/api) からコピーします。**API keys** テーブルのキーの横に表示されています。 <img src="/assets/shared/img/key-id.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> - **API key**:App Store Connect からダウンロードした API キーファイルをアップロードします。 <img src="/assets/shared/img/app-store-connect-key.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '500px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 6. **Connect** をクリックします。 **次のステップ** - [App Store サーバー通知を有効にする](enable-app-store-server-notifications) --- # File: enable-app-store-server-notifications --- --- title: "App Store サーバー通知を有効にする" description: "App Store サーバー通知を有効にして、サブスクリプションイベントをリアルタイムで追跡します。" --- App Store サーバー通知を設定することは、データの正確性を確保するうえで非常に重要です。これにより、払い戻しやその他のイベントに関する情報を含む更新を App Store からリアルタイムで受け取ることができます。 :::important App Store Server Notifications V2 を完全にサポートするには、Adapty iOS SDK 2.10.0 以降が必要です。 ::: 1. Adapty ダッシュボードで **URL for App Store server notification** をコピーします。 <img src="/assets/shared/img/2901185-app_server_notifications.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. [App Store Connect](https://appstoreconnect.apple.com/apps) を開きます。アプリを選択し、**General** → **App Information** セクションの **App Store Server Notifications** サブセクションに進みます。 3. コピーした **URL for App Store server notification** を **Production Server URL** と **Sandbox Server URL** フィールドに貼り付けます。 <img src="/assets/shared/img/86fb3d2-app_server_notifications_apple.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## 生イベントの転送 \{#raw-events-forwarding\} Apple から生の S2S イベントを引き続き受け取りたい場合もあるかもしれません。Adapty を使用しながらこれを続けるには、**URL for forwarding raw Apple events** フィールドにエンドポイントを追加するだけで、Apple からの生イベントをそのままの形式で転送します。 <img src="/assets/shared/img/e9f4bba-CleanShot_2021-03-16_at_19.30.272x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> **次のステップ** 以下のプラットフォーム向けに Adapty SDK を設定します: - [iOS](sdk-installation-ios) - [React Native](sdk-installation-reactnative) - [Flutter](sdk-installation-flutter) - [Kotlin Multiplatform](sdk-installation-kotlin-multiplatform) - [Unity](sdk-installation-unity) --- # File: troubleshoot-app-store-integration --- --- title: "App Store インテグレーションのトラブルシューティング" description: "保留中の契約、サーバー通知の遅延、価格の不一致など、Apple App Store のセットアップに関する一般的な問題を解決します。" --- この記事では、App Store インテグレーションに関する一般的な問題を説明します。各セクションでは、症状・根本原因・解決方法を紹介します。 ## プロダクトが表示されない \{#products-dont-appear\} 以下の 2 つの症状は、同じ根本原因を示しています。 - App Store Connect の API キーは正しく設定されているのに、Adapty がプロダクトをまったく取得できない。 - App Store Connect にプロダクトが存在するのに Adapty に表示されない、または期待より少ない数しか表示されない。購入を試みると SDK が「Product Id not found」と報告する。 最も一般的な根本原因は **Apple の契約が未署名** であることです — 有料契約・税務フォーム・銀行口座情報が保留中または未署名の状態になっています。契約が保留中の場合、App Store Connect API はプロダクト関連のエンドポイントに対してサイレントに 403 を返します。Adapty には明確なエラーが表示されず、プロダクトはサイレントに除外されます。 **App Store Connect → Agreements, Tax, and Banking** にアクセスして、保留中の契約にすべて署名してください。その後、Adapty の **App settings → iOS SDK** で再同期を行ってください。 ## App Store Server Notifications が「Delayed」と表示される \{#app-store-server-notifications-show-delayed\} App Store Connect で、App Store Server Notifications のステータスが **Delayed** と表示されることがあります。これは、Apple がサブスクリプションイベントの通知(更新・キャンセル・請求エラーなど)の送信を遅延させており、キューに入れられた通知が遅れて届くことを意味します。 インストール統計には影響しません。Adapty はインストールをサーバー側の通知からではなく、アプリの初回起動時にカウントします。 更新やキャンセルのデータが遅れている場合、Delayed ステータスが最も可能性の高い原因です。Apple がバックログを処理するにつれて、通常は自動的に解消されます。 ## Adapty の価格が App Store と一致しない \{#prices-in-adapty-dont-match-app-store\} Adapty のプロダクト編集ページの **price** フィールドは、プロダクトの追加方法によって動作が異なります。 Adapty でプロダクトを作成してダッシュボードからストアにプッシュする場合、この価格が初期ストア価格として使用されます。 すでにストアに存在するプロダクトを追加する場合、この価格はプレースホルダーです。Adapty のアナリティクス・インテグレーション・SDK は、App Store から取得した実際の価格を使用します。App Store の価格変更はプレースホルダーに同期されません。また、現時点ではダッシュボードからプレースホルダーを編集することもできません。 ## CSV の価格エクスポートが空になる \{#csv-price-export-is-empty\} CSV の価格エクスポートに列ヘッダーしか含まれていない場合、App Store Connect の API キーが完全に設定されていません。[ステップ 6 — App Store Connect API キーを追加する](app-store-connection-configuration#step-6-add-app-store-connect-api-key) を参照してください。 ## 新しいプロダクトを App Store にプッシュできない \{#cant-push-new-products-to-app-store\} Adapty はダッシュボードでプロダクトを作成したときに、App Store Connect にプッシュできます。App Store インテグレーションが完全に設定されていない場合、プッシュオプションはブロックされます。以下の 2 つの設定が必要です。 - **Apple app ID**: [ステップ 1 — Bundle ID と Apple app ID を入力する](app-store-connection-configuration#step-1-provide-bundle-id-and-apple-app-id) で設定してください。 - **App Store Connect API key**: [ステップ 6 — App Store Connect API キーを追加する](app-store-connection-configuration#step-6-add-app-store-connect-api-key) で設定してください。 --- # File: enabling-of-devepoler-api --- --- title: "Google Play ConsoleでDeveloper APIを有効にする" description: "AdaptyのDeveloper APIを有効にして、アプリのサブスクリプション管理を自動化・効率化しましょう。" --- <div style={{ maxWidth: '560px', margin: '0 auto 2rem', position: 'relative', aspectRatio: '16/9', width: '100%' }}> <iframe style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%' }} src="https://www.youtube.com/embed/7dN50n5bcLc?si=c2znttIb--4VcrRO" title="YouTube video player" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerPolicy="strict-origin-when-cross-origin" allowFullScreen /> </div> アプリがPlay Storeで配信されている場合、Developer APIを有効にすることはAdaptyとの連携に欠かせません。このステップにより、アプリとAdatyプラットフォーム間のシームレスな通信が確立され、自動化処理やリアルタイムのデータ分析によってサブスクリプションモデルの最適化が可能になります。以下のAPIを有効にする必要があります: - [Google Play Android Developer API](https://console.cloud.google.com/apis/library/androidpublisher.googleapis.com) - [Google Play Developer Reporting API](https://console.cloud.google.com/apis/library/playdeveloperreporting.googleapis.com) - [Cloud Pub/Sub API](https://console.cloud.google.com/marketplace/product/google/pubsub.googleapis.com) アプリをPlay Store経由で配信していない場合は、このステップをスキップできます。Play Storeで販売している場合は、今すぐ行わなくても構いませんが、Adaptyの基本機能には必須です。オンボーディング完了後、**App settings** セクションでアプリストアの設定を行えます。 Google Play ConsoleでDeveloper APIを有効にする手順は以下の通りです: 1. [Google Cloud Console](https://console.cloud.google.com/)を開きます。 2. Google Cloudウィンドウの左上で、使用するプロジェクトを選択するか、新しいプロジェクトを作成します。サービスアカウントのキーファイルをAdaptyにアップロードするまで、同じGoogle Cloudプロジェクトを使用し続けてください。 <img src="/assets/shared/img/fd66a11-google_cloud_project.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. [**Google Play Android Developer API**](https://console.cloud.google.com/apis/library/androidpublisher.googleapis.com) ページを開きます。 <img src="/assets/shared/img/f754f72-google_play_api.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **Enable** ボタンをクリックし、ステータスが **Enabled** になるまで待ちます。これでGoogle Android Developer APIが有効になります。 <img src="/assets/shared/img/d47ed14-google_play_api_create_credentials.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. [**Google Play Developer Reporting API**](https://console.cloud.google.com/apis/library/playdeveloperreporting.googleapis.com) ページを開きます。 <img src="/assets/shared/img/966cf73-Google_play_developer_reporting_api.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 6. **Enable** ボタンをクリックし、ステータスが **Enabled** になるまで待ちます。 <img src="/assets/shared/img/e776d77-Google_play_developer_reporting_api_enabled.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 7. [**Cloud Pub/Sub API**](https://console.cloud.google.com/marketplace/product/google/pubsub.googleapis.com) ページを開きます。 <img src="/assets/shared/img/b13f609-enable_Cloud_Pub_Sub_API.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 8. **Enable** ボタンをクリックし、ステータスが **Enabled** になるまで待ちます。 <img src="/assets/shared/img/3f45602-Cloud_Pub_Sub_API_enabled.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Developer APIが有効になりました。 Google Cloud Consoleの [**APIs & Services**](https://console.cloud.google.com/apis/dashboard) ページで確認できます。ページを下にスクロールし、ページ下部の表に以下の3つのAPIがすべて含まれていることを確認してください: - Google Play Android Developer API - Google Play Developer Reporting API - Cloud Pub/Sub API <img src="/assets/shared/img/b81d174-google_enabled_api.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> **次のステップ** - [Google Cloud Consoleでサービスアカウントを作成する](create-service-account) --- # File: create-service-account --- --- title: "Google Cloud ConsoleでServiceアカウントを作成する" description: "Adaptyで安全なAPIアクセスのためのサービスアカウントの作成方法を学びましょう。" --- Adaptyがデータアクセスを自動化するには、Google Play Consoleにサービスアカウントが必要です。 1. Google Cloud Consoleの[**IAM & Admin** -> **Service accounts**](https://console.cloud.google.com/iam-admin/serviceaccounts)セクションを開きます。正しいプロジェクトを使用していることを確認してください。 <img src="/assets/shared/img/17bbf45-google_cloud_create_service_account.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. **Service accounts**ウィンドウで、**Create service account**ボタンをクリックします。 <img src="/assets/shared/img/b93eec1-service_account_details.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. **Create service account**ウィンドウの**Service account details**サブセクションで、任意の**Service Account Name**を入力します。このアカウントの目的を明示するために、名前に「Adapty」を含めることをおすすめします。**Service account ID**は自動的に作成されます。 4. サービスアカウントのメールアドレスをコピーして、後で使用できるように保存しておきます。 5. **Create and continue**ボタンをクリックします。 <img src="/assets/shared/img/e69d713-grant_access_to_project.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 6. **Grant this service account access to project**サブセクションの**Select a role**ドロップダウンリストで、**Pub/Sub -> Pub/Sub Admin**を選択します。このロールは、リアルタイム開発者通知を有効にするために必要です。 <img src="/assets/shared/img/976299c-service_account_role.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 7. **Add another role**ボタンをクリックします。 8. 新しい**Role**ドロップダウンリストで、**Monitoring -> Monitoring Viewer**を選択します。このロールは、通知キューの監視を許可するために必要です。 9. **Continue**ボタンをクリックします。 <img src="/assets/shared/img/ffe8d82-grant_user_access.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 10. 変更を加えずに**Done**ボタンをクリックします。**Service accounts**ウィンドウが開きます。 **次のステップ** - [Google Play Consoleでサービスアカウントに権限を付与する](grant-permissions-to-service-account) --- # File: grant-permissions-to-service-account --- --- title: "Google Play ConsoleでサービスアカウントにGoogle Play Consoleを付与する" description: "安全で効率的なAPIアクセスのため、サービスアカウントに権限を付与します。" --- Adaptyがサブスクリプションの管理と購入の検証に使用するサービスアカウントに、必要な権限を付与します。 1. Google Play Consoleの[**Users and permissions**](https://play.google.com/console/u/0/developers/8970033217728091060/users-and-permissions)ページを開き、**Invite new users**ボタンをクリックします。 <img src="/assets/shared/img/7b0e614-users_and_permissions.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. **Invite user**ページで、作成したサービスアカウントのメールアドレスを入力します。 <img src="/assets/shared/img/3afd002-invite_user.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. **Account permissions**タブに切り替えます。 <img src="/assets/shared/img/4e2717b-account_permissions.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. 以下の権限を選択します: - View app information and download bulk reports (read-only) - View financial data, orders, and cancellation survey responses - Manage orders and subscriptions - Manage store presence 5. **Invite user**ボタンをクリックします。 6. **Send invite?**ウィンドウで、**Send invite**ボタンをクリックします。サービスアカウントがユーザーリストに表示されます。 **次のステップ** - [Google Play Consoleでサービスアカウントキーファイルを生成する](create-service-account-key-file) --- # File: create-service-account-key-file --- --- title: "Google Play ConsoleでサービスアカウントキーファイルをGoogleする" description: "Adaptyとのシームレスな連携のためのサービスアカウントキーファイルの作成方法を学びましょう。" --- Play StoreのモバイルアプリをAdaptyと連携するには、Google Play Consoleで特別なサービスアカウントキーファイルを生成してAdaptyにアップロードする必要があります。これらのファイルはアプリのセキュリティを強化し、不正アクセスを防ぎます。 :::warning 新しいサービスアカウントが有効になるまで、通常は少なくとも24時間かかります。ただし、[回避策](https://stackoverflow.com/a/60691844)があります。[Google Play Console](https://play.google.com/apps/publish/)でサービスアカウントを作成した後、任意のアプリを開いて **Monetize** -> **Products** -> **Subscriptions/In-app products** に移動します。任意のプロダクトの説明を編集して保存すると、サービスアカウントがすぐに有効化されます。その後、変更を元に戻すことができます。 ::: 1. Google Play Consoleの[**Service accounts**](https://console.cloud.google.com/iam-admin/serviceaccounts)セクションを開きます。正しいプロジェクトが選択されていることを確認してください。 <img src="/assets/shared/img/c3156cb-action_manage_keys.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. 開いたウィンドウで **Add key** をクリックし、ドロップダウンメニューから **Create new key** を選択します。 <img src="/assets/shared/img/44b30ee-create_new_key.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. **Create private key for [Your_project_name]** ウィンドウで **Create** をクリックします。秘密鍵がJSONファイルとしてコンピューターに保存されます。**Private key saved to your computer** ウィンドウに表示されたファイル名を使って確認できます。 <img src="/assets/shared/img/e7b8101-cretae_private_key.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **Create private key for Your_project_name** ウィンドウで **Create** ボタンをクリックします。これにより、秘密鍵がJSONファイルとしてコンピューターに保存されます。必要に応じて、表示された **Private key saved to your computer** ウィンドウのファイル名を使ってファイルを見つけることができます。 <img src="/assets/shared/img/187ddc6-Private_key_saved.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> このファイルは、[Google Play Store連携を設定する](google-play-store-connection-configuration)際に必要になります。 :::warning 新しいサービスアカウントが有効になるまで、通常は少なくとも24時間かかります。ただし、[回避策](https://stackoverflow.com/a/60691844)があります。[Google Play Console](https://play.google.com/apps/publish/)でサービスアカウントを作成した後、任意のアプリを開いて **Monetize** -> **Products** -> **Subscriptions/In-app products** に移動します。任意のプロダクトの説明を編集して保存すると、サービスアカウントがすぐに有効化されます。その後、変更を元に戻すことができます。 ::: **次のステップ** - [Google Play Store連携を設定する](google-play-store-connection-configuration) --- # File: google-play-store-connection-configuration --- --- title: "Google Play Storeとの連携を設定する" description: "AdaptyでGoogle Play Storeの接続を設定し、アプリ内課金をスムーズに処理しましょう。" --- このセクションでは、Google Play経由で販売されているモバイルアプリをAdaptyと連携する手順を説明します。Play StoreのアプリケーションデータをAdapty ダッシュボードに入力する必要があります。この作業は、AdaptyがPlay Storeから購入を検証し、サブスクリプションの更新情報を受け取るために欠かせないステップです。 この設定は初回オンボーディング時に行うか、後からAdapty ダッシュボードの **App Settings** で変更できます。 :::danger 設定の変更は、Adaptyのペイウォールをアプリにリリースするまでのみ許容されます。リリース後に変更すると連携が壊れ、モバイルアプリでペイウォールが表示されなくなります。 ::: ## ステップ1. パッケージ名を入力する \{#step-1-provide-package-name\} パッケージ名は、Google Play StoreにおけるアプリのユニークなIDです。サブスクリプション処理などAdaptyの基本機能に必要です。 1. [Google Play Developer Console](https://play.google.com/console/u/0/developers)を開きます。 2. IDを確認したいアプリを選択します。**Dashboard** 画面が開きます。 <img src="/assets/shared/img/7889edb-package_name.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. アプリケーション名の下にあるプロダクトIDを確認し、コピーします。 4. AdaptyトップメニューからA[**App settings**](https://app.adapty.io/settings/android-sdk)を開きます。 <img src="/assets/shared/img/b00066c-package_name.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. **App settings** 画面の **Android SDK** タブで、コピーした **Package name** を貼り付けます。 ## ステップ2. アカウントキーファイルをアップロードする \{#step-2-upload-the-account-key-file\} 1. [サービスアカウントキーファイルの作成](create-service-account)ステップで作成したサービスアカウントの秘密鍵ファイル(JSON形式)を、**Service account key file** エリアにアップロードします。 <img src="/assets/shared/img/20fdba1-service_key_file.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 変更を確定するために、**Save** ボタンをクリックするのを忘れずに。 **次のステップ** - [Google Play ConsoleでRTDN(リアルタイム デベロッパー通知)を有効にする](enable-real-time-developer-notifications-rtdn) --- # File: enable-real-time-developer-notifications-rtdn --- --- title: "Google Play ConsoleでリアルタイムデベロッパーNotification(RTDN)を有効にする" description: "Google Play ConsoleでリアルタイムデベロッパーNotification(RTDN)を有効にしてAdaptyのデータ精度を維持しましょう。払い戻しやその他の重要なイベントに関する即時更新を受け取るためのRTDNセットアップ方法を学びます" --- リアルタイムデベロッパーNotification(RTDN)を設定することは、データ精度を確保するうえで非常に重要です。これにより、払い戻しやその他のイベントに関する情報を含む、Play Storeからの更新をリアルタイムで受け取れるようになります。 ## 通知を有効にする \{#enable-notifications\} 1. **Google Cloud Pub/Sub** が有効になっていることを確認してください。[こちらのリンク](https://console.cloud.google.com/flows/enableapi?apiid=pubsub)を開き、アプリのプロジェクトを選択します。**Google Cloud Pub/Sub** をまだ有効にしていない場合は、ここで有効にする必要があります。 <img src="/assets/shared/img/pubsub.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Adaptyのトップメニューから [**App settings > Android SDK**](https://app.adapty.io/settings/android-sdk) に移動し、**Google Play RTDN topic name** タイトルの横にある **Enable Pub/Sub API** フィールドの内容をコピーします。 <img src="/assets/shared/img/a72ff2d-copy_topic.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> <p> </p> :::note **Enable Pub/Sub API** フィールドの内容が正しくない形式の場合(正しい形式は `projects/...` で始まります)、[Enable Pub/Sub APIフィールドの形式を修正する](enable-real-time-developer-notifications-rtdn#fixing-incorrect-format-in-enable-pubsub-api-field) セクションを参照してください。 ::: 3. [Google Play Console](https://play.google.com/console/) を開き、アプリを選択して、**Monetize with Play** -> **Monetization setup** に進みます。**Google Play Billing** セクションで、**Enable real-time notifications** チェックボックスをオンにします。 4. Adaptyの **App Settings** でコピーした **Enable Pub/Sub API** フィールドの内容を、**Topic name** フィールドに貼り付けます。 5. Google Play Consoleで **Save changes** をクリックします。 <img src="/assets/shared/img/e55ba0e-paste_topic_name.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## 通知をテストする \{#test-notifications\} リアルタイムデベロッパーNotificationへの登録が成功したかどうかを確認するには: 1. Google Play Consoleの設定で変更を保存します。 2. Google Play Consoleの **Topic name** の下にある **Send test notification** をクリックします。 <img src="/assets/shared/img/rtdn-test.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. AdaptyのメニューにあるトップメニューからAdaptyの [**App settings > Android SDK**](https://app.adapty.io/settings/android-sdk) に移動します。テスト通知が送信されると、トピック名の上にそのステータスが表示されます。 <img src="/assets/shared/img/rtdn-adapty-test.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Enable Pub/Sub APIフィールドの形式を修正する \{#fixing-incorrect-format-in-enable-pubsub-api-field\} **Enable Pub/Sub API** フィールドの内容が誤った形式の場合(正しい形式は `projects/...` で始まります)、以下の手順に従って問題を解決してください。 ### 1. APIの有効化と権限を確認する \{#1-verify-api-enablement-and-permissions\} 必要なAPIがすべて有効になっており、サービスアカウントに正しく権限が付与されていることを慎重に確認してください。これらの手順をすでに完了している場合でも、サブステップが抜けていないことを確かめるために再度確認することが重要です。以下のセクションの手順を繰り返してください: 1. [Google Play ConsoleでデベロッパーAPIを有効にする](enabling-of-devepoler-api) 2. [Google Cloud Consoleでサービスアカウントを作成する](create-service-account) 3. [Google Play Consoleでサービスアカウントに権限を付与する](grant-permissions-to-service-account) 4. [Google Play Consoleでサービスアカウントのキーファイルを生成する](create-service-account-key-file) 5. [Google Play Storeインテグレーションを設定する](google-play-store-connection-configuration) ### 2. ドメインポリシーを調整する \{#2-adjust-domain-policies\} **Domain restricted contacts** および **Domain restricted sharing** ポリシーを変更します: 1. [Google Cloud Console](https://console.cloud.google.com/) を開き、アプリを管理するためのサービスアカウントを作成したプロジェクトを選択します。 2. **Quick Access** セクションで、**IAM & Admin** を選択します。 <img src="/assets/shared/img/google-cloud-IAM-and-Admin.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. 左ペインで **Organization Policies** を選択します。 4. **Domain restricted contacts** ポリシーを見つけます。 <img src="/assets/shared/img/google-cloud-policy-action.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. **Actions** 列の省略記号ボタンをクリックし、**Edit policy** を選択します。 6. ポリシー編集ウィンドウで: 1. **Policy source** の下で、**Override parent's policy** ラジオボタンを選択します。 2. **Policy enforcement** の下で、**Replace** ラジオボタンを選択します。 3. **Rules** の下で、**ADD A RULE** ボタンをクリックします。 <img src="/assets/shared/img/google-cloud-edit-policy.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **New rule** -> **Policy values** の下で、**Allow All** を選択します。 <img src="/assets/shared/img/google-cloud-allow-all-policy.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. **SET POLICY** をクリックします。 7. **Domain restricted sharing** ポリシーについても、手順4〜6を繰り返します。 最後に、**Google Play RTDN topic name** タイトルの横にある **Enable Pub/Sub API** フィールドの内容を再作成します。フィールドは正しい形式になります。 リアルタイムデベロッパーNotification(RTDN)の有効化に成功したら、更新したポリシーの **Policy source** を **Inherit parent's policy** に戻すことを忘れずに行ってください。 ## 生イベントの転送 \{#raw-events-forwarding\} 場合によっては、Googleからの生のS2Sイベントを引き続き受け取りたいこともあるでしょう。Adaptyを使用しながらそれらを受け取り続けるには、**URL for forwarding raw Google events** フィールドにエンドポイントを追加するだけで、Googleからの生イベントをそのまま送信します。 <img src="/assets/shared/img/e388892-001774-September-22-GhkjOFbT.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> --- **次のステップ** 以下のプラットフォーム向けにAdapty SDKを設定します: - [Android](sdk-installation-android) - [React Native](sdk-installation-reactnative) - [Flutter](sdk-installation-flutter) - [Kotlin Multiplatform](sdk-installation-kotlin-multiplatform) - [Unity](sdk-installation-unity) --- # File: stripe --- --- title: "Stripeとの初期連携" description: "StripeをAdaptyと連携して、サブスクリプション決済をシームレスに処理しましょう。" --- Adaptyは、[Stripe](https://stripe.com/)を通じたウェブ決済・サブスクリプションを追跡することで、web2appのサブスクリプションフローをサポートしています。 この連携は、ウェブ起点の購入(Stripe Checkout、ホスト型決済ページ、またはカスタムウェブフロー)に対応しており、モバイルアプリのアクセスやアナリティクスと同期します。 以下のようなシナリオで役立ちます: - ウェブで購入した後にアプリをインストールしてログインしたユーザーに、有料機能へのアクセスを自動的に付与する - コホート、予測、その他のアナリティクスツールを含む、すべてのサブスクリプションアナリティクスをAdapty ダッシュボード一か所で管理する ウェブ購入はアプリにとってますます一般的になりつつありますが、Apple App Storeがアプリ内課金以外のシステムを許可しているのはアメリカ国内のデジタルコンテンツに限られています。他の国でウェブサブスクリプションをアプリ内で宣伝しないようにしてください。違反するとアプリが審査で却下されたり、BANされる可能性があります。 以下の手順でStripe連携を設定します。 :::important この連携は、Stripeのウェブ購入の追跡と同期を目的としています。アプリからウェブチェックアウトにユーザーを誘導する場合は、[ウェブペイウォール](web-paywall)をご覧ください。 ::: ## 1\. StripeをAdaptyに接続する \{#1-connect-stripe-to-adapty\} この連携は主に、AdaptyがWebhook経由でStripeからサブスクリプションデータを取得することで機能します。そのため、APIキーを提供し、AdaptyのWebhook URLをStripeに設定することで、AdaptyアカウントとStripeアカウントを接続する必要があります。Webhookのセットアップをできるだけラクにするために、StripeにAdatyアプリをインストールしてください: :::note 以下の手順はStripeのProductionモードとTestモードで共通ですが、それぞれ異なるAPIキーを使用する必要があります。 ::: 0. テストモードとライブモードのどちらでStripeを接続するかを決めます。最初にテストモードで設定する場合は、後でライブモードでも同じ手順を繰り返す必要があります。 1. [Stripe App Marketplace](https://marketplace.stripe.com/apps/adapty)にアクセスしてAdatyアプリをインストールします。サンドボックスモードではアプリのインストールに対応していないため、本番環境またはテストモードでのみ実行できます。 <img src="/assets/shared/img/stripe1.png"/> 2. アプリに必要な権限を付与します。これにより、Adaptyがサブスクリプションデータと履歴にアクセスできるようになります。その後、**Continue to app settings** をクリックして続行します。 権限ポップアップの下部で、ライブモードまたはテストモードのどちらでアプリをインストールするかを選択できます。 <img src="/assets/shared/img/stripe2.png"/> 3. ポップアップで新しい制限付きキーを生成します。メール、Touch ID、またはセキュリティキーを使って本人確認が必要です。キーを生成した後は再度確認できないため、パスワードマネージャーや秘密管理ストアに安全に保存してください。 <img src="/assets/shared/img/stripe4.png"/> 4. ポップアップから生成されたキーをコピーし、Adaptyの[App Settings → Stripe](https://app.adapty.io/settings/stripe)に移動します。モードに合わせて **Stripe App Restricted API Key** セクションにキーを貼り付けます。テストモードとライブモードでは異なるキーを生成する必要があることに注意してください。 <img src="/assets/shared/img/Stripe3.png"/> 以上で完了です!次は、Stripeでプロダクトを作成してAdaptyに追加しましょう。 <Details> <summary>非推奨のインストールフロー</summary> 1. Stripeの[Developers → API Keys](https://dashboard.stripe.com/apikeys)に移動します: <img src="/assets/shared/img/6549602-CleanShot_2023-12-06_at_17.29.122x.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. **Secret key** タイトルの横にある **Reveal live (test) key button** をクリックしてキーをコピーし、Adaptyの[App Settings → Stripe](https://app.adapty.io/settings/stripe)に移動します。ここにキーを貼り付けます: <img src="/assets/shared/img/2989508-CleanShot_2023-12-07_at_14.59.122x.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. 次に、AdaptyのStripe設定ページ下部からWebhook URLをコピーします。Stripeの[**Developers** → **Webhooks**](https://dashboard.stripe.com/webhooks)に移動し、**Add endpoint** ボタンをクリックします: <img src="/assets/shared/img/e7149f5-CleanShot_2023-12-07_at_17.31.392x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. AdaptyのWebhook URLを **Endpoint URL** フィールドに貼り付けます。次にWebhookの **Version** フィールドで **Latest API version** を選択します。その後、以下のイベントを選択します: - charge.refunded - customer.subscription.created - customer.subscription.deleted - customer.subscription.paused - customer.subscription.resumed - customer.subscription.updated - invoice.created - invoice.updated - payment_intent.succeeded <img src="/assets/shared/img/cbc5404-CleanShot_2023-12-07_at_17.36.232x.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. "Add endpoint" を押し、"Signing secret" の下にある "Reveal" を押します。これはAdapty側でWebhookデータを復号するために使用されるキーです。表示後にコピーしてください: <img src="/assets/shared/img/0460cbb-CleanShot_2023-12-07_at_17.52.582x.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 6. 最後に、このキーをAdaptyの App Settings → Stripe の "Stripe Webhook Secret" に貼り付けます: <img src="/assets/shared/img/055db20-CleanShot_2023-12-07_at_14.56.212x.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> </Details> ## 2\. Stripeでプロダクトを作成する \{#2-create-products-on-stripe\} :::note テストモードで設定している場合は、この手順を続ける前にStripeもTestモードに切り替えてください。 ::: Stripeの[Product catalog](https://dashboard.stripe.com/products?active=true)にアクセスし、販売したいプロダクトと料金プランを作成します。Stripeでは1つのプロダクトに複数の料金プランを設定できるため、プロダクトを追加作成しなくてもオファーを柔軟に調整できます。 <img src="/assets/shared/img/b202e2e-CleanShot_2023-12-06_at_15.06.262x.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> :::warning 現時点でAdaptyがサポートしているのは、**Flat rate**(例:$9.99/月)または **Package pricing**(例:$9.99/10ユニット)のみです。これらはアプリストアと同様の動作をします。**Tiered pricing**、**Usage-based fee**、**Customer chooses price** のオプションはサポートされていません。 ::: ## 3\. StripeプロダクトをAdatyに追加する \{#3-add-stripe-products-to-adapty\} :::warning プロダクトは必須です!Adapty ダッシュボードでStripeプロダクトを作成してください。Adaptyはこれらのプロダクトに紐づいたトランザクションのイベントのみ追跡します。このステップをスキップすると、トランザクションイベントが作成されません。 ::: AdaptyではStripeをApp StoreやGoogle Playと同様に扱います。つまり、デジタルプロダクトを販売する別のストアとして設定します。設定方法も同様で、StripeプロダクトのIDを(`product_id`と`price_id`を)AdaptyのProductsセクションに追加するだけです: <img src="/assets/shared/img/stripe-add-product.webp" style={{ border: 'none', /* border width and color */ width: '500px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> StripeのプロダクトIDは `prod_...`、価格IDは `price_...` の形式になっています。Stripeの[Product Catalog](https://dashboard.stripe.com/products?active=true)でプロダクトを開けば、簡単に確認できます: <img src="/assets/shared/img/14a72d7-CleanShot_2023-12-06_at_17.32.512x.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 必要なプロダクトをすべて追加したら、次はStripeに購入者のユーザーIDを伝える設定をしましょう。これにより、AdaptyがStripeからの情報を正しく取り込めるようになります。 ## 4\. ウェブ購入にユーザーIDを付加する \{#4-enrich-purchases-made-on-the-web-with-your-user-id\} Adaptyは、アクセスレベルの付与・更新において、Stripeからのwebhookを唯一の情報源として利用しています。ただし、この連携を正しく機能させるためには、Stripe連携時にお客様側から追加情報を提供する必要があります。 プラットフォーム(ウェブまたはモバイル)を横断して一貫したアクセスレベルを維持するには、AdaptyがWebhookから認識できる単一のユーザーIDに依存する必要があります。これはユーザーのメールアドレス、電話番号、または利用している認証システムのその他のIDが使えます。 ユーザーを識別するためにどのIDを使用するかを決めてください。次に、Stripeで決済を初期化しているコード部分にアクセスし、そのユーザーIDを[Stripe Subscription](https://docs.stripe.com/api/subscriptions/object#subscription_object-metadata)(`sub_...`)または[Checkout Session](https://docs.stripe.com/api/checkout/sessions/create#create_checkout_session-metadata)オブジェクト(`ses_...`)の`metadata`に`customer_user_id`として以下のように追加してください: ```json showLineNumbers title="Stripe Metadata contents" {'customer_user_id': "YOUR_USER_ID"} ``` コードに必要な変更はこれだけです。これにより、AdaptyはStripeから受け取ったすべてのWebhookを解析し、この`metadata`を抽出して、サブスクリプションを正しくユーザーに紐付けます。 :::warning ユーザーIDは必須です これがなければ、ユーザーを特定してモバイル側でアクセスレベルを付与する方法がありません。 `metadata`に`customer_user_id`を指定しない場合は、AdaptyがStripeの他の情報からIDを探すよう設定できます:StripeのCustomerオブジェクトの`email`、またはStripeのSessionの`client_reference_id`のいずれかです。 プロファイル作成の挙動の設定方法については[こちら](stripe#profile-creation-behavior)をご覧ください。 ::: :::note StripeのCustomerも必須です Checkout Sessionsを使用している場合は、`customer_creation`を`always`に設定して[Stripe Customerを作成する](https://docs.stripe.com/api/checkout/sessions/create#create_checkout_session-customer_creation)ようにしてください。 ::: ## 5\. モバイルユーザーへのアクセス付与 \{#5-provide-access-to-users-on-the-mobile\} ウェブから来たモバイルユーザーが有料機能にアクセスできるようにするには、前のステップで提供したのと同じ`customer_user_id`を使って`Adapty.activate()`または`Adapty.identify()`を呼び出すだけです(詳細は<InlineTooltip tooltip="ユーザーの識別">[iOS](identifying-users)、[Android](android-identifying-users)、[React Native](react-native-identifying-users)、[Flutter](flutter-identifying-users)、[Unity](unity-identifying-users)</InlineTooltip>をご覧ください)。 ## 6\. 連携をテストする \{#6-test-your-integration\} サンドボックスと本番環境の両方で上記の手順を完了したことを確認してください。StripeのTestモードで行ったトランザクションは、AdaptyではSandboxとして扱われます。 :::info 以上で完了です! ユーザーはウェブで購入を完了し、アプリで有料機能にアクセスできるようになります。また、すべてのサブスクリプションアナリティクスを1か所で確認できます。 ::: ## プロファイル作成の挙動 \{#profile-creation-behavior\} Adaptyは購入をモバイルで利用可能にするために、[顧客プロファイル](profiles-crm)に紐付ける必要があります。そのため、デフォルトではStripeからWebhookを受信した際にプロファイルを作成します。Adaptyで顧客ユーザーIDとして使用するものを選択できます: 1. **デフォルトかつ推奨:** [上記のステップ4](stripe#4-enrich-purchases-made-on-the-web-with-your-user-id)でmetadataに指定した`customer_user_id` 2. StripeのCustomerオブジェクトの`email`([Stripeのドキュメント](https://docs.stripe.com/api/customers/object#customer_object-email)を参照) 3. StripeのSessionオブジェクトの`client_reference_id`([Stripeのドキュメント](https://docs.stripe.com/api/checkout/sessions/create#create_checkout_session-client_reference_id)を参照) 使用するIDは[App Settings → Stripe](https://app.adapty.io/settings/stripe)で設定できます。 :::warning **注意:** 特定のStripeトランザクションに指定したIDが含まれていない場合、プロファイルは一切作成されません。このトランザクションは、何らかのプロファイルに紐付けられるまで匿名のままになります(例えば、後から[S2S validate](api-adapty/operations/validateStripePurchase)を使ってこのトランザクションを手動で通知した場合など)。 アナリティクスには表示されますが、プロファイルのカウントに依存するセクション(LTV、コホート、コンバージョンなど)には反映されず、イベントフィードでも確認できません。 ::: プロファイルをまったく作成しないという4つ目の選択肢もありますが、上記のアナリティクス制限があるため推奨しません。 ## 現在の制限事項 \{#current-limitations\} ### アップグレード、ダウングレード、日割り計算 \{#upgrading-downgrading-and-proration\} サブスクリプションのアップグレードやダウングレードを行うと、日割り計算による請求が発生することがあります。Adaptyはこれらの請求を収益計算に含めません。Stripeダッシュボードからこれらのオプションを手動で無効にするか、Stripe APIで`proration_behaviour`属性の値を`none`に設定して無効にすることをお勧めします。 ### キャンセル \{#cancellations\} Stripeにはサブスクリプションのキャンセルオプションが2つあります: 1. 即時キャンセル:日割り計算の有無にかかわらず、サブスクリプションが即座にキャンセルされます 2. 期間終了時のキャンセル:現在の請求期間の終了時にキャンセルされます(アプリストアのアプリ内サブスクリプションと同様)。 Adaptyはどちらのオプションにも対応していますが、即時キャンセルの場合、収益計算で日割り計算オプションは考慮されません。 ### 請求の問題とグレース期間 \{#billing-issues-and-grace-period\} 顧客の支払いに問題が発生すると、Adaptyは請求問題イベントを生成し、アクセスが取り消されます。Stripeのグレース期間はまだサポートしていませんが、将来のリリースで対応予定です。 ### 返金 \{#refunds\} Adaptyが追跡するのは全額返金のみです。日割り計算による返金や部分返金は現在サポートしていません。 ### トランザクションIDの一意性 \{#transaction-id-uniqueness\} Adaptyは`store_transaction_id`と`store_original_transaction_id`を使用してプロファイルとトランザクションを照合します。これらはテスト環境と本番環境の間で**一意である必要があります**。 #### なぜ重要なのか \{#why-this-matters\} 同じトランザクションIDが両方の環境に存在すると、Adaptyはそれらを1つのトランザクションとして扱い、以下の問題が発生します: - 本番環境の購入がテスト環境のアクセスレベルとプロダクトIDを引き継ぐ - APIレスポンスでプロダクトIDと環境の情報が誤って表示される - プロファイルの紐付けとサブスクリプションイベントが正しく機能しない #### 一意性を確保する方法 \{#how-to-ensure-uniqueness\} StripeのインボイスIDはテスト環境とライブ環境で重複する可能性があります。環境をまたいだIDの衝突を防ぐには、以下のいずれかの方法を選択してください。 #### オプション1:環境プレフィックス付きのアカウントレベルの採番 \{#option-1-account-level-numbering-with-environment-prefixes\} 各環境に対して個別にプレフィックスを設定します: 1. Stripeダッシュボードでテストモードに切り替えます。 2. [Settings → Billing → Invoices](https://dashboard.stripe.com/settings/account/?support_details=true)に移動します。 3. **Invoice numbering** を **Sequentially across your account** に設定します。 4. **Invoice prefix** を TEST-(またはテスト環境固有の任意のプレフィックス)に設定します。 5. ライブモードに切り替えて、手順2〜4を繰り返します。プレフィックスには LIVE-(またはライブ環境固有の任意のプレフィックス)を使用します。 #### オプション2:顧客レベルの採番 \{#option-2-customer-level-numbering\} [**Stripe settings** -> **Billing** -> **Invoices** タブ](https://dashboard.stripe.com/settings/account/?support_details=true)の **Invoice numbering** を **Sequentially for each customer (customer-level)** に設定します。 上記の設定を行っても、インボイスを削除するとStripeが同じ顧客の新しいインボイスに同じIDを再利用する場合があります。インボイスはできるだけ削除しないようにすることをお勧めします。 ### Stripe CheckoutまたはPayment Linksを使った買い切り購入 \{#one-time-purchases-via-stripe-checkout-or-payment-links\} AdaptyがStripe Checkout(`mode=payment`)またはPayment Linksを通じた買い切り(非サブスクリプション)購入を追跡するのは、Stripeがその購入に対してインボイスを生成した場合のみです。デフォルトでは、Stripeは買い切りのCheckout購入に対してインボイスを作成しません。この場合、`payment_intent.succeeded`はインボイスデータなしで到達するため、Adaptyがトランザクションを記録するには不十分です。 Adaptyで買い切りCheckout購入を追跡するには、セッション作成時に[インボイスの作成を有効にして](https://docs.stripe.com/payments/checkout/receipts?payment-ui=stripe-hosted#paid-invoices-hosted)ください。これにより、Stripeがインボイスを生成し、関連する`invoice.created`および`invoice.updated`イベントを送信します。Adaptyはこれらのイベントを処理してトランザクションを記録します。 ## Stripeデータをさらに活用する \{#get-more-from-your-stripe-data\} Stripeと連携すると、Adaptyはすぐにインサイトを提供できる状態になります。Stripeデータを最大限に活用するには、追加のAdapty連携を設定してStripeのイベントを転送しましょう。これにより、すべてのサブスクリプションアナリティクスをAdapty ダッシュボード一か所に集約できます。 :::tip アナリティクスをさらに強化するために、Stripeのmetadataに`variation_id`を含めると、購入を特定のペイウォールインスタンスに紐付けることができます。これは、特定のペイウォールの表示がコンバージョンにつながったかどうかを追跡したい場合など、自社製ウェブペイウォールの実装時に特に有用です。 `variation_id`は、Stripe Subscription(`sub_...`)とCheckout Session(`ses_...`)オブジェクトのmetadataからのみ読み取られます: ```json showLineNumbers title="Stripe Metadata with variation_id" { 'customer_user_id': "YOUR_USER_ID", 'variation_id': "YOUR_VARIATION_ID" } ``` ::: Stripeイベントの転送・分析に使用できる連携: - [Amplitude](amplitude/) - [Webhook](webhook) - [Firebase](firebase-and-google-analytics) - [Mixpanel](mixpanel) - [Posthog](posthog) ### サポートしているStripeイベント \{#supported-stripe-events\} Adaptyは以下のStripeイベントをサポートしています: - charge.refunded - customer.subscription.created - customer.subscription.deleted - customer.subscription.paused - customer.subscription.resumed - customer.subscription.updated - invoice.created - invoice.updated - payment_intent.succeeded --- # File: paddle --- --- title: "Paddleとの初期連携" description: "AdaptyとPaddleを連携して、サブスクリプション決済をシームレスに処理しましょう。" --- Adaptyは、[Paddle](https://www.paddle.com/)を通じて行われたウェブ決済とサブスクリプションを追跡することで、web2appのサブスクリプションフローをサポートしています。 この連携では、ウェブ経由の購入を管理し、アプリ内課金と並行して、モバイルアプリへのアクセスと分析データを同期します。 以下のようなケースで役立ちます: - アプリ内課金とウェブサイト購入の両方のサブスクリプションデータを一元管理する - ウェブサイトで購入したユーザーに、モバイルアプリの有料機能へのアクセスを付与する - すべての販売チャネルの分析データとサブスクリプションデータを1つのダッシュボードで確認する :::note Appleは現在、米国のApp Storeアプリに外部決済システムへのリンクを含めることを許可していますが、アプリ内購入と外部オプションの両方を提供する必要がある場合もあります。お使いの地域とアプリカテゴリに適用される最新のApp Storeガイドラインをご確認ください。 ::: :::note この連携は、PaddleのウェブからのアプリへのAの追跡と同期に焦点を当てています。ユーザーをアプリからウェブチェックアウトに誘導する必要がある場合は、Adaptyの[ウェブペイウォール](web-paywall)をご利用ください。 ::: Paddle連携を設定するには、以下の手順に従ってください: ## 1. PaddleをAdapyに接続する \{#1-connect-paddle-to-adapty\} この連携では、ウェブフックを使用してPaddleからAdapyにサブスクリプションデータを送信します。AdapyとPaddleアカウントを接続するには、以下が必要です: 1. Paddle APIキーを提供する 2. AdapyのウェブフックURLをPaddleに追加する :::note 以下の手順は、本番環境とテスト環境の両方に適用されます。同時に両方を設定できます。記載のリンクは本番環境用です。テスト環境のリンクを取得するには、各URLの先頭に`sandbox-`を追加してください。例えば、`https://vendors.paddle.com/authentication-v2`の代わりに`https://sandbox-vendors.paddle.com/authentication-v2`を使用します。 ::: ### 1.1. Paddle APIキーの取得と追加 \{#11-get-and-add-paddle-api-keys\} 1. Paddleで[Developer Tools → Authentication](https://vendors.paddle.com/authentication-v2)に移動し、**New API key**をクリックします。 <img src="/assets/shared/img/paddle-new-key.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. キーに名前を付け、有効期限を設定します。AdapyでAPIキーを機能させるには、すべてのエンティティに対して**Read**権限を付与する必要があります。**Save**をクリックします。 <img src="/assets/shared/img/paddle-key.webp" style={{ border: 'none', /* border width and color */ width: '300px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. **Copy key**をクリックします。 <img src="/assets/shared/img/copy-paddle-key.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. Adaptyで[App Settings → Paddle](https://app.adapty.io/settings/paddle)に移動し、**Paddle API key**セクションにキーを貼り付けます。 :::warning Paddle APIキーに有効期限を設定した場合、有効期限が切れる前に手動で新しいキーを生成し、Adaptyで更新する必要があります。キーが期限切れになると、警告なしに連携が停止し、ユーザーが購入できなくなります。 ::: <img src="/assets/shared/img/paddle-api-keys-adapty.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### 1.2. Adaptyに送信するイベントの追加 \{#12-add-events-that-will-be-sent-to-adapty\} 1. AdapyのPaddleページから**Webhook URL**をコピーします。 2. Paddleで[**Developer Tools → Notifications**](https://vendors.paddle.com/notifications-v2)に移動し、**New destination**をクリックしてウェブフックを追加します。 <img src="/assets/shared/img/paddle-webhook.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. ウェブフックにわかりやすい名前を付けます。後で簡単に見つけられるよう、名前に「Adapty」を含めることをお勧めします。 4. AdapyからコピーしたWebhook URLを**URL**フィールドに貼り付けます。正しい環境のウェブフックを使用していることを確認してください。 5. **Notification type**を**Webhook**に設定します。 <img src="/assets/shared/img/paddle-create-webhook.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 6. 以下のイベントを選択します: - `subscription.created` - `subscription.updated` - `transaction.created` - `transaction.updated` - `adjustment.created` - `adjustment.updated` <img src="/assets/shared/img/paddle_events.png" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 7. **Save destination**をクリックしてウェブフックの設定を完了します。 ### 1.3. ウェブフックシークレットキーの取得と追加 \{#13-retrieve-and-add-the-webhook-secret-key\} 1. **Notifications**ウィンドウで、作成したウェブフックの横にある三点ドットをクリックし、**Edit destination**を選択します。 2. **Edit destination**パネルに**Secret key**という新しいフィールドが表示されます。それをコピーします。 <img src="/assets/shared/img/paddle-webhook-secret-key-copy.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. Adaptyで[App Settings → Paddle](https://app.adapty.io/settings/paddle)に移動し、**Notification secret key**フィールドにキーを貼り付けます。このキーはAdapyでウェブフックデータを検証するために使用されます。 <img src="/assets/shared/img/paddle-webhook-secret-key.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### 1.4. PaddleのカスタマーとAdapyのプロファイルを対応付ける \{#14-match-paddle-customers-with-adapty-profiles\} Adaptyは、アプリ内で使用できるよう各購入を[カスタマープロファイル](profiles-crm)に紐付ける必要があります。デフォルトでは、AdapyがPaddleからウェブフックを受信したときにプロファイルが自動的に作成されます。Adaptyの`customer_user_id`として使用する値を選択できます: 1. **デフォルト・推奨:** `custom_data`フィールドで渡す`customer_user_id`([Paddleドキュメント](https://developer.paddle.com/build/transactions/custom-data)参照) 2. PaddleのCustomerオブジェクトの`email`([Paddleドキュメント](https://developer.paddle.com/paddle-js/methods/paddle-checkout-open/#parameters)参照) 3. `ctm-...`形式のPaddle Customer ID([Paddleドキュメント](https://developer.paddle.com/paddle-js/methods/paddle-checkout-open/#parameters)参照) 4. プロファイルを作成しない。カスタマープロファイルをより細かく制御して自分で管理したい場合はこのオプションを選択します。 使用する値は[App Settings → Paddle](https://app.adapty.io/settings/paddle)の**Profile creation behavior**フィールドで設定できます。 <img src="/assets/shared/img/paddle-users.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## 2. AdapyにPaddleプロダクトを追加する \{#2-add-paddle-products-to-adapty\} :::warning PaddleプロダクトをAdapty ダッシュボードに追加するか、既存のプロダクトにPaddleプロダクトIDを追加してください。Adaptyは、これらのプロダクトに紐付いたトランザクションのイベントのみを追跡します。この手順をスキップすると、トランザクションイベントが作成されません。 ::: PaddleはApp StoreやGoogle Playと同様にAdapyで動作します。つまり、デジタルプロダクトを販売するもう一つのプラットフォームです。設定するには、Adaptyの[Products](https://app.adapty.io/products)セクションで、Paddleの関連する`product_id`と`price_id`の値を追加します。 <img src="/assets/shared/img/paddle-create-product.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Paddleでは、プロダクトIDは`pro_...`、価格IDは`pri_...`の形式です。特定のプロダクトを開くと、[Paddleプロダクトカタログ](https://vendors.paddle.com/products-v2)で確認できます: <img src="/assets/shared/img/paddle-product-price.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> プロダクトを追加したら、次のステップはAdapyが購入を正しいユーザーに紐付けられるようにすることです。 ## 3. モバイルでユーザーにアクセスを付与する \{#3-provide-access-to-users-on-the-mobile\} ウェブで購入したユーザーがモバイルでもアクセスできるようにするには、購入時に渡したものと同じ`customer_user_id`を使って`Adapty.activate()`または`Adapty.identify()`を呼び出します。詳細は[ユーザーの識別](identifying-users)をご覧ください。 ## 4. 連携をテストする \{#4-test-your-integration\} すべての設定が完了したら、連携をテストできます。PaddleのTest環境で行われたトランザクションはAdapyに**Test**として表示されます。本番環境のトランザクションは**Production**として表示されます。 連携が完了しました。ユーザーはウェブサイトでサブスクリプションを購入し、モバイルアプリのプレミアム機能に自動的にアクセスできるようになります。また、統合されたAdapy ダッシュボードですべてのサブスクリプション分析を追跡できます。 ## 重要な注意事項 \{#important-considerations\} - Adaptyの分析では、トランザクション金額に税金とPaddle手数料が含まれます。これはPaddleダッシュボードとは異なり、Paddleでは税金と手数料を差し引いた金額が表示されます。そのため、Adaptyに表示される数値はPaddleダッシュボードの数値より高くなります。 - 他のストアとは異なり、Paddleでの返金は特定のトランザクションのみに影響し、サブスクリプションを自動的にキャンセルしません。サブスクリプションは明示的にキャンセルされない限り有効なままです。 - `custom_data`フィールドに`variation_id`を含めることで、購入を特定のペイウォールインスタンスに紐付けることもできます。Adaptyはウェブフックからこのデータを処理し、分析に含めます。 ### 有料トライアル \{#paid-trials\} Paddleで有料トライアルを使用する場合、Adaptyで2つのプロダクトを作成する必要があります: 1. 非サブスクリプションプロダクトを作成し、トライアル期間の料金を請求するPaddle価格に紐付けます。 2. サブスクリプションプロダクト(月次/週次など)を作成し、無料トライアルコンポーネントを持つPaddle価格に紐付けます。 Paddleの観点では、これは1つのプロダクトに2つの価格が含まれる単一のトランザクションです。1つはトライアル料金(例:$0.99)、もう1つは無料トライアル($0.00)の価格です。 Adaptyの観点では、これにより2つの別々のイベントが作成されます:トライアル支払いの非サブスクリプション購入と、サブスクリプションプロダクトのトライアル開始イベントです。 例えば、ユーザーが月額$9.99のサブスクリプションに対して$0.99の有料トライアルを開始すると、Paddleは両方の価格を含む1つのトランザクションを作成しますが、Adaptyはこれを$0.99の非サブスクリプション購入(即時支払い)と$0.00のトライアル開始イベント(将来的に月額$9.99のサブスクリプション)として処理します。 :::note ユーザーが有料トライアルをキャンセルすると、**Trial expired**と**Trial renewal canceled**イベントが発生します。 ::: ## Paddleデータをさらに活用する \{#get-more-from-your-paddle-data\} :::important PaddleイベントをインテグレーションS(integrations)で動作させるには、ユーザーが少なくとも一度App Store / Google Playアカウントでアプリにログインする必要があります。 ::: Paddleとの連携が完了すると、Adaptyはすぐに分析情報を提供できる状態になります。Paddleデータを最大限に活用するには、追加のAdapy連携を設定してPaddleイベントを転送し、すべてのサブスクリプション分析を単一のAdapy ダッシュボードに集約できます。 Paddleイベントの転送と分析に使用できる連携: - [AppsFlyer](appsflyer) - [Webhook](webhook) - [Posthog](posthog) ## 現在の制限事項 \{#current-limitations\} - **キャンセル**: Paddleにはサブスクリプションキャンセルの2つのオプションがあります: 1. 即時キャンセル:サブスクリプションが即座にキャンセルされます。 2. 期間終了時のキャンセル:現在の請求期間が終了した時点でサブスクリプションがキャンセルされます(アプリストアのアプリ内サブスクリプションと同様)。 - **返金**: Adaptyは全額返金と部分返金を追跡します。 - **グレース期間**: デフォルトでは、Paddleは請求の問題に対して30日間の固定グレース期間を適用し、その間サブスクリプションは有効なままです。[グレース期間の長さと期間終了後のアクション(サブスクリプションの一時停止またはキャンセル)はカスタマイズできます](https://developer.paddle.com/build/retain/configure-payment-recovery-dunning#prerequisites)。 **トライアル**: トライアル終了後に支払いの収集が失敗した場合、サブスクリプションのステータスは`past_due`に変わります。本番環境では、PaddleのRetainがダニングウィンドウを適用してサブスクリプションがキャンセルまたは一時停止される前に支払い回収を試みます。サンドボックスではRetainが利用できないため、支払いの再試行は行われず、サブスクリプションは無期限で`past_due`のままになります。 --- **関連情報:** - [PaddleでのPurchaseを検証し、アクセスレベルを取得し、PaddleのトランザクションHistory をサーバーサイドAPIでインポートする](api-adapty/operations/validatePaddlePurchase) --- # File: custom-store --- --- title: "他のストアとの初期連携" description: "App StoreとのAdapty初期連携:クイックガイド" --- Adaptyへようこそ!アプリで最高の成果を達成できるよう、スムーズなスタートをサポートします。 初期連携が必要なのは [App Store](initial_ios)、[Google Play](initial-android)、[Stripe](stripe)、[Paddle](paddle) のみです。Adaptyはこれらのストアでアプリ、プロダクト、オファーを検証するためです。 Adaptyは他のアプリストアとのデータ検証や購入処理は行いません。ただし、他のストアで販売されたプロダクトをAdaptyに登録することで、購入完了後に有料コンテンツへのアクセス付与、アナリティクスへのトランザクション反映、インテグレーション経由での共有が可能です。 <img src="/assets/shared/img/Adapty-Communication-Scheme.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> <p> </p> :::important バックエンドで購入を処理し、[Adaptyサーバーサイドコンフィグ](getting-started-with-server-side-api)を使用してトランザクションをAdaptyに送信してください。Adaptyはトランザクションを受信して初めて、アクセスの付与、トランザクションイベントのトリガー、インテグレーションへの送信、アナリティクスへの反映を行います。 ::: プロダクトをカスタムアプリストア経由で販売するものとしてマークするには、プロダクト作成時にアプリストアを選択します。必要なストアが一覧にない場合は、以下の手順で作成してください。 1. **Products** ページで、カスタムアプリストア経由で販売したいプロダクトを開きます。 2. 販売先のアプリストアを選択します。一覧にない場合は、**Create Custom Store** ボタンをクリックします。 <img src="/assets/shared/img/create_custom-appstore.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. ストアの **Title** と **Store ID** を入力します。 4. **Create store** ボタンをクリックします。 バックエンドが正しく設定されていれば、Adaptyはこのカスタムストアからのプロダクトトランザクションを受信し、アナリティクス、[**Event Feed**](event-feed)、[インテグレーション](https://app.adapty.io/integrations)に反映し、適切にアクセスを付与します。 ## カスタムストアデータをさらに活用する \{#get-more-from-your-custom-store-data\} :::important カスタムストアのイベントをインテグレーションで機能させるには、ユーザーが少なくとも1回はApp Store / Google Playアカウントでアプリにログインしている必要があります。 ::: カスタムストアのインテグレーションをセットアップすると、Adaptyはすぐにインサイトを提供できる状態になります。データを最大限に活用するために、追加のAdaptyインテグレーションを設定してカスタムストアのイベントを転送し、すべてのサブスクリプションアナリティクスを一つのAdapty ダッシュボードに集約できます。 カスタムストアのイベントを転送・分析するために利用できるインテグレーション: - [AppsFlyer](appsflyer) - [Webhook](webhook) - [Posthog](posthog) --- # File: transfer-apps --- --- title: "アプリを別のアカウントに移管する" description: "Adapty でアプリのオーナーを変更する" --- 会社が買収された場合、アプリを売却する場合、または事業体を再編する場合に、アプリを別のオーナーに移管できます。移管プロセスでは、サービスを継続するために Adapty、App Store Connect、Google Play Console での変更を連携して行う必要があります。 ## アプリのオーナーシップを移管する \{#transfer-app-ownership\} ストアでの移管を先に完了してから、Adapty でのアプリ移管を行ってください。この順序により、移管中も購入が正常に機能し続けます。 :::note 移管プロセス中はプロダクトを削除・再作成しないでください。移管が正常に完了したことを確認するまで、プロダクト ID を変更しないでください。 ::: ### App Store(iOS)の移管 \{#app-store-ios-transfer\} :::important App Store Connect の API キー(Issuer ID、Key ID、.p8 ファイル)はアプリ単位ではなくアカウント単位でスコープされています。移管後は、新しいオーナーのアカウントから新しい API キーを生成し、Adapty で更新する必要があります。 アプリ固有の共有シークレットは移管期間中もレシートの検証を継続しますが、移管完了後に新しいオーナーが再生成して Adapty を更新する必要があります。 ::: 1. **新しいオーナー:** アカウントをお持ちでない場合は、[app.adapty.io](https://app.adapty.io) で Adapty アカウントを作成してください。 2. **旧オーナー:** Apple の[移管ガイド](https://developer.apple.com/help/app-store-connect/transfer-an-app/overview-of-app-transfer)に従って、App Store Connect でアプリの移管を開始してください。 3. **新しいオーナー:** App Store Connect で移管を承認してください。 4. **旧オーナー:** Adapty でのアプリ移管を依頼するため、[support@adapty.io](mailto:support@adapty.io) にメールを送ってください。アプリ名と新しいオーナーのメールアドレスを記載してください。 5. **新しいオーナー:** Adapty でアプリを受け取ったら、[App Store 連携ガイド](initial_ios)を参照して、自分のアカウントで必要なすべての認証情報を生成・設定してください。 ### Google Play(Android)の移管 \{#google-play-android-transfer\} 1. **新しいオーナー:** アカウントをお持ちでない場合は、[app.adapty.io](https://app.adapty.io) で Adapty アカウントを作成してください。 2. **両オーナー:** 両方の Google Play デベロッパーアカウントが完全に登録済みであることを確認してください。 3. **旧オーナー:** Google Play Console または Google Play デベロッパーサポートから移管リクエストを送信してください。Google から DUNS 番号、契約書、売却証明書などの追加書類の提出を求められる場合があります。 4. **新しいオーナー:** 移管リクエストを確認して承認してください。 5. **Google:** Google サポートチームが移管を処理します。通常数営業日かかりますが、アカウントの確認、サブスクリプションの複雑さ、支払い設定によってはさらに時間がかかる場合があります。 6. **旧オーナー:** Google が移管を完了したら、Adapty でのアプリ移管を依頼するため、[support@adapty.io](mailto:support@adapty.io) にメールを送ってください。アプリ名と新しいオーナーのメールアドレスを記載してください。 7. **新しいオーナー:** Adapty でアプリを受け取ったら、[Google Play 連携ガイド](initial-android)を参照して、自分のアカウントで必要なすべての認証情報を生成・設定してください。 移管にはユーザー、サブスクリプション、統計情報、評価、ストアのリスティングが含まれます。既存のサブスクライバーへの課金は継続されますが、収益の振り込みは移管完了後に新しいオーナーのマーチャントアカウントに切り替わります。移管前の支払いレポートと注文は元のアカウントに残ります。詳細な要件については、Google の[移管ガイド](https://support.google.com/googleplay/android-developer/answer/6230247)を参照してください。 ## リスクの軽減とタイミング \{#risk-mitigation-and-timing\} **移管中も継続して機能するもの:** - 購入と更新(アプリ固有の共有シークレットが移管期間中もレシートを検証し続けます) - 既存のサブスクライバーのアクセス - SDK の動作 **一時的に機能しなくなるもの:** - App Store Connect の API 呼び出し(新しいキーが設定されるまで) - サーバー通知(エンドポイントが再設定されるまで) - 認証情報の移行中はアナリティクスに欠損が生じる場合があります **推奨タイミング:** - 主なユーザーのタイムゾーンで午前3時〜6時など、トラフィックの少ない時間帯に移管を完了させてください - ストアの移管を承認した後、すぐに認証情報を設定できるよう新しいオーナーが準備しておいてください - ストアの移管承認から Adapty の連携完了まで、15〜30 分の余裕を見てください **移管完了後:** - レシート検証をすぐにテストしてください - 48 時間、自動更新の成功率を監視してください - サーバー通知がシステムに届いていることを確認してください - 新しい購入が正しくトラッキングされていることを確認してください ## 移管が正常に完了したことを確認する \{#verify-transfer-completed-successfully\} Adapty とストアの両方で移管が完了したら: 1. **ダッシュボードへのアクセスを確認する:** 新しいオーナーが自分の Adapty ダッシュボードにアプリが表示されていることを確認してください。 2. **API キーの接続を確認する:** 新しい App Store Connect API キーまたは Google Play サービスアカウントが Adapty で正常に接続されていることを確認してください。 3. **SDK の接続をテストする:** アプリを実行して、Adapty SDK がエラーなく初期化されることを確認してください。 --- # File: installation-of-adapty-sdks --- --- title: "Adapty SDK のインストール" description: "iOS、Android、クロスプラットフォームアプリ向けの Adapty SDK をインストールします。" --- 始め方は、以下の3つのパスから選べます: - **プラットフォーム別のクイックスタートガイドに従う**: ガイドにはプロダクション対応のコードスニペットが含まれているため、実装はすぐに完了します。 - [iOS](ios-sdk-overview) - [Android](android-sdk-overview) - [React Native](react-native-sdk-overview) - [Flutter](flutter-sdk-overview) - [Unity](unity-sdk-overview) - [Kotlin Multiplatform](kmp-sdk-overview) - [Capacitor](capacitor-sdk-overview) - **LLM を活用する**: ドキュメントは LLM フレンドリーな設計です。Adapty ドキュメントで LLM を最大限に活用する方法については、[ガイド](adapty-cursor)をご覧ください。 - **サンプルアプリを試す**: - [iOS (Swift)](https://github.com/adaptyteam/AdaptySDK-iOS/tree/master/Examples) - [Android (Kotlin)](https://github.com/adaptyteam/AdaptySDK-Android/tree/master/app) - [React Native (純粋な RN によるベーシックなサンプル)](https://github.com/adaptyteam/AdaptySDK-React-Native/tree/master/examples/BasicExample) - [React Native (アドバンストサンプル – より複雑なケースを扱えるため、開発時に便利)](https://github.com/adaptyteam/AdaptySDK-React-Native/tree/master/examples/AdaptyDevtools) - [React Native (Expo dev ビルド)](https://github.com/adaptyteam/AdaptySDK-React-Native/tree/master/examples/FocusJournalExpo) - [React Native (Expo Go & Web)](https://github.com/adaptyteam/AdaptySDK-React-Native/tree/master/examples/ExpoGoWebMock) - [Flutter (Dart)](https://github.com/adaptyteam/AdaptySDK-Flutter/tree/master/example) - [Unity (C#)](https://github.com/adaptyteam/AdaptySDK-Unity/tree/main/Assets) - [Kotlin Multiplatform](https://github.com/adaptyteam/AdaptySDK-KMP/tree/main/example) - [Capacitor](https://github.com/adaptyteam/AdaptySDK-Capacitor/tree/master/examples) --- # File: sample-apps --- --- title: "サンプルアプリ" description: "" --- Adapty SDK をすぐに使い始められるよう、主要な機能の統合方法と使い方を示したサンプルアプリを用意しています。ペイウォール、購入処理、アナリティクスのトラッキングすぐに使える実装例が揃っています。 <img src="/assets/shared/img/adapty-scheme.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## サンプルアプリを使う理由 \{#why-use-sample-apps\} - **すぐに統合できる:** 実際のアプリで Adapty SDK の動作を確認できます。 - **ベストプラクティス:** 推奨される実装パターンに従えます。 - **デバッグ・テスト:** 自分のプロジェクトに Adapty を統合する前に、サンプルアプリを使ってトラブルシューティングや実験ができます。 ## 利用可能なサンプルアプリ \{#available-sample-apps\} - [iOS (Swift)](https://github.com/adaptyteam/AdaptySDK-iOS/tree/master/Examples) - [Android (Kotlin)](https://github.com/adaptyteam/AdaptySDK-Android/tree/master/app) - [React Native (純粋な RN によるベーシックな例)](https://github.com/adaptyteam/AdaptySDK-React-Native/tree/master/examples/BasicExample) - [React Native (より複雑なケースにも対応した開発向けの高度な例)](https://github.com/adaptyteam/AdaptySDK-React-Native/tree/master/examples/AdaptyDevtools) - [React Native (Expo dev ビルド)](https://github.com/adaptyteam/AdaptySDK-React-Native/tree/master/examples/FocusJournalExpo) - [React Native (Expo Go & Web)](https://github.com/adaptyteam/AdaptySDK-React-Native/tree/master/examples/ExpoGoWebMock) - [Flutter (Dart)](https://github.com/adaptyteam/AdaptySDK-Flutter/tree/master/example) - [Unity (C#)](https://github.com/adaptyteam/AdaptySDK-Unity/tree/main/Assets) - [Kotlin Multiplatform](https://github.com/adaptyteam/AdaptySDK-KMP/tree/main/example) - [Capacitor (React)](https://github.com/adaptyteam/AdaptySDK-Capacitor/tree/master/examples/basic-react-example) - [Capacitor (Vue.js)](https://github.com/adaptyteam/AdaptySDK-Capacitor/tree/master/examples/basic-vue-example) - [Capacitor (Angular)](https://github.com/adaptyteam/AdaptySDK-Capacitor/tree/master/examples/basic-angular-example) - [Capacitor (高度な開発ツール)](https://github.com/adaptyteam/AdaptySDK-Capacitor/tree/master/examples/adapty-devtools) --- # File: builder-ui --- --- title: "フロービルダーの UI" description: "フロービルダーのインターフェースとワークスペースの概要。" --- フロービルダーのメイン UI には、ビジュアル要素の追加、プロパティの編集、ユーザーフローのロジック変更に必要なすべてのツールが揃っています。この記事では、インターフェースの各エリアについて、役割と場所を説明します。 ## プロジェクトコントロールと便利なショートカット(トップツールバー) \{#project-controls-and-useful-shortcuts-top-toolbar\} * **Close** Close: フローエディターを終了してフロー一覧ページに戻ります。 * **App name** App: フローが属するアプリを表示します。 * **All flows** Flows: このアプリのすべてのフロー一覧を開きます。 * **Rename the flow**: フロー名の横にある鉛筆アイコン Pencil をクリックして名前を変更します。 * **View mode toggle**: デザインビュー Cursor と[リモートコンフィグビュー](customize-flow-with-remote-config) Remote Config を切り替えます。 * **Undo/Redo**: 矢印アイコンをクリックして変更を元に戻す Undo またはやり直す Redo ことができます。⌘Z / Ctrl+Z でも元に戻せます。 * **Save draft / Publish**: **Save draft** をクリックすると公開せずに進捗を保存できます(⌘ / Ctrl+S)。ドロップダウン Open dropdown を開いて [**Publish**](builder-save-publish) ボタンにアクセスできます。フローを[プレースメント](create-placement)に追加できるのは公開後のみです。 ## プレビューエリア(中央) \{#preview-area-center\} ワークスペースの中央エリアは、フローがモバイルデバイス上でどのように見えるかをシミュレートします。 * 要素を選択してプロパティを編集するには、その要素をクリックします。コンテナ内の子要素を選択するには、まずコンテナをクリックしてから子要素をクリックしてください。 * 画面自体のプロパティを編集するには、いずれの要素もない場所をクリックするか、「スクリーンとレイヤー」パネルで画面を選択します。 * 要素の順序を変更するには、「スクリーンとレイヤー」パネルでそのエントリを上下にドラッグします。 :::warning フローエディターはレスポンシブレイアウトを作成するために設計されています。そのため、**要素の位置を手動で変更することはできません**。変更できるのは順序のみです。各コンテナのレイアウト設定によって、内部の要素がどのように配置されるかが決まります。 ::: ### アクティブ画面バー(デバイスプレビューの上) \{#active-screen-bar-above-the-device-preview\} - **Screen name** — 現在の画面名が表示されるピルです。 - **Toggle animations** Toggle animations — 要素のアニメーションプレビューのオン/オフを切り替えます。オフにするまで継続して再生されます。アクティブ画面に[アニメーション](builder-styling#animation)が含まれている場合のみ表示されます。実際のデバイス上のアニメーション表示には影響しません。 - **Add element** Plus — 現在の画面で[要素ライブラリ](builder-elements)を開きます。「スクリーンとレイヤー」パネル上部の **+** と同等の操作で、パネルが折りたたまれているときに便利です。 ### ビューコントロール(ボトムツールバー) \{#view-controls-bottom-toolbar\} ボトムツールバーのツールでプレビューを操作できます。 * **Device**: 利用可能な iPhone と Android スマートフォンのモデルから選択して、ビューポートのサイズとデバイスの外枠を変更します。 * **Screen orientation**: 縦向き Portrait と横向き Landscape を切り替えて、異なる向きでフローをプレビューします。 * **Color scheme**: ライト Light mode とダーク Dark mode モードを切り替えて、異なるテーマでのデザインを確認します。 * **Locale**: ロケールを選択して、ローカライズされたコンテンツでフローをプレビューします。 * **View options**: デバイスのベゼルとセーフエリアガイドのオン/オフを切り替えます。 ## 画面と要素のプロパティ(右パネル) \{#screen-and-element-properties-right-panel\} ### 画面の設定とレイアウト \{#screen-settings-and-layout\} :::link メイン記事:[スクリーンとレイヤー](paywall-layout-and-products) ::: 要素が選択されていない状態では、右パネルでアクティブな[フロー画面](paywall-layout-and-products)のプロパティを調整できます。設定できる項目は以下のとおりです: * システム UI とのインタラクション(ステータスバーの表示/非表示など) * 自動レイアウトのルール * 背景(色、画像、動画) * パディングのサイズ * 縦方向スクロールの動作 [インタラクティブクイズ](onboarding-quizzes)などの特定の要素が画面に含まれている場合、関連するプロパティが追加表示されます。 ### 要素のプロパティ \{#element-properties\} 要素を選択すると、右パネルでスタイルとインタラクションのプロパティを変更できます。 #### デザインプロパティ \{#design-properties\} :::link 詳細:[要素の配置](manage-paywall-ui-elements)、[要素のスタイリング](builder-styling) ::: **Design** タブでは、選択した要素の外観とレイアウトを設定できます: * **Visibility**: 要素の表示/非表示を切り替えます。**Conditional** を有効にすると、要素を表示する条件を設定できます。 * **Position**: Relative、Absolute、Fixed のいずれかの配置方法を選択します。 * **Content**(テキスト要素のみ): 要素のテキストコンテンツを編集し、[変数](#variables)の挿入やローカライズの管理を行います。 * **Typography**(テキスト要素のみ): フォント、ウェイト、サイズ、色、揃え、装飾、省略を設定します。 * **Spacing**: 要素のマージンとパディングを設定します。 * **Effects**: ドロップシャドウ、インナーシャドウ、背景ブラー、レイヤーブラーを追加します。 * **Animation**: アニメーション効果(例:Pulse)を追加し、タイミングと強度を設定します。 * **Appearance**: 不透明度と回転を調整します。 * **Layout**: レイアウト方向(縦または横)を選択し、子要素の配置方法を決定します。 #### インタラクションプロパティ \{#interactions-properties\} :::link 詳細:[アクション](onboarding-actions)、[ナビゲーションとインタラクション](onboarding-navigation-branching) ::: **Interactions** タブでは、ユーザーが選択した要素を操作したときの動作を定義できます。各インタラクションは **トリガー** と 1 つ以上の **アクション** で構成されます: * **トリガー** は何かが起きる*タイミング*を定義します。例:**On Tap**(ユーザーが要素をタップしたとき) * **アクション** は*何が起きるか*を定義します。例:別の画面に遷移する、変数の値を変更するなど。1 つのトリガーに複数のアクションを追加して順番に実行させることもできます。 同じ要素に複数のトリガーを追加して、複数のアクションを順番に実行させることができます。 ## 左パネル \{#left-panel\} 左パネルはアクティブなボタンに応じて機能が変わります。以下から選択できます: * [スクリーンとレイヤー](#screens-and-layers) * [要素の追加](#element-selection) * [プロダクト](#products) * [スタイル](#saved-styles) * [変数](#variables) * [ローカライズ](#localization) ### スクリーンとレイヤー \{#screens-and-layers\} :::link メイン記事:[スクリーンとレイヤー](paywall-layout-and-products) ::: レイヤー Layers ボタンを押すと「スクリーンとレイヤー」が開きます(フロービルダーを開いたときにデフォルトで表示されます)。 各画面がレイヤーのツリーとして表示されます。画面上の各要素がレイヤーとなり、コンテナにはその子要素がネストされています。レイヤーをドラッグ&ドロップして並べ替えることができます。 ### 要素の選択 \{#element-selection\} :::link メイン記事:[要素](builder-elements) ::: プラス Plus ボタンをクリックすると、左パネルに利用可能な UI 要素とそのバリエーションが表示されます。エントリをクリックすると、現在の画面に新しいレイヤーとして追加されます。 ### プロダクト \{#products\} :::link メイン記事:[プロダクト](paywall-product-block) ::: プロダクト Products ボタンを押すとプロダクト一覧が開きます。フロー内の各画面に割り当てられたプロダクトが表示されます。 この一覧は読み取り専用です。画面にプロダクトを割り当てるには、Product 要素を追加して右パネルで設定してください。プロダクトの作成・編集は、Adapty ダッシュボードの **Products** ページで行います。 ### 保存済みスタイル \{#saved-styles\} :::info 詳細: - [要素のスタイリング](builder-styling) - [テキストコンテンツ](onboarding-text) - [ダークモード](paywall-dark-mode) ::: スタイル Styles ボタンを押すと「保存済みスタイル」が開きます。 ここでグローバルスタイルの編集と管理ができます。フロー内の複数の要素が同じタイポグラフィや色を使用している場合、そのデータをグローバルスタイルとして保存しておけば、ワンクリックで再利用できます。 現在、フロービルダーがサポートするグローバルスタイルは「フォントスタイル」と「カラースタイル」の 2 種類です。各カラースタイルにはダークモード用の値を別途設定することもできます。 ### 変数 \{#variables\} :::link メイン記事:[変数](onboarding-variables) ::: ブラケット Variables ボタンを押すと「変数」が開きます。 ここでフローの変数を作成・管理できます。実行時に SDK が変数のプレースホルダーを実際の値(ユーザー属性、プロダクト価格、ローカライズされた文字列など)に置き換えます。 変数は 2 つのタブに分類されています: * **Custom**: アクションを通じて自分で作成・管理する変数。 * **Elements**: クイズの回答、トグルの状態、タブの選択など、ユーザーの操作によって決まる値。 プロダクト変数(価格、名前、その他のプロダクトデータ)はこのパネルには表示されません。テキスト要素を編集する際に直接参照してください。 変数は次の目的で使用できます: * **テキストのバインド**: 静的な文字列の代わりに動的なコンテンツを表示する。 * **表示の制御**: 条件に基づいて要素を表示/非表示にする(例:プレミアムユーザーにはアップグレードボタンを非表示にする)。 * **ユーザーとのインタラクション**: フォームやクイズなどのユーザー入力フィールドからデータを取得する。 ### ローカライズ \{#localization\} :::link メイン記事:[ローカライズ](add-paywall-locale-in-adapty-paywall-builder) ::: 「ローカライズ」ビューでは、フロー全体の翻訳可能なコンテンツを一元管理できます。すべてのテキスト文字列と画像が画面ごとに整理され、各ロケールの列が表示されます。このビューから以下の操作ができます: * 新しいロケールを追加してローカライズされた文字列をインラインで編集する。 * 翻訳ステータスを確認する(各行は **Done** または **Missing** としてマークされます)。 * 画面でフィルタリングしたり、未翻訳のみ表示したりする。 * **AI Translate** で自動翻訳する、または **Import/Export** で一括翻訳をインポート/エクスポートする。 --- # File: flow-builder-recipes --- --- title: "Common flow recipes" description: "Step-by-step guides for building common screen templates in the Flow Builder." --- This section walks through how to build the most common screen templates in the Flow Builder — element by element, from the layout choices to the interactions. Each guide is self-contained and uses the standard Flow Builder elements. <CustomDocCardList /> Follow this quickstart video to create a basic personalized flow: <div style={{ maxWidth: '560px', margin: '0 auto 2rem', position: 'relative', aspectRatio: '16/9', width: '100%' }}> <iframe style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%' }} src="https://www.youtube.com/embed/aa-m459VIuY?si=zN_Co6B6qB88UPZP" title="YouTube video player" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerPolicy="strict-origin-when-cross-origin" allowFullScreen /> </div> --- # File: basic-paywall-screen --- --- title: "基本的なペイウォール画面を作成する" description: "フローBuilder で標準的なペイウォール画面を構築するためのステップバイステップガイド。" --- これは最も一般的なペイウォールのテンプレートです。単独の画面として使うか、マルチ画面[フロー](adapty-flow-builder)の最後に配置してください。 標準的なペイウォール画面には、見出し、価値説明、機能リスト、プロダクトリスト、購入ボタン、および購入の復元・利用規約・プライバシーポリシーへのフッターリンクが含まれます。 ## はじめる前に \{#before-you-start\} - Adapty ダッシュボードで[プロダクトを作成する](create-product)。 - [Adapty を App Store と Google Play に接続する](integrate-payments)。 ## 1. 再利用可能なスタイルを設定する \{#1-set-up-reusable-styles\} 再利用可能なスタイルを使うと、ワンクリックで同じタイポグラフィやカラーをすべての画面に適用できます。新しいフローにはデフォルトのテキストスタイル(H1、Body、Button Label など)があらかじめ用意されているので、要素を追加する前にデザインに合わせて調整してください。また、画面全体で使うブランドカラーのカラースタイルを追加してください。 詳しい手順については、[要素のスタイリング — 再利用可能なスタイル](builder-styling#reusable-styles)を参照してください。 スタイルを設定するには: 1. 左パネルで **Styles** Styles パネルを開く。 2. **Text** タブで既存のスタイルをクリックして、フォント、ウェイト、サイズ、カラーを編集する。デフォルトでは足りない場合にのみ新しいスタイルを追加してください。 3. **Colors** タブで **Plus Create style** をクリックし、画面全体で再利用する予定のカラーを追加する。 ## 2. 画面レイアウトを設定する \{#2-set-up-the-screen-layout\} 画面自体が追加するすべての要素のコンテナになります。後で追加する要素が正しく配置されるよう、まずレイアウト、背景、パディングを設定してください。 画面プロパティの全一覧については、[画面とレイヤー — 画面設定](paywall-layout-and-products#screen-settings)を参照してください。 画面を設定するには: 1. キャンバスの空白エリアをクリックして画面を選択する。右パネルが画面設定に切り替わる。 2. **System UI** の **Safe area** を無効にして、コンテンツが画面の端まで広がるようにする。 3. **Layout** でディレクションを **Vertical** Vertical、ディストリビューションを **Space evenly** に設定する。 4. **Fill** で背景のタイプを選択する(単色、グラデーション、画像)。この例では2つのカラーストップを持つ **Gradient** Gradient を使用しています。 ## 3. 閉じるボタンを追加する \{#3-add-the-close-button\} 閉じるボタンはペイウォールを閉じます。**Close** プリセットはあらかじめ設定済みなので、アクションの設定は不要です。 1. キャンバス上で **+** をクリックする。 2. **Buttons** > **Close** を選択する。 ## 4. タイトルを追加して閉じるボタンと並べる \{#4-add-the-title-and-pair-it-with-the-close-button\} H1 は画面上部で閉じるボタンの横に配置されます。水平に揃えるために、両方を水平コンテナにまとめます。 タイトルを追加するには: 1. **+** > **Text** > **H1** をクリックする。 2. H1 を選択した状態で、右パネルの **Design** タブを開き、**Content** フィールドでテキストを編集する。 タイトルを閉じるボタンとグループ化するには: 1. **Layers** パネルで、閉じるボタンレイヤーの三点メニュー Context menu をクリックし、**Wrap** > **Wrap in Horizontal Container** を選択する。 2. H1 レイヤーを新しい水平コンテナにドラッグする。 2つの要素を揃えるには: 1. 閉じるボタンのサイズと H1 のフォントサイズを調整して、同じ行に収まるようにする。 2. 水平コンテナを選択した状態で、右パネルでアラインメントとディストリビューションを設定して要素を正しく揃える。 ## 5. 価値説明を追加する \{#5-add-the-value-description\} タイトルの下にある短いボディテキストで、ユーザーがサブスクリプションから得られるものを説明します。 1. **+** > **Text** > **Body** をクリックする。 2. body 要素を選択した状態で、**Design** タブの **Content** フィールドでテキストを編集する。 ## 6. 機能リストを追加する \{#6-add-the-feature-list\} 機能リストは、サブスクリプションに含まれる内容をハイライトします。各行にはアイコン、機能タイトル、短い説明が含まれます。 リストプリセットの全一覧については、[要素 — リスト](builder-elements#list)を参照してください。 機能リストを追加するには: 1. **+** > **List** をクリックし、リストプリセットを選択する。ペイウォールには Icon List が最もよく使われます。 2. 各行を選択し、**Content** フィールドでタイトルと説明を編集する。 3. 行を追加または削除するには、リストを選択して **Layers** パネルの行コントロールを使用する。 ## 7. プロダクトリストを追加する \{#7-add-the-product-list\} プロダクトリストには、ユーザーが選択できるサブスクリプションオプションが表示されます。Products 要素は画面に割り当てられたプロダクトごとに1枚のカードをレンダリングし、1枚のカードが自動的にデフォルトとしてマークされます。 プロダクトの管理について詳しくは、[購入の設定](paywall-product-block)を参照してください。 プロダクトを追加して設定するには: 1. **+** > **Products** をクリックし、レイアウトプリセットを選択する。Vertical List が最もよく使われます。 2. キャンバス上の各プロダクトカードを選択し、**Design** タブのドロップダウンからプロダクトを選ぶ。ドロップダウンには Adapty ダッシュボードで設定されたすべてのプロダクトが表示されます。 3. デフォルト選択を変更するには、対象のカードを選択して **Design** タブで **Set as default product** を有効にする。 4. 割引バッジをカスタマイズするには、**Layers** パネルでプロダクトカードを展開し、バッジレイヤーを選択して **Content** フィールドでテキストを編集する。他のカードのバッジは、各バッジレイヤーの目のアイコン Show を切り替えて非表示にする。 ## 8. 購入ボタンを追加する \{#8-add-the-purchase-button\} 購入ボタンは、ユーザーが選択したプロダクトのアプリ内課金を開始します。`products.selectedProduct` 変数は常に画面で現在選択されているプロダクトに解決されます。 購入ボタンを追加するには: 1. **+** > **Buttons** をクリックし、ボタンプリセットを選択する。 2. ボタンを選択した状態で、右パネルの **Interactions** タブを開く。 3. **Add trigger** > **On tap** をクリックし、**Add action** をクリックする。 4. **Action** を **Purchase** に、**Product** を `products.selectedProduct` に設定する。 ## 9. フッターリンクを追加する \{#9-add-footer-links\} フッターには、利用規約とプライバシーポリシーへのリンク(アプリストアで必須)、および以前の購入を復元するボタンが含まれます。 フッターリンクを追加するには: 1. **+** > **Buttons** > **Links** をクリックする。Restore Purchases、Terms of Use、Privacy Policy の行が追加されます。 2. **Layers** パネルで **Terms of Use** ボタンを選択する。**Interactions** タブを開くと **Open URL** アクションがすでに設定されています。アクションをクリックして遷移先の URL を入力する。 3. **Privacy Policy** ボタンでも同様に、プライバシーポリシーの URL を設定する。 4. **Restore Purchases** ボタンはそのままにする。アクションはあらかじめ設定済みです。 :::tip 要素の位置が高すぎる・低すぎると感じたり、余白を追加したい場合は、要素のマージンとパディングを調整してください。 ::: ## 次のステップ \{#next-steps\} - [フローを保存して公開する](builder-save-publish)。 - [プレースメントにフローを追加する](create-placement)ことで、ユーザーへの表示を開始できます。 --- # File: show-plans-bottom-sheet --- --- title: "すべてのプランをボトムシートに表示する" description: "シングルCTA、「すべてのプランを表示」リンク、プロダクト一覧を展開するボトムシートを備えたヒーローペイウォールを作成します。" --- このテンプレートは、まず1つのハイライトされたオファーを前面に出し、プラン一覧への控えめなリンクを添えます。**Show all plans** をタップすると、他のプロダクト、購入ボタン、フッターリンクを含むボトムシートがスライドアップします。 特定のプランが突出したコンバージョン率を持つ場合に活用してください。ボトムシートにより、メイン画面をすっきり保ちながら、代替プランにワンタップでアクセスできます。 ## 始める前に \{#before-you-start\} - Adapty ダッシュボードで[プロダクトを作成](create-product)します。 - [Adapty を App Store および Google Play に接続](integrate-payments)します。 ## 1. 画面レイアウトを設定する \{#1-set-up-the-screen-layout\} ヒーロー画像を画面の背景として使用し、残りのコンテンツを下部にグループ化することで、画像が画面の上部を占めるようにします。 画面プロパティの完全なリストについては、[画面とレイヤー — 画面設定](paywall-layout-and-products#screen-settings)を参照してください。 画面を設定するには: 1. キャンバスの空白領域をクリックして画面を選択します。 2. **System UI** の下にある **Safe area** を無効にして、ヒーロー画像が画面の端まで広がるようにします。 3. **Fill** の下で **Image** Image を選択し、ヒーロー画像をアップロードします。 4. **Layout** の下で、方向、ギャップ、配置を設定して、コンテンツを好みの位置に固定します。このテンプレートでは、**Vertical** Vertical 方向に小さいギャップと **bottom-middle** 配置を使用して、見出しとボタンを画面下部にグループ化します。 ## 2. CTAの見出しを追加する \{#2-add-the-cta-heading\} 見出しは画面の下部、サブスクライブボタンのすぐ上に配置されます。ヒーロー画像はその上の領域を埋めます。 1. **+** > **Text** > **H1** をクリックします。 2. H1 を選択した状態で、**Design** タブを開き、**Content** フィールドのテキストを編集します。 ## 3. ボトムシートとそのタイトルを追加する \{#3-add-the-bottom-sheet-and-its-title\} ボトムシートは、画面の下部からスライドアップするレイアウトコンテナです。今は表示状態で追加してください — 次のいくつかのステップでコンテンツを追加してから、完成したら非表示にします。非表示の要素は編集できないため、コンテンツを追加し終えるまでシートを表示状態に保つ必要があります。 ボトムシートやその他のレイアウトコンテナの詳細については、[エレメント — レイアウト](builder-elements#layout)を参照してください。 ボトムシートとそのタイトルを追加するには: 1. **+** > **Layout** > **Bottom Sheet** をクリックします。 2. **Layers** パネルでボトムシートを展開し、**Title** レイヤーを選択して、**Design** タブの **Content** フィールドを編集します(例:`Choose your plan`)。 ## 4. ボトムシート内にプロダクト一覧を追加する \{#4-add-the-product-list-inside-the-bottom-sheet\} すべてのプロダクトをボトムシート内に配置します。そのうちの1つはメインのCTAボタンに表示される価格にも使用されます。 プロダクトの管理について詳しくは、[購入の設定](paywall-product-block)を参照してください。 プロダクトを追加・設定するには: 1. **+** > **Products** をクリックし、レイアウトプリセットを選択します。ほとんどの場合、Vertical List が適しています。要素が画面上に表示されますが、ボトムシートの外側になります。 2. **Layers** パネルで、Products レイヤーをボトムシート内の **Content** コンテナにドラッグします。 3. キャンバス上の各プロダクトカードを選択し、**Design** タブのドロップダウンからプロダクトを選択します。 ## 5. ボトムシート内に購入ボタンを追加する \{#5-add-the-purchase-button-inside-the-bottom-sheet\} ボトムシートには、ユーザーがリストから選択したプランを購入するための専用の購入ボタンが必要です。 1. **+** > **Buttons** をクリックし、ボタンプリセットを選択します。 2. **Layers** パネルで、新しいボタンをボトムシート内の **Content** コンテナにドラッグします。 3. ボタンを選択した状態で、右パネルの **Interactions** タブを開きます。 4. **Add trigger** > **On tap** をクリックし、**Add action** をクリックします。 5. **Action** を **Purchase**、**Product** を `products.selectedProduct` に設定します。 ## 6. ボトムシート内にフッターリンクを追加する \{#6-add-the-footer-links-inside-the-bottom-sheet\} :::important ボタン内にネストされたテキストには[インラインリンク](onboarding-text#inline-link)を使用しないでください。代わりに、ボタン自体に **Open URL** アクションを設定してください。 ::: 利用規約、プライバシーポリシー、購入の復元はシートの下部に配置されます — メイン画面はすっきりと保たれます。 1. **+** > **Buttons** > **Links** をクリックします。これにより、Restore Purchases、Terms of Use、Privacy Policy の行が追加されます。 2. **Layers** パネルで、Links の行をボトムシート内の **Content** コンテナにドラッグします。 3. **Layers** パネルで、**Terms of Use** ボタンを選択します。**Interactions** タブを開き、**Open URL** フィールドに利用規約の URL を貼り付けます。 4. **Privacy Policy** ボタンでも同様に、プライバシー URL を設定します。 5. **Restore Purchases** リンクはそのままにしておきます。アクションは事前に設定されています。 ## 7. ボトムシートを非表示にする \{#7-hide-the-bottom-sheet\} シートのコンテンツが揃ったら、デフォルトで画面に表示されないように非表示にします。ユーザーは最後のステップで **Show all plans** をタップすることで表示できます。 **Layers** パネルでボトムシートを選択し、状態を **Hide** Hide に設定します。シートはレイヤーツリーに残りますが、キャンバスにはレンダリングされなくなります。 ## 8. メインのサブスクライブボタンを追加する \{#8-add-the-main-subscribe-button\} 画面上のメインボタンは、ワンタップでユーザーを月額プランに登録します。ラベルには月額プロダクトの価格変数を使用するため、ボタンは常にプロダクトと同期されます。 1. **Layers** パネルでスクリーンをクリックして、新しい要素がボトムシート内ではなくルートに追加されるようにします。 2. **+** > **Buttons** をクリックし、ボタンプリセットを選択します。 3. ボタンを選択した状態で、**Design** タブを開き、**Content** フィールドにカーソルを置きます。Variable icon をクリックして、メインプロダクトの価格変数を選択します。残りのラベルで囲んでください — 例:`Subscribe for {price}/month`。 4. **Interactions** タブに切り替え、**Add trigger** > **On tap** > **Add action** をクリックします。 5. **Action** を **Purchase**、**Product** を必要なプロダクトに設定します。ボトムシートのボタンとは異なり、こちらは `products.selectedProduct` ではなく特定のプロダクトを対象とします。 ## 9. 「すべてのプランを表示」リンクを追加する \{#9-add-the-show-all-plans-link\} サブスクライブボタンの下にあるテキストリンクをタップすると、ボトムシートが表示されます。**Button Label** スタイルのテキスト要素として追加することで、見た目をミニマルに保ちながらアクションを設定できます。 Show/Hide アクションの詳細については、[アクション — 要素の表示/非表示](onboarding-actions#showhide-elements)を参照してください。 リンクを追加するには: 1. **Layers** パネルでスクリーンを選択した状態で、**+** > **Text** > **Button Label** をクリックします。 2. テキスト要素を選択した状態で、**Content** フィールドを `Show all plans` に編集します。 3. **Interactions** タブを開き、**Add trigger** > **On tap** > **Add action** をクリックします。 4. **Action** を **Show** に設定し、ドロップダウンからボトムシート要素を選択します。 ## 次のステップ \{#next-steps\} - [フローを保存して公開する](builder-save-publish)。 - [プレースメントにフローを追加して](create-placement)、ユーザーへの表示を開始する。 --- # File: paywall-with-tabs --- --- title: "タブ付きペイウォールを作成する" description: "2つのタブで異なるフィーチャーリスト、プロダクトグループ、購入アクションを切り替えるペイウォール画面を作成します。" --- このテンプレートは、タブを使って1つの画面で同じオファーの2つのバリアントを切り替えます。各タブには独自のフィーチャーリスト、プロダクトリスト、購入ボタンが含まれています。タブをタップすると画面を離れることなく表示コンテンツが切り替わります。プラン階層、請求期間、またはオーディエンスセグメントでプランを分けるのに便利です。 ## 始める前に \{#before-you-start\} - Adapty ダッシュボードで[プロダクトを作成する](create-product)。 - [Adapty を App Store および Google Play に接続する](integrate-payments)。 ## 1. 画面レイアウトを設定する \{#1-set-up-the-screen-layout\} 画面は閉じるボタン、見出し、タブ、タブコンテンツのコンテナとして機能します。この例では背景に画像を使用していますが、単色やグラデーションでも同様に機能します。 画面プロパティの完全な一覧は、[画面とレイヤー — 画面設定](paywall-layout-and-products#screen-settings)を参照してください。 画面を設定するには: 1. キャンバスの空の領域をクリックして画面を選択します。 2. **System UI** の下で、**Safe area** を無効にして背景が画面の端まで広がるようにします。 3. **Fill** の下で、背景タイプを選択して設定します。この例では **Image** Image を使用していますが、単色やグラデーションでも同様に機能します。 4. **Layout** の下で、方向を **Vertical** Vertical に設定し、要素が上から縦に並びタブコンテンツが残りのスペースを埋めるようにギャップと配置を設定します。 ## 2. 閉じるボタンを追加する \{#2-add-the-close-button\} 閉じるボタンはペイウォールを閉じます。**Close** プリセットはあらかじめ設定済みのため、アクションの設定は不要です。 1. キャンバスで **+** をクリックします。 2. **Buttons** > **Close** を選択します。 ## 3. タイトルを追加して閉じるボタンと組み合わせる \{#3-add-the-title-and-pair-it-with-the-close-button\} 見出しは画面上部で閉じるボタンの隣に配置されます。両方を横に並べるには、水平コンテナでまとめます。 タイトルを追加するには: 1. **+** > **Text** > **H1** をクリックします。 2. H1 を選択した状態で、**Design** タブを開き **Content** フィールドのテキストを編集します。 タイトルと閉じるボタンをグループ化するには: 1. **Layers** パネルで、閉じるボタンレイヤーの三点メニュー Context menu をクリックし、**Wrap** > **Wrap in Horizontal Stack** を選択します。 2. H1 レイヤーを新しい水平コンテナにドラッグします。 2つの要素を揃えるには: 1. 同じ行に無理なく収まるよう、閉じるボタンのサイズと H1 のフォントサイズを調整します。 2. 水平コンテナを選択した状態で、右パネルの配置と分布を設定して要素が正しく並ぶようにします。 ## 4. タブを追加してラベルを設定する \{#4-add-the-tabs-and-configure-their-labels\} タブ要素は画面のセクションを切り替え可能なコンテンツパネルに分割します。各タブには、そのタブが選択されたときに表示される独自のコンテンツコンテナがあります。 タブ要素の詳細は [要素 — タブ](builder-elements#tabs) を参照してください。選択可能なグループについては、[選択可能な要素とグループ](flow-selectable-elements)を参照してください。 タブを追加するには: 1. **+** > **Tabs** をクリックして、プリセット(Segment control、Button Tabs、Underline)を選択します。 2. キャンバスまたは **Layers** パネルで各タブの名前を選択した状態で、**Design** タブの **Content** フィールドを編集してラベルを変更します(例:`Premium` と `Pro`)。 ## 5. 最初のタブにフィーチャーリストを追加する \{#5-add-a-feature-list-to-the-first-tab\} 最初のタブ内のコンパクトなフィーチャーリストで、そのプランに含まれる内容をユーザーに伝えます。 リストプリセットの完全なセットは、[要素 — リスト](builder-elements#list)を参照してください。 フィーチャーリストを追加するには: 1. **+** > **List** をクリックして、リストプリセットを選択します。Icon List がペイウォールに最もコンパクトです。要素はレイヤーツリーの末尾に表示されます。 2. 各行を選択した状態で、**Content** フィールドのタイトルを編集します。 3. **Layers** パネルで、リストを最初のタブの **Content** コンテナにドラッグします。 ## 6. 最初のタブにプロダクトリストを追加する \{#6-add-the-product-list-to-the-first-tab\} プロダクトリストは最初のタブのサブスクリプションオプションを表示します。Products 要素は画面に割り当てられたプロダクトごとに1つのカードをレンダリングし、独自の選択可能グループを作成します。 プロダクトの管理については、[購入を設定する](paywall-product-block)を参照してください。 プロダクトを追加して設定するには: 1. **+** > **Products** をクリックして、レイアウトプリセットを選択します。Vertical List は積み重なったプランに適しています。要素はレイヤーツリーの末尾に表示されます。 2. キャンバスで各プロダクトカードを選択し、**Design** タブのドロップダウンからプロダクトを選択します。 3. **Layers** パネルで、Products レイヤーを最初のタブの **Content** コンテナにドラッグします。 ## 7. 最初のタブに購入ボタンを追加する \{#7-add-the-purchase-button-to-the-first-tab\} 購入ボタンは、最初のタブ内でユーザーが選択したプロダクトのアプリ内課金を開始します。ラベルには選択したプロダクトの価格が使用されるため、ユーザーの選択と常に同期します。 Purchase アクションの詳細は、[アクション — Purchase](onboarding-actions#purchase)を参照してください。 購入ボタンを追加して設定するには: 1. **+** > **Buttons** をクリックして、ボタンプリセットを選択します。要素はレイヤーツリーの末尾に表示されます。 2. ボタンを選択した状態で、**Design** タブを開いて **Content** フィールドにカーソルを置きます。変数アイコン Variable icon をクリックし、`products.selectedProduct` を選択してから `prod_price` 属性を選択します。変数全体は `products.selectedProduct.prod_price` になります。残りのラベルで囲みます(例:`Subscribe for {prod_price}`)。 3. **Interactions** タブに切り替えて、**Add trigger** > **On tap** > **Add action** をクリックします。 4. **Action** を **Purchase** に、**Product** を `products.selectedProduct` に設定します。 5. **Layers** パネルで、ボタンを最初のタブの **Content** コンテナにドラッグします。 ## 8. 最初のタブのコンテンツを2番目のタブにコピーする \{#8-copy-the-first-tabs-content-into-the-second-tab\} 同じ構造を最初から作り直す代わりに、最初のタブのフィーチャーリスト、プロダクトリスト、購入ボタンを2番目のタブにコピーします。その後、値を更新するだけで済みます。 コンテンツをコピーするには: 1. **Layers** パネルで、最初のタブの **Content** コンテナを展開します。 2. 内部の各要素(フィーチャーリスト、プロダクト、購入ボタン)を選択し、⌘C / Ctrl+C でコピーして ⌘V / Ctrl+V で貼り付けます。コピーがレイヤーツリーの末尾に表示されます。 3. コピーされた各要素を2番目のタブの **Content** コンテナにドラッグします。 ## 9. 2番目のタブのコンテンツを更新する \{#9-update-the-second-tabs-content\} 2番目のタブは最初のタブと同じ内容になっています。各要素を更新して2番目のプランを反映させます。 2番目のタブを更新するには: 1. 2番目のタブ内のフィーチャーリストを編集して、行が2番目のプランのフィーチャーと一致するようにします。 2. 2番目のタブの Products 要素で各プロダクトカードを選択し、ドロップダウンから2番目のプランのプロダクトを割り当てます。この Products 要素は自動的に別の選択可能グループ(`products2`)になります。 3. 2番目のタブの購入ボタンを選択します。**Design** タブの **Content** フィールドで、価格変数を `products.selectedProduct.prod_price` から `products2.selectedProduct.prod_price` に変更します。 4. **Interactions** タブに切り替えて、**Purchase** アクションの **Product** を `products.selectedProduct` から `products2.selectedProduct` に更新します。 ## 10. 共有フッターリンクを追加する \{#10-add-the-shared-footer-links\} 利用規約、プライバシーポリシー、購入の復元は、どのタブがアクティブであっても常に表示されます。両方のタブコンテンツコンテナの外側の画面レベルに追加して、タブ間で共有されるようにします。 フッターリンクを追加するには: 1. **+** > **Buttons** > **Links** をクリックします。これにより、Restore Purchases、Terms of Use、Privacy Policy の行がレイヤーツリーの末尾に追加されます。これはタブ内にネストされず、画面のルートに配置されるため、正しい位置です。 2. **Layers** パネルで **Terms of Use** ボタンを選択します。**Interactions** タブを開き、**Open URL** フィールドに利用規約の URL を貼り付けます。 3. **Privacy Policy** ボタンにもプライバシー URL を入力して同じ手順を繰り返します。 4. **Restore Purchases** リンクはそのままにしておきます。アクションはあらかじめ設定済みです。 ## 次のステップ \{#next-steps\} - [フローを保存して公開する](builder-save-publish)。 - [プレースメントにフローを追加する](create-placement)ことで、ユーザーへの表示を開始します。 --- # File: paywall-features-per-product --- --- title: "プロダクトごとに異なる機能を表示する" description: "条件付き表示を使って、ユーザーが選択したプロダクトに応じて異なる機能リストを表示します。" --- このテンプレートは条件付き表示を使って、プランごとに異なる機能リストを強調表示します。画面には2つのプロダクト(例:ProとPro+)が表示され、ユーザーが選択したプロダクトに応じて異なる機能リストが表示されます。1つのプロダクトはデフォルトとして設定されるため、画面が最初に読み込まれたときにそのプロダクトの機能リストが表示されます。 ## 始める前に \{#before-you-start\} - Adapty ダッシュボードで[プロダクトを作成](create-product)する。 - [AdaptyをApp StoreおよびGoogle Playに接続](integrate-payments)する。 ## 1. 画面レイアウトを設定する \{#1-set-up-the-screen-layout\} 画面は、追加するすべての要素のコンテナとして機能します。この例では背景に画像を使用していますが、単色やグラデーションでも同様に機能します。 画面プロパティの全リストは、[画面とレイヤー — 画面の設定](paywall-layout-and-products#screen-settings)を参照してください。 画面を設定するには: 1. キャンバスの空白部分をクリックして画面を選択します。 2. **System UI** の下にある **Safe area** を無効にして、背景が画面の端まで広がるようにします。 3. **Fill** の下で背景の種類を選んで設定します。この例では **Image** Image を使用していますが、単色やグラデーションでも同様に機能します。 4. **Layout** の下で方向を **Vertical** Vertical に設定し、要素が上から縦に並びコンテンツが残りのスペースを埋めるように、ギャップと配置を設定します。 ## 2. 閉じるボタンを追加する \{#2-add-the-close-button\} 閉じるボタンはペイウォールを閉じます。**Close** プリセットはあらかじめ設定済みなので、アクションの設定は不要です。 1. キャンバスで **+** をクリックします。 2. **Buttons** > **Close** を選択します。 ## 3. タイトルを追加して閉じるボタンと組み合わせる \{#3-add-the-title-and-pair-it-with-the-close-button\} 見出しは画面上部の閉じるボタンの横に配置されます。横方向に揃えるには、両方を横方向コンテナでラップします。 タイトルを追加するには: 1. **+** > **Text** > **H1** をクリックします。 2. H1 を選択した状態で **Design** タブを開き、**Content** フィールドのテキストを編集します。 タイトルを閉じるボタンとグループ化するには: 1. **Layers** パネルで、閉じるボタンレイヤーの3点メニュー Context menu をクリックし、**Wrap** > **Wrap in Horizontal Container** を選択します。 2. H1 レイヤーを新しい横方向コンテナにドラッグします。 2つの要素を揃えるには: 1. 閉じるボタンのサイズとH1のフォントサイズを調整して、同じ行に収まるようにします。 2. 横方向コンテナを選択した状態で、右パネルで配置と分布を設定して要素を正しく揃えます。 ## 4. プロダクトリストを追加する \{#4-add-the-product-list\} ユーザーが選択できるプロダクトを追加します。画面が最初に読み込まれたときに意味のある状態になるよう、1つをデフォルトとして設定します。 プロダクトの管理の詳細は、[購入を設定する](paywall-product-block)を参照してください。 プロダクトを追加して設定するには: 1. **+** > **Products** をクリックしてレイアウトプリセットを選択します。このテンプレートには縦方向リストが適しています。 2. キャンバス上の各プロダクトカードを選択し、**Design** タブのドロップダウンからプロダクトを選びます。 3. デフォルトで選択したいカード(例:Pro+)を選択し、**Design** タブで **Set as default product** を有効にします。 ## 5. 最初のプロダクトの機能リストを追加する \{#5-add-the-feature-list-for-the-first-product\} 最初の機能リストはデフォルトのプロダクトを説明します。ユーザーが最初のプロダクトを選択しているときのみ表示されます。 条件付き表示の詳細は、[条件付き表示](onboarding-element-visibility)を参照してください。 :::tip 2つの別々のリストの代わりに、単一のリストを追加してその中のテキスト要素を条件付きにすることで、1つのリストが選択されたプロダクトに応じて変化するようにできます。[条件付きテキストを追加する](onboarding-text#add-conditional-text)を参照してください。 ::: 機能リストを追加して設定するには: 1. **+** > **List** をクリックしてコンパクトなリストプリセットを選択します。ペイウォールにはアイコンリストが適しています。 2. 各行を選択した状態で、**Content** フィールドのタイトルを編集して最初のプロダクトの機能を説明します。 3. リストを選択した状態で **Design** タブを開きます。**Visibility** の下で **Conditional** Conditional を選択します。 4. 最初のプロダクトが現在選択されているときのみリストが表示されるよう条件を設定します。`products.selectedProduct.prod_title` 変数と照合します。**Value** については、変数アイコン `{}` をクリックし、最初のプロダクトカードを選んでから `prod_title` 属性を選択します。比較結果はそのプロダクトのタイトルに解決されます。 ## 6. 2番目のプロダクトの機能リストを追加する \{#6-add-the-feature-list-for-the-second-product\} 2番目のプロダクトについても同じ手順を繰り返します。2つのリストは相互排他的であり、選択されているプロダクトに応じてどちらか一方のみが表示されます。 2番目の機能リストを追加するには: 1. **+** > **List** をクリックして、視覚的な一貫性のために同じコンパクトプリセットを選択します。 2. 各行を編集して2番目のプロダクトの機能を説明します。 3. **Visibility** の下で **Conditional** Conditional を選択し、手順5と同じ条件を設定しますが、**Value** の変数ピッカーで2番目のプロダクトカードの `prod_title` を指定します。 ## 7. 購入ボタンを追加する \{#7-add-the-purchase-button\} 購入ボタンは、ユーザーが選択したプロダクトのアプリ内課金を開始します。ラベルには選択されたプロダクトの価格が使用されるため、ユーザーがプランを切り替えると更新されます。 Purchase アクションの詳細は、[アクション — Purchase](onboarding-actions#purchase)を参照してください。 購入ボタンを追加して設定するには: 1. **+** > **Buttons** をクリックしてボタンプリセットを選択します。 2. ボタンを選択した状態で **Design** タブを開き、**Content** フィールドにカーソルを置きます。変数アイコン Variable icon をクリックし、`products.selectedProduct` を選んでから `prod_price` 属性を選択します。完全な変数は `products.selectedProduct.prod_price` に解決されます。ラベルの残りのテキストで囲みます(例:`Subscribe for {prod_price}`)。 3. **Interactions** タブに切り替えて **Add trigger** > **On tap** > **Add action** をクリックします。 4. **Action** を **Purchase** に、**Product** を `products.selectedProduct` に設定します。 ## 8. フッターリンクを追加する \{#8-add-the-footer-links\} 利用規約、プライバシーポリシー、購入の復元はメインコンテンツの下に配置されます。 フッターリンクを追加するには: 1. **+** > **Buttons** > **Links** をクリックします。これにより、レイヤーツリーの末尾にRestore Purchases、Terms of Use、Privacy Policyを含む行が追加されます。 2. **Layers** パネルで **Terms of Use** ボタンを選択します。**Interactions** タブを開き、**Open URL** フィールドに利用規約のURLを貼り付けます。 3. **Privacy Policy** ボタンについてもプライバシーURLで同じ手順を繰り返します。 4. **Restore Purchases** リンクはそのままにします。アクションはあらかじめ設定済みです。 ## 次のステップ \{#next-steps\} - [フローを保存して公開する](builder-save-publish)。 - [プレースメントにフローを追加して](create-placement)ユーザーへの表示を開始する。 --- # File: onboarding-flow-tutorial --- --- title: "パーソナライズされたオンボーディングフローを構築する" description: "複数画面で構成されるオンボーディングフローの全構築プロセス(画面、コンテンツ、ナビゲーション、条件分岐)を実例を使って説明します。" --- フロービルダーのマルチスクリーンフローは、ナビゲーションアクションで接続された画面のシーケンスです。フローは直線的に進めることも、以前の画面で収集したユーザー入力に基づいて分岐させることもできます。このチュートリアルでは、4画面のオンボーディングフローを例に、画面の作成、コンテンツの構築、ナビゲーションの接続、条件分岐の追加まで、端から端まで説明します。 この例では以下を使用します: - ユーザーの名前をパーソナライズ用の変数として公開する**名前入力** - 次に表示する画面を決定する回答を持つ**シングルチョイスクイズ** - 各オーディエンスセグメント向けにカスタマイズされたコピーを持つ**2つの分岐パス** - 最終画面としての**ペイウォール** 同じパターンは、ユーザー入力に基づいてコンテンツをパーソナライズする任意のフローに適用できます。 動画形式を好む場合は、同じプロセスを端から端まで説明するこのクイックスタートチュートリアルをご覧ください: <div style={{ maxWidth: '560px', margin: '0 auto 2rem', position: 'relative', aspectRatio: '16/9', width: '100%' }}> <iframe style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%' }} src="https://www.youtube.com/embed/aa-m459VIuY?si=zN_Co6B6qB88UPZP" title="YouTube video player" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerPolicy="strict-origin-when-cross-origin" allowFullScreen /> </div> ## 始める前に \{#before-you-start\} - Adapty ダッシュボードで[プロダクトを作成](create-product)してください。この例のフローでは、年間と月間の2つのサブスクリプションを使用します。 - [Adapty を App Store と Google Play に接続](integrate-payments)してください。 ## 1. 再利用可能なスタイルを設定する \{#1-set-up-reusable-styles\} 再利用可能なスタイルを使うと、一度のクリックですべての画面に統一されたタイポグラフィと色を適用できます。カラースタイルにはライトとダークのバリアントが含まれており、フローは両方のテーマを自動的にサポートします。 詳細な手順については、[要素スタイリング — 再利用可能なスタイル](builder-styling#reusable-styles)を参照してください。 スタイルを設定するには: 1. 左パネルで **Styles** Styles パネルを開きます。 2. **Colors** タブで **Plus Create style** をクリックし、再利用する色を追加します。各色について、ライトの値を選択し、Dark タブに切り替えてダークの値を選択します。 3. **Text** タブで、既存のスタイルをクリックしてフォント、ウェイト、サイズを編集するか、**Plus Create style** をクリックしてカスタムプリセットを追加します。 ## 2. 画面を作成する \{#2-create-the-screens\} フローは画面のシーケンスです。最初の画面を共通のベース(レイアウト、背景、セーフエリア)で設定し、残りの画面のために複製します。こうすることで、すべての画面が同じ基盤を共有し、一度だけ設定すれば済みます。 画面の管理については、[画面とレイヤー — 画面の管理](paywall-layout-and-products#manage-screens)を参照してください。 画面を設定するには: 1. 最初の画面のキャンバスの空いている場所をクリックして画面設定を開きます。 2. **System UI** の下で **Safe area** を無効にして、背景やエッジに揃えた要素が画面の端まで広がれるようにします。 3. **Fill** の下で背景の種類を選択して設定します。たとえば、フローのすべての画面の背景に表示される **Image** Image などです。 4. **Layout** の下で方向を **Vertical** Vertical に設定し、デザインに合った配置を選択します。 5. 左パネルの **Screens** セクションで、最初の画面の三点メニュー Context menu をクリックして **Duplicate** を選択します。合計4画面になるまで繰り返します(最初の分岐パスを複製して後で2番目の分岐パスを追加します)。 6. 各画面の役割に合った名前に変更します。この例では:`Welcome`、`Quiz`、`Rock path`、`Paywall` です。 ## 3. イントロダクション画面を構築する \{#3-build-the-introduction-screen\} 最初の画面は通常、雰囲気を設定します — ヘッドライン、機能リスト、残りのフローを開くコールトゥアクションです。この例では Welcome 画面がこれにあたります。 **Screens** パネルで **Welcome** 画面をクリックし、要素を追加します: 1. メイン画像を追加します。**+** > **Media** > **Image** をクリックし、画像をアップロードして必要に応じてマージンを調整します。 2. ヘッドラインを追加します:**+** > **Text** をクリックし、保存したテキストスタイルから見出しスタイルを選択して、**Content** フィールドを編集します。 3. 機能リストを追加します。**+** > **List** > **Icon Cards** をクリックし、各カードのアイコンとラベルを編集します。 4. 下部にプライマリナビゲーションボタンを追加します。ナビゲーションのステップでアクションが設定されます。 ## 4. 入力とクイズ画面を構築する \{#4-build-the-input-and-quiz-screen\} 2番目の画面はユーザーからの入力を収集します。この例では、名前と、次に表示するパスを決定するシングルチョイスの回答を尋ねます。 入力とクイズについては、[入力とフォーム](builder-inputs-and-forms)と[アンケートとクイズ](onboarding-quizzes)を参照してください。 **Screens** パネルで **Quiz** 画面をクリックし、要素を追加します。画面上の各グループ(イントロ、質問+入力、質問+クイズ)は、関連する要素が視覚的にまとまるように、それぞれ独自の縦コンテナに配置します。 1. イントロのヘッドラインとボディを追加します。ヘッドラインには **+** > **Text** > **H1**、サポートコピーには **+** > **Text** > **Body** をクリックします。 2. イントロをグループ化します。**+** > **Layout** > **Vertical Container** をクリックし、新しいコンテナをレイヤーツリーの一番上にドラッグして、H1 とボディをその中にドラッグします。 3. 最初の質問と入力を追加します。質問のキャプションには **+** > **Text**、フィールドには **+** > **Inputs** > **Text** をクリックします。 4. **Design** タブで入力の **Element ID** を設定します。この例では `name` です。これにより、他の画面が参照できる変数として値が公開されます。 5. イントロと同じ方法で、キャプションと入力を縦コンテナにグループ化します。 6. 2番目の質問とクイズを追加します。キャプションには **+** > **Text**、**+** > **Quiz** をクリックして Icon Options などのレイアウトプリセットを選択します。オプションを設定します。この例では `Rock` と `Hip hop` です。 7. イントロと同じ方法で、キャプションとクイズを縦コンテナにグループ化します。 8. オプションの ID を設定します。各クイズオプションを選択し、**Interactions** タブを開いて **Element ID** を設定します。これらの ID は後の条件ナビゲーションで参照されます。 9. クイズをシングルチョイスに切り替えます:キャンバスの空いている場所をクリックして **Screen settings** を開き、**Selectable Groups** までスクロールして、クイズグループの名前をクリックし、タイプを **Single choice** に設定します。 10. 下部にプライマリボタンを追加します。これが分岐をトリガーする Next ボタンです。 ## 5. 最初の分岐パスを構築する \{#5-build-the-first-branching-path\} 各パス画面は、1つのオーディエンスセグメント向けにコンテンツをカスタマイズします。この例では、Rock パスにロック中心のコンテンツ(プレイリスト、アーティスト、おすすめ)が含まれます。 変数については、[変数](onboarding-variables)を参照してください。 画面を構築するには: 1. **Screens** パネルで **Rock path** 画面をクリックします。 2. ヘッドラインを追加します。パーソナライズを表示する **Content** フィールドにカーソルを置き、変数アイコン Variable icon をクリックして **Elements** タブを開きます。入力がある画面(この例では **Quiz**)を選択し、入力の値変数を選択します。ピッカーは `<elementId>.value` として解決します。この例では `name.value` です。実行時に、ヘッドラインはユーザーが入力したテキストで更新されます。 3. このパスのオーディエンスセグメントに合わせたボディコピーを追加のテキスト要素として追加します。 4. 下部にプライマリボタンを追加します。 ## 6. 2番目の分岐パスを構築する \{#6-build-the-second-branching-path\} パス画面は通常レイアウトを共有します — 変わるのはコピーだけです。最初のパス画面を複製してコンテンツを更新します。 複製して更新するには: 1. **Screens** パネルで最初のパス画面を選択し、⌘D / Ctrl+D を押して複製します。コピーは画面リストの末尾に表示されます。 2. コピーの名前を変更します。この例では `Hip hop path` とし、複製元の画面の隣に来るように画面リスト内で適切な位置にドラッグします。 3. 別のオーディエンスセグメント向けにボディコピーを更新します。パーソナライズされたヘッドラインは引き続き機能します — 変数はそのまま引き継がれます。 ## 7. ペイウォールを構築する \{#7-build-the-paywall\} 最終画面はペイウォールです — ユーザーがサブスクリプションに登録できる場所です。ペイウォールの仕組みの詳細なウォークスルーについては、[基本的なペイウォール画面を作成する](basic-paywall-screen)を参照してください。以下はそのウォークスルーの簡略版です。 **Screens** パネルで **Paywall** 画面をクリックし、要素を追加します: 1. 上部に **Horizontal Container** を追加し、その中に **Close** ボタンを追加します。Close プリセットはあらかじめ設定されています。 2. メイン画像、ヘッドライン(パス画面と同じパーソナライズ変数を使用)、サブヘッドラインをサポートコピーとして追加します。 3. プロダクトを追加します:**+** > **Products** をクリックして **Vertical List** を選択します。**Design** タブのドロップダウンから各カードにプロダクトを割り当てます。 4. デフォルトプロダクトのカードをクリックして **Set as default product** を有効にし、画面が読み込まれたときにあらかじめ選択されるようにします。 5. 購入ボタンを追加します。**+** > **Buttons** をクリックしてプリセットを選択します。**Interactions** タブで **Add trigger** > **On tap** > **Add action** をクリックし、**Action** を **Purchase**、**Product** を `products.selectedProduct` に設定します。 6. **Button** > **Links** テンプレートを画面に追加します。Restore Purchases、Terms of Use、Privacy Policy の3つのフッターリンクが含まれています。 Restore リンクはあらかじめ設定されています。その他のリンクを設定するには、ボタン要素を選択し、**Interactions** タブを開いて、**Open URL** アクションのターゲットを設定します。 ## 8. 画面間のナビゲーションを接続する \{#8-wire-navigation-between-the-screens\} 画面は自動的には接続されません。**On tap** トリガーと **Navigate to** アクションを使って、各画面のプライマリボタンを次の画面に接続します。ユーザー入力に基づいて分岐する画面は、代わりに **Conditional action** を使用します。 ナビゲーションと条件アクションについては、[ナビゲーションとインタラクション](onboarding-navigation-branching)と[アクション — 条件アクション](onboarding-actions#conditional-actions)を参照してください。 この例のフローのナビゲーションを接続するには: 1. **イントロダクション画面からのスタティックナビゲーション。** Welcome 画面を開き、プライマリボタンを選択して **Interactions** タブに切り替えます。**Add trigger** > **On tap** > **Add action** をクリックし、**Action** を **Navigate to** に設定して次の画面(この例では Quiz 画面)を選択します。 2. **クイズからの条件ナビゲーション。** Quiz 画面を開き、Next ボタンを選択して **Conditional action** を持つ **On tap** トリガーを追加します。IF/ELSE ルールを設定します: - 変数ピッカーで **Elements** タブを開き、**Quiz** 画面を選択して `quiz.selectedOptionId` を選択します。 - **Equals** 演算子を使用して、いずれかのオプションの ID(この例では Rock オプション)と比較します。 - 比較が一致する場合、**IF** で **Navigate to** を実行して最初のパス画面を選択します。 - **ELSE** で **Navigate to** を実行して2番目のパス画面を選択します。 3. **各分岐パスからペイウォールへのスタティックナビゲーション。** 各パス画面でステップ1のパターンを繰り返し、ペイウォールを目的地として設定します。 ## 次のステップ \{#next-steps\} - [フローを保存して公開する](builder-save-publish)。 - [フローをプレースメントに追加](create-placement)して、ユーザーへの表示を開始します。 - オーディエンス別のフロー(フロー内での分岐ではなく)の場合は、オーディエンスセグメントを作成して、プレースメントページで異なるフローを割り当てます。 --- # File: migrate-to-flows --- --- title: "フローへの移行" description: "別々のオンボーディングとペイウォールをひとつのAdaptyフローにまとめる方法 — 変わること、そして古いバージョンのユーザーへの影響なくリリースする方法を説明します。" --- Adaptyでは、*フロー*はオンボーディングとペイウォールをひとつのプレースメントの背後にある単一のエンティティとして組み合わせたものです。フローは、現在それぞれ独立して構築・配信している個別のオンボーディングとペイウォールを置き換えます。 このガイドでは、フローに移行する際に何が変わるのか、そして古いバージョンのアプリを使用しているユーザーへの影響を最小限に抑えながら変更を展開する方法を説明します。 :::important フローは現在 iOS SDK v4 以降でサポートされています。他のプラットフォームやフレームワークへのサポートは近日公開予定です。 ::: ## フロー vs. オンボーディングとペイウォール \{#flows-vs-onboardings-and-paywalls\} 個別のオンボーディングとペイウォールを使う場合、2つのビルダーと2つのプレースメントを管理する必要があります。また、オンボーディングからペイウォールへのユーザーの受け渡しも自分のコードで行う必要があります。 フローはその両方をひとつの体験に置き換えます — イントロ画面、クイズ、購入画面をひとつのエディターで構築し、ひとつのプレースメントから配信できます。 以下の表で各オプションの違いを比較します: | | フロー | ペイウォールビルダーのペイウォール | オンボーディング | |---|---|---|---| | 複数画面 | あり | なし — 単一画面のみ | あり | | レンダリング | ネイティブ | ネイティブ | WebView | | プロダクトとプレースメント | プレースメントはひとつ;プロダクトを直接フローに追加 | プレースメントはひとつ;プロダクトを直接ペイウォールに追加 | プレースメントはひとつだが、プロダクト自体は持たない — 販売するには別途ペイウォールを作成し、独自のプレースメントから配信する必要がある | ## 移行すべきか? \{#should-you-migrate\} 既存のオンボーディングとペイウォールは引き続き動作し、Adaptyもそれらのサポートを続けます。ただし、新機能はスタンドアロンのオンボーディングビルダーやペイウォールビルダーではなく、フローに対して追加されるようになっています。 **長期的な視点で構築するなら、フローの方が優れた基盤です** — リリーススケジュールに合わせてタイミングよく移行してください。 ## 移行方法 \{#how-to-migrate\} 移行は4つのステップで構成されています。作業のほとんどは一度限りのSDKアップグレードです — フローの構築とプレビューはノーコードで行えます。 1. **[フローを構築する](#build-your-flow)**:ノーコードエディターでフローを作成します。開発者は不要です。 2. **[デバイスでプレビューする](#preview-on-device)**:Adaptyモバイルアプリを使って実機でフローを確認します。アプリのビルドは不要です。 3. **[フロー用の新しいプレースメントを作成する](#create-a-new-placement-for-your-flow)**:固有のIDを持つ新しいフロープレースメントを作成し、既存のプレースメントとの共存方法を決めます。 4. **[SDKをアップデートする](#update-the-sdk)**:iOS SDK v4にアップグレードし、プレースメントからフローをフェッチして、サンドボックス購入を確認します。これがメインの開発者タスクです。 ### フローを構築する \{#build-your-flow\} **Flows** ページで **Create flow** をクリックしてビルダーを起動し、オンボーディングとペイウォールをひとつの体験として再構築します。ビルダーの詳細については以下を参照してください: - **[フローのドキュメント](adapty-flow-builder)**:ビルダーの操作方法と作成できるものを説明します。 - **[よく使うフローのレシピ](flow-builder-recipes)**:最もよく使われる画面のステップバイステップガイドです。 - **AIに質問する**:詰まったときはドキュメントの各ページにあるチャットを使ってください。 :::note 既製のフローテンプレートからフローを作成したり、AIで生成したりする機能はまだ利用できません — どちらも近日公開予定です。現在は、すべての新しいフローがよく使われる複数の画面からスタートし、それをニーズに合わせて編集・スタイリングできます。 ::: ### デバイスでプレビューする \{#preview-on-device\} アプリに手を加えることなく、実機でフローをプレビューできます。App Store から [Adapty アプリ](https://apps.apple.com/us/app/adapty/id6739359219) をダウンロードしてください。次に、フロービルダーで **Test on device** をクリックし、ロケールを選択して、デバイスでQRコードをスキャンします。実際の画面、分岐、コピー、デザインが確認できます。 :::note プレビューモードでは、Adaptyはストア内のプロダクトにアクセスできないため、プレビューに表示される価格は実際のものではありません。実際の購入確認は後ほど、サンドボックスアカウントを使ったv4ビルドで行います — [SDKをアップデートする](#update-the-sdk)を参照してください。 ::: ### フロー用の新しいプレースメントを作成する \{#create-a-new-placement-for-your-flow\} プレースメントは、フロー、ペイウォール、オンボーディングのいずれか1種類のコンテンツのみを配信します。既存のオンボーディングまたはペイウォールのプレースメントをフロープレースメントに変換することはできません([プレースメントの種類](create-placement)を参照)。フローには独自の新しいプレースメントが必要です。 **新しいフロープレースメントには、まったく新しい固有のプレースメントIDを付与してください。** 既存のペイウォールまたはオンボーディングのプレースメントIDと同じものや、再利用したものは使用できません。 :::warning 移行期間中は古いプレースメントをそのままにしておく 古いバージョンのアプリには、オンボーディングとペイウォールのプレースメントIDがコンパイルされています。そのユーザーたちはオンボーディングとペイウォールのメソッドを引き続き呼び出し、アップデートするまで既存のオンボーディングとペイウォールを表示します。SDK v4の採用率が十分に高くなってから、古いプレースメントを廃止してください。 ::: すべての場所を一度にフローに移行する必要はありません。iOS SDK v4では、`getFlow` メソッドがフロープレースメントとペイウォールプレースメントの両方からフェッチするため、アプリはどこでも同じメソッドを呼び出せます。ペイウォールビルダーのペイウォールを使いたいプレースメントはそのままにして、それ以外にフローを使いましょう。 移行期間中、各プレースメントタイプは独自の指標を追跡します。古いバージョンと新しいバージョンのアプリが両方稼働している間、データは2セットのプレースメントに分かれます。古いオンボーディングとペイウォールのプレースメントが古いバージョンをカバーし、新しいフロープレースメントがSDK v4以降をカバーします。これらは別々のコホートとして比較し、ユーザーがアップデートするにつれてフロープレースメントのシェアが増加することを想定してください。 フローを使ったA/Bテストも引き続き実施できます:フロープレースメント上のフローバリアント間で[通常のA/Bテスト](ab-tests)を実行できます。クロスプレースメントのA/Bテストは現在ペイウォールのみ利用可能なため、フロープレースメント間では実行できません。新しいフローと古いペイウォールの比較は、単一のテストではなくコホート比較になります — それらは異なるプレースメントタイプに存在するためです。 ### SDKをアップデートする \{#update-the-sdk\} フロープレースメントの準備ができたら、アプリをそこに向けます。フローはAdapty SDK v4以降でのみレンダリングされます。SDKをアップグレードし、`getFlow(placementId:)` を使って新しいプレースメントからフローをフェッチします。具体的なアップグレード手順については [iOS SDK v4 移行ガイド](migration-to-ios-sdk-v4)を参照してください。 フローを組み込んだら、他の購入フローと同様に検証します:デバイスまたはシミュレーターで実行し、[サンドボックス購入](ios-test)を行って、プロダクト、購入処理、アクセスレベルがすべて正常に動作することを確認してください。 :::note フローはSDK v4以降でビルドされたアプリをインストールしたユーザーにのみ表示されます。古いバージョンのアプリを使っているユーザーは引き続き既存のオンボーディングとペイウォールを受け取ります。これが移行期間中に古いプレースメントを維持し続ける理由です。フローをまだサポートしていないプラットフォームでも同様です。 ::: --- # File: paywall-layout-and-products --- --- title: スクリーンとレイヤー description: "フロービルダーで各スクリーンのスクリーン管理と要素の階層を管理します。" --- フローは1つ以上のスクリーンで構成されています。各スクリーンはユーザーのジャーニーにおける1つのステップを表します。たとえば、ペイウォール、クイズ、プロダクト情報のスライドなどです。 各スクリーン上の要素はレイヤー階層として整理されています。 スクリーン、レイヤー、要素を管理するには、デフォルトの **Screens and Layers** ビューを開いてください。スクリーンの順序と各スクリーンのレイヤー構造が表示されます。 ## スクリーンの管理 \{#manage-screens\} 左パネルの上部セクションには、フロー内のすべてのスクリーンが一覧表示されます。各エントリには番号付きのラベルとサムネイルプレビューが表示されます。 * **スクリーンを選択する**: スクリーンエントリをクリックしてアクティブにします。ビジュアルエディターに選択したスクリーンが表示され、下のレイヤーセクションがそのレイヤー階層に更新されます。 * **スクリーンを追加する**: スクリーンセクション上部の Plus ボタンをクリックして、フローに新しい空のスクリーンを追加します。 * **スクリーンを並べ替える**: スクリーンエントリをドラッグ&ドロップして、フロー内の順序を変更します。 :::important フローに未使用の空のスクリーンがある場合、公開できません。公開前に下書きのスクリーンをすべて削除してください。 ::: ### スクリーンの操作 \{#screen-actions\} スクリーンエントリの三点アイコン Context をクリックすると、コンテキストメニューが開きます。 | 操作 | ショートカット | 説明 | |--------|----------|-------------| | **Play Animation** | | このスクリーンに設定されたアニメーションをプレビューする | | **Copy** | ⌘C / Ctrl+C | スクリーンをクリップボードにコピーする | | **Paste here** | ⌘V / Ctrl+V | 以前にコピーしたスクリーンを貼り付ける | | **Duplicate** | ⌘D / Ctrl+D | スクリーンのコピーを作成してフローに追加する | | **Rename** | | スクリーンの表示名を変更する | | **Delete** | ⌘⌫ / Ctrl+Del | フローからスクリーンを削除する | :::warning スクリーンを削除すると、そのスクリーンを指定していた [Navigate to Screen](onboarding-navigation-branching) アクションは**ターゲットを失います**が、アクション自体は**削除されません**。新しい遷移先を設定するか、アクションを削除してください。そうしないと、[フローのプレビューや公開](builder-save-publish#publish-a-flow)ができなくなります。 ::: ## スクリーン間の移動 \{#navigate-between-screens\} :::link メイン記事:[ナビゲーションとインタラクション](onboarding-navigation-branching) ::: リスト内のスクリーンの順序だけでは、ナビゲーションは決まりません。スクリーンを接続するには、要素のインタラクションを使用してください。ボタンを設定して、ユーザーを別のスクリーンに移動させます。 ## スクリーン設定 \{#screen-settings\} アクティブなスクリーンのプロパティと設定を表示するには、スクリーンプレビューの空白部分をクリックしてください。右パネルがスクリーン設定ビューに切り替わります。 ### システムUI \{#system-ui\} スクリーンがデバイスのハードウェアとどのように連携するかを制御します。 * **Safe area** は、ノッチやシステムバーからコンテンツを保護するパディングを追加します。 * **Status bar** は、システムのステータスバー(時刻、バッテリー、信号アイコン)の表示と非表示を切り替えます。 ### プログレスインジケーターへのスクリーンの含め方 \{#include-screen-in-progress-indicator\} フローに[プログレスインジケーター](builder-loaders-and-progress-bars#progress-indicators)要素を追加すると、Adaptyはすべてのスクリーンに表示します。 **Include screen in progress indicator** のチェックを外すと、特定のスクリーンからプログレスインジケーターが非表示になります。ウェルカムスクリーン、最終的なペイウォール、または進行状況として登録したくないステップに使用してください。 ### スクリーンレイアウト \{#screen-layout\} :::link 詳細記事:[要素の配置](manage-paywall-ui-elements) ::: **Layout** セクションでは、スクリーンが子要素をどのように配置するかを決定します。これらのプロパティは、コンテナ要素であれば何にでも使用できます。 * **Free**: 子要素が独立して配置されます。 * **Vertical**: 要素がフレックスボックスの列のように上から下へ並べられます。 * **Horizontal**: 要素がフレックスボックスの行のように左から右へ並べられます。 縦と横のレイアウトでは、間隔と配置も設定できます。 * **Alignment**: クロス軸に沿った要素の位置。 * **Gap**: 隣接する要素間のスペース。 * **Distribution**: 子要素の間および周囲へのスペースの配分。 #### RTLレイアウト \{#rtl-layout\} **Mirror for RTL** チェックボックスをオンにすると、右から左に読む書き方のシステムに合わせてレイアウトが反転します。水平コンテナ内の要素の順序が逆になります。 ### スクリーンの背景 \{#screen-background\} :::link メイン記事:[背景](paywall-head-picture) ::: **Fill** は、[スクリーンの背景](paywall-head-picture)を単色、グラデーション、画像、または動画に設定します。背景は、**Safe area** が有効になっている場合でも、ノッチやシステムバーの裏側を含むデバイスのビューポート全体を塗りつぶします。 #### 背景動画のループ再生 \{#loop-background-video\} **Loop** トグルを有効にすると、背景動画を連続ループで再生します。 #### カスタムメディアIDの割り当て \{#assign-a-custom-media-id\} [画像や動画と同様に](custom-media)、スクリーンの背景にカスタムメディアIDを割り当てて、SDKから参照することができます。 ### スクリーンの余白 \{#screen-spacing\} 各辺(上、右、下、左)のスクリーンパディングを調整します。 ### スクロール \{#scroll\} オーバーフローの動作を制御します。**Vertical scroll** を有効にすると、スクリーンコンテンツがビューポートの高さを超えたときにスクロールできるようになります。 ### 選択可能なグループ \{#selectable-groups\} :::link メイン記事:[選択可能な要素とグループ](flow-selectable-elements) ::: **Selectable groups** セクションには、現在のスクリーン上のすべての選択可能なグループが一覧表示されます。[クイズ](onboarding-quizzes)、[プロダクト](paywall-product-block)、[タブ](builder-tabs)、[トライアルトグル](builder-toggles)、または[カスタムの選択可能な要素](flow-selectable-elements#make-an-element-selectable)から作成されます。 グループエントリをクリックすると、名前の変更、タイプの変更、公開している変数の確認、または削除ができます。 ## レイヤーの管理 \{#manage-layers\} スクリーン上の各要素はレイヤーとして表されます。レイヤーセクションには、アクティブなスクリーン上の要素の順序が表示されます。 :::important フローのレイヤーは、グラフィックデザインソフトウェアのレイヤーのように重なりません。代わりに、スクリーンの個々のコンポーネントを表します。要素が重なるのは、[絶対配置または固定配置](manage-paywall-ui-elements)を使用している場合だけです。重ね順はレイヤーツリー内の位置ではなく、`z-index` プロパティによって決まります。 ::: ツリー構造は親子関係を反映しています。任意の親レイヤーの矢印をクリックすると、子要素を展開または折りたたむことができます。 レイヤーを直接作成することはできません。[要素を追加](builder-elements)ビューから追加したすべての要素は、ツリーに新しいレイヤーとして表示されます。 * **レイヤーを選択する**: レイヤーをクリックして選択します。ビジュアルエディターでキャンバス上の対応する要素がハイライトされ、右パネルにその[デザイン](builder-styling)と[インタラクション](onboarding-navigation-branching)プロパティが表示されます。 * **レイヤーを並べ替える**: ツリー内でレイヤーをドラッグ&ドロップして、親コンテナ内の順序を変更します。ツリー内の順序はスクリーン上の視覚的な順序と一致します。 * **レイヤーの表示・非表示を切り替える**: レイヤーにカーソルを合わせると、右側に目 Eye アイコンが表示されます。クリックするとレイヤーの表示・非表示が切り替わります。非表示のレイヤーはツリーに残りますが、ビジュアルエディターやデバイスには表示されません。実行時にロジックで表示を制御するには、[条件付き表示](onboarding-element-visibility)を使用してください。 * **すべてのレイヤーを折りたたむ**: レイヤーセクションの右上にある折りたたみ Collapse ボタンをクリックすると、ツリー全体が折りたたまれます。 ### レイヤーの操作 \{#layer-actions\} 三点アイコン Context をクリックすると、コンテキストメニューが開きます。 | 操作 | ショートカット | 説明 | |--------|----------|-------------| | **Copy** | ⌘C / Ctrl+C | レイヤーをクリップボードにコピーする | | **Paste here** | ⌘V / Ctrl+V | 以前にコピーしたレイヤーを子として貼り付ける | | **Duplicate** | ⌘D / Ctrl+D | 同じコンテナ内にレイヤーのコピーを作成する | | **Rename** | | レイヤーの表示名を変更する。デフォルトでは、レイヤーのコンテンツまたはコンポーネントタイプが名前として使用される | | **Delete** | ⌘⌫ / Ctrl+Del | レイヤーとそのすべての子を削除する | | **Wrap** | | レイヤーを新しいコンテナでラップする:**Wrap in Horizontal Container** または **Wrap in Vertical Container** | | **Unwrap / Ungroup** | | ラップしているコンテナを削除して、その子を1つ上のレベルに移動する | | **Move up** | ↑ | 親コンテナ内でレイヤーを1つ上の位置に移動する | | **Move down** | ↓ | 親コンテナ内でレイヤーを1つ下の位置に移動する | --- # File: paywall-product-block --- --- title: "購入を設定する" description: "フロービルダーで画面にプロダクトを割り当て、プロダクト要素を追加し、購入ボタンを設定します。" --- 画面上で購入を設定するには、購入ボタンを追加して **Purchase** アクションを設定します。このアクションは、特定のプロダクトを対象にすることも、画面上の Products 要素からユーザーが選択したプロダクトを対象にすることもできます。 ## プロダクトを追加する \{#add-products\} プロダクト要素は、キャンバス上にプロダクトを表示するビジュアルカードです。 プロダクト要素を追加するには: 1. キャンバスで、対象のスクリーンの **+** をクリックします。 2. **Products** を選択します。 3. レイアウトのプリセットを選択します: 縦リスト、横リスト、フィーチャーカルーセル、フィーチャーカード、バナーリスト、またはボトムシート。 4. 各プロダクトカードを選択し、**Design** パネルのドロップダウンでプロダクトを割り当てます。 :::important プロダクトが紐付けられていないプロダクト要素は、[プレビューと公開をブロックします](builder-save-publish#troubleshooting)。プロダクトを割り当てるか、要素を削除してください。 ::: :::note **Purchase** アクションをプロダクトカードの **On tap** インタラクションに直接紐付けることもできます。カードをタップすると購入がトリガーされ、別途購入ボタンを用意する必要がありません。 ::: :::important プロダクトグループを削除して新しいグループに置き換えた場合は、すべてのアクションと変数が新しいグループを参照しているか確認してください。削除済みのグループへの参照が残っていると、[プレビューや公開がブロックされます](builder-save-publish#troubleshooting)。 ::: ## 購入ボタンを追加する \{#add-a-purchase-button\} 購入ボタンは、ユーザーがタップしたときに **Purchase** アクションをトリガーします。 購入ボタンを追加するには: 1. キャンバス上で、画面の **+** をクリックします。 2. **Button** を選択し、ボタンのプリセットを選びます。 3. ボタンを選択した状態で、右パネルの **Interactions** タブを開きます。 4. **Add trigger** > **On tap** をクリックし、**Add action** をクリックします。 5. **Action** を **Purchase** に設定し、**Product** を以下のいずれかに設定します: - `products.selectedProduct`:画面上の Products 要素でユーザーが選択したプロダクトを購入します。 - 特定のプロダクト:画面上の選択内容に関わらず、常にそのプロダクトを購入します。 ### ボタンに価格を表示する \{#show-the-price-on-the-button\} 選択中のプロダクトの価格をボタンのラベルに挿入するには、変数を使います: 1. ボタンを選択した状態で、右パネルの **Design** タブを開きます。 2. **Content** フィールドで、価格を表示したい位置にカーソルを置きます。 3. 変数アイコンをクリックして `products.selectedProduct` を選択し、続けて `prod_price` 属性を選択します。完全な変数は `products.selectedProduct.prod_price` になります。 4. 変数の前後に固定テキストを追加します。例: `Subscribe for {prod_price}`。 ユーザーが別のプロダクトを選択するたびに、ラベルが自動的に更新されます。 ## 購入を復元する \{#restore-purchases\} ユーザーが以前の購入を復元できるようにするには、画面に復元ボタンまたはリンクを追加します。 購入を復元する要素を追加するには: 1. キャンバス上で、画面の **+** をクリックします。 2. **Button** を選択し、テキストリンクの場合は **Links**、スタイル付きボタンの場合は他のボタンタイプを選択します。 3. 要素を選択した状態で、右パネルの **Interactions** タブを開き、**Add trigger** をクリックします。 4. **On tap** を選択して、**Add action** をクリックします。 5. **Action** ドロップダウンから **Restore purchases** を選択します。 ## 選択されたプロダクトに基づいて追加要素を表示する \{#display-additional-elements-based-on-the-selected-product\} 画面にプロダクトが表示されている場合、ユーザーが選択したプロダクトに応じて他の要素を表示・非表示にできます。 条件付き表示を設定するには: 1. **Products** 要素でプロダクトカードを選択します。 2. 右パネルの **Interactions** タブを開き、**Add trigger** をクリックします。 3. **On tap** を選択し、**Add action** をクリックします。 4. **Action** ドロップダウンから **Show** または **Hide** を選択します。 5. そのプロダクトが選択されたときに表示または非表示にする要素を選択します。 ## フロー内のプロダクトを確認する \{#review-products-in-flow\} 左サイドバーの **Products** パネルには、フロー内の各画面に紐付いた既存プロダクトが表示されます。 各画面には2つのセクションがあります: - **Default** — 画面が読み込まれたときにあらかじめ選択されている1つのプロダクト。 - **Other** — 同じ画面で利用可能な追加プロダクト。 --- # File: manage-paywall-ui-elements --- --- title: "要素の配置" description: "レイアウト、ポジションモード、サイズ設定、スペーシングを使って画面上に要素を配置します。" --- フロービルダーはレスポンシブなレイアウトを作成します。要素を正確な座標にドラッグする必要はありません。代わりに、子要素を自動的に整列させる**コンテナ**の中に要素をネストします。 コンテナが要素の方向(縦または横)、配置、スペーシングを決定します。個々の要素はサイズやマージンを微調整できます。また、必要に応じて絶対配置や固定配置でフローから外れることもできます。 :::link 塗りつぶし、ボーダー、エフェクトなどの視覚的なプロパティについては、[要素のスタイリング](builder-styling)を参照してください。 ::: ## レイアウト \{#layout\} レイアウトは画面上に要素を配置するための主要なツールです。各コンテナは、方向、配置、スペーシングのルールに従って子要素を自動的に分配します。ビルダーで利用できるレイアウト要素は次のとおりです。 * **[縦コンテナ](builder-containers#containers)**:子要素を上から下に並べる * **[横コンテナ](builder-containers#containers)**:子要素を左から右に並べる * **[ディバイダー](builder-containers#dividers)**:要素間の視覚的な区切り線 * **[カルーセル](builder-containers#carousel)**:横スクロール可能なスライドセット * **[ボトムシート](builder-containers#bottom-sheet)**:ユーザーがボタンをタップすると追加コンテンツを表示するスライドオーバーレイパネル コンテナは画面の主要な構成要素です。コンテナ同士をネストして複雑なレイアウトを構築できます。各コンテナには、子要素の分配方法を制御する**レイアウト**セクションが右パネルにあります。 要素を新しいコンテナにグループ化するには、**Wrap**[レイヤーアクション](paywall-layout-and-products#layer-actions)を使用します。コンテナを削除して子要素を昇格させるには、**Unwrap**を使用します。 :::link 画面とレイヤー階層の詳細については、[スクリーンとレイヤー](paywall-layout-and-products)を参照してください。 ::: ### 方向 \{#direction\} * Free **フリー**:自動レイアウトなし。子要素は独立して配置されます(子要素が絶対配置を使用する場合に便利) * Vertical **縦**:子要素がカラムの行のように上から下に積み重なる * Horizontal **横**:子要素が行のアイテムのように左から右に並ぶ ### 要素の順序 \{#element-order\} 子要素は**レイヤー**パネルに表示される順序でレンダリングされます。縦コンテナでは、リストの先頭アイテムが画面の上部に表示されます。横コンテナでは、先頭アイテムが左側に表示されます。レイヤーパネルで要素をドラッグして並び替えるか、**Move Up**または**Move Down**[レイヤーアクション](paywall-layout-and-products#layer-actions)を使用します。 ### 配置 \{#alignment\} 配置グリッドは、コンテナのクロス軸に沿って子要素が配置される位置を制御します。縦コンテナでは、配置によって子要素の水平方向の位置(左、中央、右)が制御されます。横コンテナでは、垂直方向の位置(上、中央、下)が制御されます。 ### 分配 \{#distribution\} 分配は、メイン軸に沿って子要素間のスペースをどのように分割するかを決定します。 * **ギャップ** Gap(デフォルト):隣接する子要素間の固定ピクセル値 * **スペース ビトウィーン**:子要素がエッジに広がり、要素間に等間隔のギャップが入る * **スペース アラウンド**:各子要素の周囲に等間隔のスペースが入り、エッジには半分サイズのギャップが入る * **スペース イーブンリー**:すべての子要素の前後および間に等間隔のスペースが入る ### コンテンツのクリップ \{#clip-content\} コンテナの境界を超えてはみ出すコンテンツを視覚的にクリップします。これを無効にするとオーバーフローが許可されます(例:カードのエッジを意図的にはみ出すバッジなど)。 ## ポジション \{#position\} デフォルトでは、各要素の位置はコンテナのレイアウトによって自動的に決まります。**ポジション**トグルを使うと、通常のフローから外れて手動で位置を指定できます。 ### 相対(デフォルト) \{#relative-default\} 要素は通常のレイアウトフロー内にとどまります。位置は親コンテナのレイアウトルールによって自動的に決まり、自由にドラッグすることはできません。相対要素の周囲のスペースを調整するには**マージン**を使用します。 テキストブロック、画像、カード、ボタン、リストアイテムなど、ほぼすべてのコンテンツに相対配置を使用します。 ### 絶対 \{#absolute\} 要素が通常のフローから外れ、他のコンテンツの上にオーバーレイされます。隣接する要素のレイアウトには影響しなくなります。 **絶対**を選択すると、追加のコントロールが表示されます。 * **オフセットフィールド**(T、L、R、B):要素から親コンテナの各エッジまでの距離をピクセルで設定 * **アンカーグリッド**:3×3グリッドの点をクリックして、要素がアンカーされる親のコーナー、エッジ、または中央を選択 * **水平アンカー** Horizontal positioning(左 / 中央 / 右)と**垂直アンカー** Vertical positioning(上 / 中央 / 下):グリッドと同じアンカーポイントを制御するドロップダウン * **Z インデックス**:兄弟要素に対する[スタッキングオーダー](#stacking-order)を制御する数値フィールド。値が大きいほど上に表示される デコラティブオーバーレイ、バッジ、閉じるボタン、画像の上に配置するアイコンには絶対配置を使用します。 :::tip 絶対要素を親の全幅に伸ばすには、水平アンカーを**Left**に設定し、**Right**オフセットを0にします。要素が両方のエッジに固定されます。 ::: ### 固定 \{#fixed\} 要素は親コンテナを完全に無視し、デバイスのビューポートに固定されます。ユーザーがスクロールしても表示され続け、ページコンテンツがその下を動きます。 固定配置は絶対配置と同じコントロール(オフセット、アンカーグリッド、Zインデックス)を使用します。すべてのオフセットは親ではなく画面のエッジを基準にします。 下部のスティッキーボタン、フローティングナビゲーションバー、固定ヘッダーには固定配置を使用します。 ## サイズ設定 \{#sizing\} 各要素には**幅**と**高さ**のコントロールがあります。ドロップダウンをクリックしてサイズモードを選択します。 * **フィル**:要素が親の利用可能なスペースをすべて占めるように伸びる。表示されるピクセル値は計算結果です。 * **ハグ**:要素がコンテンツに合わせて縮む。表示されるピクセル値は計算結果です。 * **固定**:親やコンテンツのサイズに関わらず、指定した正確なピクセル値を使用する。絶対配置または固定配置の要素で唯一利用可能なモードです。 ## スペーシング \{#spacing\} 要素の各辺ごとにスペーシング値を個別に設定します。 * **マージン**:要素と隣接要素の間のスペース。値に関わらず、親コンテナの境界を超えて広がることはありません。 * **パディング**:要素の境界とそのコンテンツの間のスペース。 テキスト要素はマージンのみ持ちます。スクリーンはパディングのみ持ちます。コンテナや子コンテンツを持つその他の要素では両方が利用できます。 ## スタッキングオーダー \{#stacking-order\} 相対要素は互いに重なりません。各コンテナは子要素を順番に配置します。要素が**絶対**または**固定**配置で通常のフローから外れた場合にのみ重なりが発生します。 要素が重なる場合、**レイヤー**パネルで後に来る兄弟要素が前の要素の上にレンダリングされます。後の兄弟が相対配置で前の兄弟が絶対配置であっても同様です。 **絶対**および**固定**要素には、より細かい制御のための**Zインデックス**フィールドがあります。値が大きい方が上に表示されます。相対要素にはZインデックスがなく、レイヤーの順序のみでスタックが決まります。 要素の順序を変更するには、**Move up**および**Move down**[レイヤーアクション](paywall-layout-and-products#layer-actions)を使用します。 --- # File: builder-styling --- --- title: "エレメントのスタイリング" description: "エレメントの見た目(塗りつぶし、ボーダー、エフェクト、タイポグラフィ、状態、プロジェクト全体のスタイル)を設定します。" --- 右パネルの **Design** タブで、各エレメントの見た目を設定します。使用できるプロパティはエレメントの種類によって異なりますが、多くのエレメントは共通のスタイリングオプションを持っています。 ## サイズとスペース \{#size-and-space\} :::link メイン記事: [エレメントの配置](manage-paywall-ui-elements) ::: ### 表示 \{#visibility\} **Visibility** トグルは、エレメントを画面に表示するかどうかを制御します。 * Show **Show**(デフォルト): エレメントは常に表示されます。 * Conditional **Conditional**: 特定の条件が満たされた場合のみエレメントが表示されます。詳しくは[条件付き表示](onboarding-element-visibility)を参照してください。 * Hide **Hide**: エレメントは常に非表示になります。エレメントを削除せずに一時的にフローから除外したい場合に使用します。 ### サイズ指定 \{#sizing\} 各エレメントには **Width** と **Height** の設定があり、3つのモードから選択できます。 * **Fill**: 親要素の空きスペースをすべて占有するように伸長します * **Hug**: エレメントのコンテンツに合わせて縮小します * **Fixed**: 寸法に正確なピクセル値を設定します ### スペーシング \{#spacing\} **Spacing** セクションには、2つのレイヤーを持つボックスモデルが表示されます。 * **Margin**: エレメントと隣接要素との間のスペースです。値に関わらず、親コンテナの境界を超えて広がることはありません。 * **Padding**: エレメントのボーダーとコンテンツの間のスペースです。 各辺ごとに個別に値を設定できます。 :::note テキストエレメントにはマージンのみがあります。スクリーンにはパディングのみがあります。コンテナや子コンテンツを持つその他のエレメントでは、両方が使用できます。 ::: ## 塗りつぶし \{#fill\} **Fill** セクションはエレメントの背景を設定します。ソリッドカラー、グラデーション、画像、動画の4種類の塗りつぶしタイプが使用できます。 このプロパティを使用して、スクリーン全体のヒーロー画像・動画を設定することもできます。 * **ソリッドカラー** Solid color。カラーピッカーを使用するか、16進数値を入力するか、[プロジェクト全体のカラースタイル](#color-styles)を割り当てます。**opacity** を調整して背景を半透明にできます。 * **グラデーション** Gradient。2つ以上のカラーストップでグラデーション塗りつぶしを追加します。ストップをドラッグしてトランジションを調整し、グラデーションの角度を変えて方向を制御します。 * **画像** Image または **動画** Video。[画像・動画](custom-media)をエレメントの背景として設定します。 ## ボーダー \{#border\} ボーダーはデフォルトでオフになっています。右パネルの **Border** の横にある Plus をクリックして追加します。ボーダーを削除するには、**Border** 見出しの横にある Close をクリックします。 ボーダーが存在する場合、以下を設定できます。 * **Color**: カラーピッカーを使用するか、16進数値を入力するか、[プロジェクト全体のカラースタイル](#color-styles)を割り当てます。**opacity** を調整してボーダーを半透明にできます。 * **Width**: ボーダーの太さ(ピクセル単位)。 ## コーナー \{#corners\} **Corners** セクションはボーダー半径(角丸)を設定します。 * **Radius スライダー**: 4つすべてのコーナーに同じ半径を設定します * **コーナーごとの切り替え** Per Corner: 有効にすると、各コーナーに異なる半径を個別に設定できます ## エフェクト \{#effects\} **Effects** の横にあるプラスボタン Plus をクリックして、1つ以上のビジュアルエフェクトを追加します。 * **Drop shadow**: エレメントの背後に影を表示します * **Inner shadow**: エレメントの境界内に影を表示します * **Background blur**: 背景をぼかします * **Layer blur**: エレメントとその子要素をぼかします 同じエレメントに複数のエフェクトを重ねることができます。表示トグル Show で一時的にエフェクトを無効化できます。 ## アニメーション \{#animation\} **Animation** の横にある Plus ボタンをクリックして、アニメーションエフェクトを追加します。現在、利用できるアニメーションは **Pulse** のみです。エレメントがリズミカルに拡大・縮小して注目を集めます。 Pulse アニメーションは以下のパラメーターで設定できます。 | パラメーター | 説明 | |-----------|-------------| | Scale amount (%) | 元のサイズに対してエレメントがどれだけ拡大するか | | Duration (ms) | 1回のアニメーションサイクルの長さ | | Delay between loops (ms) | 繰り返しの間の一時停止 | | Shadow color | 点滅するシャドウエフェクトの色 | | Shadow size (px) | 点滅するシャドウのサイズ | ### アニメーションのプレビュー \{#preview-the-animation\} ビルダーはデフォルトで静止したスクリーンを表示します。アニメーションを確認するには、以下のいずれかの方法でオンにします。 - デバイスプレビューの上にある **Toggle animations** Toggle animations ボタンをクリックします。スクリーンのアニメーションのオン・オフを切り替え、オンにすると再度クリックするまでアニメーションが連続再生されます。このボタンは、アクティブなスクリーンに少なくとも1つのアニメーションが含まれている場合にのみ表示されます。 - スクリーンレイヤーの横にある三点アイコンからスクリーンの[コンテキストメニュー](paywall-layout-and-products#screen-actions)を開き、**Play Animation** を選択します。 ## 外観 \{#appearance\} * **Opacity**: 0%(透明)から100%(不透明)の範囲で設定します * **Rotation**: 度数値を入力してエレメントを回転させます ## タイポグラフィプロパティ(テキストエレメント) \{#typography-properties-text-elements\} テキストエレメントには以下のコントロールを含む **Typography** セクションが表示されます。 ### フォント \{#font\} :::link 関連記事: [カスタムフォント](using-custom-fonts-in-paywall-builder) ::: フォントドロップダウン Font select をクリックしてフォントピッカーを開きます。2つのタブがあります。 * **Styles**: プロジェクトに保存された[テキストスタイル](#text-styles)の一覧です。スタイルを選択すると、そのタイポグラフィ設定がすべて一度に適用されます。 * **Fonts**: 利用可能なすべてのフォントファミリーの一覧です。検索またはスクロールして必要なものを見つけてください。 ### サイズとウェイト \{#size-and-weight\} * **Weight**: ドロップダウンからフォントウェイトを選択します * **Size**: ドロップダウンからサイズを選択するか、カスタム値を入力します ### 色 \{#color\} カラースウォッチをクリックしてカラーピッカーを開きます。16進数値を入力するか、パレットを使用するか、[再利用可能なスタイル](#reusable-styles)から選択します。不透明度スライダーを調整してテキストを半透明にできます。 ### 揃え \{#alignment\} 2グループの揃えコントロールがあります。 * **水平**: 左揃え Align left、中央揃え Align center、右揃え Align right * **垂直**: 上揃え Align top、中央揃え Align middle、下揃え Align bottom ### 装飾 \{#decoration\} * **None** None: 装飾なし(デフォルト) * **Underline** Underline: テキストに下線を追加します * **Strikethrough** Strikethrough: テキストに取り消し線を追加します ### トランケーション \{#truncation\} トランケーションを有効にすると、**Max Lines** の設定を超えたテキストを切り捨てます。 複数の言語をサポートする場合に便利です。翻訳後の文字列が元の文字列より長くなっても、 トランケーションによってレイアウトが崩れるのを防ぎます。 :::note テキストエレメントを選択すると、キャンバス上でその上部に**インラインツールバー**も表示されます。このツールバーから、右パネルをスクロールせずにフォント、ウェイト、サイズ、揃えにすばやくアクセスできます。 ::: ## 状態別設定(インタラクティブエレメント) \{#state-specific-settings-interactive-elements\} インタラクティブエレメントは複数のビジュアル状態をサポートします。該当するエレメントを選択すると、右パネルに **States** セクションが表示されます。状態を切り替えて、それぞれに異なるビジュアルプロパティを設定します。 各状態では、塗りつぶし、ボーダー、タイポグラフィの色、不透明度など、あらゆるビジュアルプロパティを上書きできます。 ### セレクタブル状態 \{#selectable-states\} :::link メイン記事: [セレクタブルエレメント](flow-selectable-elements) ::: セレクタブルグループ(クイズの選択肢、プロダクト、タブ、トライアルトグル)に属するエレメントには、デフォルトで2つの状態があります。 * **Default**: エレメントの通常の外観 * **Selected**: ユーザーがこのオプションを選択したときの外観。塗りつぶし、ボーダーカラー、テキストカラーなどのプロパティを上書きして、アクティブな選択肢を強調表示します インタラクティブでないときのスタイルを設定するには、3番目の状態を手動で追加します。**States settings** Settings を開いて **Disabled state** を追加します。 **Disabled** 状態は条件によって決まります。選択した後、**Set conditions** set conditions をクリックして、エレメントが実行時に無効になる条件(例: 必須フィールドが空の場合など)を定義します。 ### インプット状態 \{#input-states\} 入力フィールドには追加の状態があります。 * **Default**: 通常の未フォーカス状態の外観 * **Active**: フィールドがフォーカスされ、入力可能な状態 * **Invalid**: 入力値がバリデーションに失敗した状態 * **Disabled**: フィールドがインタラクティブでない状態 ### その他の状態を持つエレメント \{#other-state-bearing-elements\} 一部のエレメントは、標準の **Default / Selected / Disabled** パターン以外で状態別スタイリングを公開しています。 - **[プログレスインジケーターのステップ](builder-loaders-and-progress-bars#step-states)** — ステップごとに3つの状態: **Completed**、**Current**、**Upcoming**。 - **[カルーセルのドット](builder-containers#dots)** — 2つのカラーバリアント: 非アクティブなドットの **Color** と現在のスライドのドットの **Active Color**。 ## 再利用可能なスタイル \{#reusable-styles\} 左サイドバーの **Styles** Styles パネルでは、フロー全体に適用される再利用可能なスタイルを定義できます。テキストスタイルとカラースタイルの2種類が使用できます。ダークモードのサポートを有効にするにはカラースタイルを使用する必要があります。 ### テキストスタイル \{#text-styles\} :::link メイン記事: [テキストコンテンツ](onboarding-text) ::: テキストスタイルには、フォントファミリー、ウェイト、サイズ、行の高さ、揃え、装飾などのタイポグラフィ設定一式が保存されます。すべてのフローテンプレートにはデフォルトのプリセットが含まれており、カスタムスタイルを作成することもできます。 テキストスタイルを作成するには: 1. **Styles** Styles パネルを開き、**Text** タブを選択します。 2. **Plus Create style** をクリックします。 3. 名前を入力し、タイポグラフィの設定を行います。 4. **Create** をクリックします。 テキストスタイルを適用するには、テキストエレメントを選択し、**Typography** セクションのフォントドロップダウンからスタイルを選択します。 ### カラースタイル \{#color-styles\} カラースタイルは、フロー全体で参照できる名前付きの色です。各カラースタイルには名前(「Primary text」や「Brand」など)、16進数値、および参照しているエレメント数を示す使用カウントがあります。 カラースタイルを作成するには: 1. **Styles** Styles パネルを開き、**Colors** タブを選択します。 2. **Plus Create style** をクリックします。 3. 名前を入力して色を選択します。 カラースタイルを更新すると、それを参照しているすべてのエレメントが自動的に更新されます。 ### ダークモード \{#dark-mode\} :::link メイン記事: [ダークモード](paywall-dark-mode) ::: 必要に応じて、各カラースタイルにライトモード Light mode とダークモード Dark mode の2つのバリアントを追加できます。SDK はデバイスの現在のカラースキームに基づいて自動的に適切なバリアントを適用します。 ビルダーでダークモードをプレビューするには、[下部ツールバー](builder-ui#view-controls-bottom-toolbar)にある **theme toggle** Dark mode を使用します。 --- # File: flow-selectable-elements --- --- title: "選択可能な要素とグループ" description: "要素を選択可能にし、グループに整理して、フロー全体の条件でその状態を活用する方法を解説します。" --- 選択可能な要素とは、ユーザーがタップして選択・解除できるフロー要素のことです。その状態を使って、フロー全体のナビゲーション、表示/非表示、その他のロジックを制御できます。できることは以下の通りです: - [デフォルトの選択可能な要素を使う](#default-selectable-elements) — クイズの選択肢、プロダクト、タブ、トライアルトグルは最初から選択可能 - [任意の要素を選択可能にする](#make-an-element-selectable) — 任意の要素を選択可能にして、グループに割り当てる - [グループを作成・管理する](#create-a-group) — 選択可能な要素を単一選択、複数選択、またはトグルグループに整理する - [条件で選択状態を使う](#use-selectable-state-in-conditions) — フロー内の任意の画面の条件からグループの値を参照する ## デフォルトの選択可能な要素 \{#default-selectable-elements\} 一部の要素タイプはデフォルトで選択可能です。自動作成されたグループにすでに属しており、追加設定は不要です: - **クイズの選択肢**:各クイズの回答はクイズグループ内の選択可能な要素です。[クイズ](onboarding-quizzes)を参照してください。 - **プロダクト**:プロダクトグループ内のプロダクトカード。[プロダクトブロック](paywall-product-block)を参照してください。 - **タブ**:タブグループ内のタブアイテム。[タブ](builder-tabs)を参照してください。 - **トライアルトグル**:グループに属し、選択状態を持つコンテナ。[トグル](builder-toggles)を参照してください。 ## 要素を選択可能にする \{#make-an-element-selectable\} 場合によっては、追加の要素を選択可能にしたいことがあります。たとえば、クイズグループ内の要素として機能する **Don't ask me again** チェックボックスを追加できます。 要素を選択可能にするには: 1. 画面上または **Layers** パネルで要素を選択します。 2. 右側の **Interactions** パネルに切り替えます。 3. **Turn into selectable element** を選択します。 4. **Group** ドロップダウンで、既存のグループを選択するか[新しいグループを作成](#create-a-group)します。 5. **Element ID** を設定します — グループ内でこの要素を一意に識別するIDです。 6. この要素をデフォルトで選択状態にしたい場合は、**Set as default in group** チェックボックスをオンにします。 ## グループを作成する \{#create-a-group\} グループは画面上の選択可能な要素を整理し、ユーザーが1つだけ選べるか、複数選べるか、トグルできるかといった選択の仕方を定義します。 グループを作成するには: 1. 要素を選択して[選択可能にします](#make-an-element-selectable)。 2. **Group** ドロップダウンで **Create group** を選択します。 3. **Group name** を入力します。 4. [グループタイプ](#group-types)を選択します。 これで、同じ画面上の他の選択可能な要素の **Group** ドロップダウンでこのグループが使えるようになります。 ## グループタイプ \{#group-types\} :::important ほとんどの[クイズプリセット](onboarding-quizzes)はデフォルトで **multi-choice** になっています。1つだけ回答できるようにするには、[グループタイプ](#manage-groups)を変更してください。 ::: - **Single choice**:グループ内で一度に選択できる要素は1つだけです。新しい要素を選択すると、前の選択が解除されます。 - **Multi-choice**:複数の要素を同時に選択できます。 - **Toggle**:各要素はタップするたびに選択・解除を切り替え、他の要素とは独立して動作します。 ## グループを管理する \{#manage-groups\} グループを表示・編集するには、**Screen settings** パネルを開いて **Selectable groups** セクションを確認します。現在の画面上のすべてのグループが一覧表示されます。 グループIDをクリックすると: - グループIDを変更できます - [グループタイプ](#group-types)を変更できます - グループ要素が条件でどのように参照されているかを確認できます ## 条件で選択状態を使う \{#use-selectable-state-in-conditions\} グループの選択状態は、フロー内の任意の画面の条件から参照できます — グループが定義されている画面だけでなく、どの画面からでも参照可能です。たとえば:`IF quiz.photo is selected, THEN navigate to the Photo screen` のように使います。 :::important グループ内のすべての要素は同じ画面上に配置する必要があります。異なる画面の要素を1つのグループに追加することはできません。ただし、グループの値はフロー内の任意の画面の条件から参照できます。 ::: 選択状態は以下の場面で使えます: - **[条件付きアクション](onboarding-actions#conditional-actions)**:選択された要素に基づいて、ユーザーを異なる画面にルーティングしたり、異なるアクションをトリガーしたりします。 - **[動的ナビゲーション](onboarding-navigation-branching)**:クイズの回答、トグルの状態、その他の選択に基づいてフローを分岐させます。 - **[条件付き表示](onboarding-element-visibility)**:前の画面でユーザーが選択した内容に基づいて要素を表示または非表示にします。 --- # File: builder-element-states --- --- title: "要素のステート" description: "ステートごとに要素をスタイリングし、条件を使って実行時に要素を無効化します。" --- インタラクティブなフロー要素は、ユーザーのアクションに応じて見た目が変わります。たとえば、タップしたクイズの選択肢は**選択済み**になり、フォーカスされた入力フィールドは**アクティブ**になります。条件によって変わるステートもあります。たとえば、ボタンを**無効化**することができます。各ステートを個別にスタイル設定することで、アプリのコードを書かずにユーザーへの視覚的なフィードバックを実現できます。 <div style={{ maxWidth: '560px', margin: '0 auto 2rem', position: 'relative', aspectRatio: '16/9', width: '100%' }}> <iframe style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%' }} src="https://www.youtube.com/embed/gdsNfHpKAqQ?si=VY5mqZgH1j0RB6fE" title="YouTube video player" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerPolicy="strict-origin-when-cross-origin" allowFullScreen /> </div> ## 要素の種類別の利用可能な状態 \{#available-states-by-element-kind\} | 要素の種類 | 組み込み状態 | 追加可能な状態 | |---|---|---| | [選択可能な要素](#selectable-element-states) | **Default**、**Selected** | **Disabled** | | [入力](#input-states) | **Default**、**Active**、**Invalid** | **Disabled** | | [タップ操作を持つ任意の要素](#condition-driven-disabled-state) — ボタン、画像、アイコン、スタックなど | **Default** | **Disabled** | | [プログレスインジケーターのステップ](#step-states-for-progress-indicators) | **Completed**、**Current**、**Upcoming** | — | **Addable** ステートはデフォルトでは表示されません — **States settings** Settings を開いて追加してください。これらは [**条件駆動型**](#condition-driven-disabled-state) です: どのタイミングで有効化するかを自分で定義します。 ## ステートのスタイル設定方法 \{#how-to-style-a-state\} 1. 要素を選択します。右パネルの **States** セクションに、その要素が対応するステートが一覧表示されます。 2. **States** セクションで、対象のステートを有効にします。必要に応じて[条件ベースの Disabled ステート](#condition-driven-disabled-state)を追加します。 3. フィル、ボーダー、タイポグラフィ、テキストコンテンツなど、任意のプロパティを変更します。変更はそのステートにのみ適用されます。 ネストされた要素は、親要素とともにステートフルになります。子要素のカラー、レイアウト、テキストコンテンツなど、あらゆる変更は親要素のアクティブなステートにスコープされます。 4. ビルダーは実行時に一致するスタイルを適用します。 :::tip ステートは、テキスト要素の見た目だけでなく、*内容*も変更できます。ビルダーはテキストコンテンツをフィルやボーダー幅と同じカテゴリのプロパティとして扱います。 ::: ## 選択可能な要素のステート \{#selectable-element-states\} クイズの選択肢、プロダクト、タブ、トライアルトグル、そして[カスタム選択可能要素](flow-selectable-elements#make-an-element-selectable)など、選択可能な要素にはデフォルトで2つのステートが用意されています。 - **Default**:要素の通常時の外観。 - **Selected**:ユーザーが要素をタップしたときに適用されます。ユーザーが選択を解除すると、ビルダーはDefaultに戻ります。 単一選択グループでは、ある要素を選択すると他の要素の選択が解除されます。複数選択グループでは、複数の要素を同時に選択できます。トグルは独立しており、一つを選択しても他の要素には影響しません。詳しくは[グループタイプ](flow-selectable-elements#group-types)を参照してください。 :::tip 複数の要素(クイズの選択肢など)に同じ状態のスタイルを適用したい場合は、まず1つの要素にスタイルを設定してから複製してください。状態のスタイルは兄弟要素間で引き継がれないため、現時点では複製がその回避策となります。 ::: ## 入力の状態 \{#input-states\} - **デフォルト**: 入力欄の通常時の外観。 - **アクティブ**: 入力欄にフォーカスが当たっている間に適用される。 - **無効(Invalid)**: 入力内容がバリデーションに失敗したときに適用される。たとえば、メールアドレス欄に `@` が含まれていない場合など。詳しくは[入力のバリデーション](builder-inputs-and-forms#input-validation)を参照。 - **無効化(Disabled)**: 入力欄が操作できない状態。手動でこの状態を追加する。[条件に基づく Disabled 状態](#condition-driven-disabled-state)を参照。 各状態のスタイル設定は、選択可能な要素と同じ方法で行う。対象の状態をアクティブにしてから、プロパティを変更する。 ## 条件によるDisabledステート \{#condition-driven-disabled-state\} Disabledステートは、ユーザーが要素を操作できないようにします。Default・Selected・Active・Invalidとは異なり、Disabledステートは自動的に有効になりません — ユーザーが定義したトリガー条件が必要です。 Disabledは以下で使用できます: - **入力フィールド**: テキスト、メール、パスワード、数値、電話番号、日付・時刻など、あらゆる[入力フィールド](builder-inputs-and-forms)。 - **選択可能な要素**: クイズの選択肢、プロダクト、タブ、トライアルトグル、および任意の[カスタム選択可能要素](flow-selectable-elements#make-an-element-selectable)。 - **タップ操作のある要素**: ナビゲーションアクションを起動するボタン、画像、アイコンなど。 ### Disabled ステートを追加する \{#add-the-disabled-state\} Disabled ステートを追加して設定するには: 1. 対象の要素を選択します。 2. **States** セクションで、**Settings** Settings をクリックします。 3. **Add Disabled state** を選択します。Disabled ステートが **States** セクションに表示されます。 4. 新しい Disabled ステートの横にある **Edit conditional state** Edit conditional state をクリックします。 5. 条件を追加します。入力が検証をパスしない限り **submit** ボタンを無効にしたい場合は、入力の `isValid` 変数を `false` と比較します。 6. Disabled ステートに制限を視覚的に伝えるスタイルを設定します(例:不透明度を下げるなど)。 { } Adapty SDKは実行時に条件を評価し、必要に応じてDisabled状態を適用します。アプリのコードは不要です。 ## プログレスインジケーターのステップ状態 \{#step-states-for-progress-indicators\} :::link メイン記事:[プログレスインジケーター](builder-loaders-and-progress-bars#step-states) ::: プログレスインジケーターは、オンボーディングフローのどこまで進んだかをユーザーに示します。各ステップには3つの状態があります: - **完了(Completed)**:ユーザーがすでに通過したステップ。 - **現在(Current)**:ユーザーが現在いるステップ。 - **未到達(Upcoming)**:まだ到達していないステップ。 --- # File: builder-containers --- --- title: "レイアウト要素:コンテナ、カルーセル、ボトムシート" description: "フロービルダーで要素をコンテナ、カルーセル、ボトムシートにグループ化する方法を説明します。" --- レイアウト要素は、他の要素をグループ化してスクリーン上の配置を制御します。 フロービルダーには4種類のレイアウト要素があります: - **コンテナ**:子要素を縦または横の軸に沿って並べる - **カルーセル**:一度に1枚のスライドを表示するスワイプ可能なコンテナ - **ボトムシート**:画面の下から上にスライドし、背後のコンテンツの上に重なって表示されるパネル - **ディバイダー**:行または列を区切る細い線 :::link **タブ**もこのカテゴリに含まれますが、別の記事で説明しています。詳細は [タブ](builder-tabs) をご覧ください。 ::: ## コンテナ \{#containers\} :::link メイン記事:[要素の配置](manage-paywall-ui-elements) ::: コンテナは要素を縦または横にグループ化します。**縦コンテナ**は要素を行として並べ、**横コンテナ**は列として並べます。 :::tip コンテナを入れ子にすることで、より複雑なレイアウトを構成できます。 ::: ### コンテナの方向を変更する \{#change-container-direction\} コンテナの方向は固定ではありません。右パネルの **Layout** セクションで **Vertical**、**Horizontal**、**Free** をいつでも切り替えられます。コンテナを削除して作り直す必要はありません。 同じ **Layout** セクションで、スペーシング、アライメント、配置を設定できます。子要素は **Layers** パネルに表示される順に描画されます。ドラッグして並び替えましょう。 ### ラップとアンラップ \{#wrap-and-unwrap\} 既存の要素をコンテナに変換するには、要素を選択して **Wrap** [レイヤーアクション](paywall-layout-and-products#layer-actions)を使います。**Layers** パネルから新しいコンテナに追加の要素をドラッグして入れられます。スタックを削除して子要素を1つ上のレベルに昇格させるには、**Unwrap** を使います。 ## カルーセル \{#carousel\} **カルーセル**は、一度に1枚のスライドを表示するスワイプ可能なコンテナです。ユーザーが横にスワイプすると次のスライドが表示され、タイマーによる自動進行も設定できます。 カルーセルには複数の **Slide** レイヤーが含まれます。スライドがアクティブになると、そのレイヤー上の要素が画面に表示されます。 タブと異なり、カルーセルのアクティブなスライドは[選択可能グループ](flow-selectable-elements)として公開されません。スライドは条件や動的テキストから参照できません。ビジュアルのローテーションにはカルーセルを使い、ユーザーによる分岐にはタブを使ってください。 ### アクティブなスライドを変更する \{#change-active-slide\} カルーセルを選択すると、ビルダーに **Slide** ドロップダウンと **+ Add Slide** ボタンを含むポップアップコントロールバーが表示されます。 - **+ Add Slide** をクリックして新しい空のスライドを追加できます。 - **Slide** ドロップダウンでキャンバス上のアクティブスライドを切り替えるか、**Layers** パネルで対応するスライドレイヤーをクリックします。 スライドの順序を変更するには、Layers パネル内のカルーセル内でドラッグします。 {/* TODO: on-device GIF */} ### プロパティ \{#properties\} #### 自動スクロール \{#auto-scroll\} 自動スクロールは、ユーザーがスワイプしなくてもスライドを自動的に切り替える機能です。 動作は2つのタイミング設定で制御します: - **Delay** — 各スライドが表示される時間(ミリ秒)。 - **Duration** — スライド間のトランジションにかかる時間(ミリ秒)。 #### カルーセルのサイズ設定 \{#carousel-sizing\} カルーセル自体のサイズと隣接するスライド間のスペーシングを専用のコントロールで設定します。異なるコンテンツ量のスライドをスワイプしてもレイアウトがずれないよう、**Height** は **Fixed** に設定することをおすすめします。 #### スライドのサイズ設定 \{#slide-sizing\} スライドごとの **Width** と **Height** を設定します。デフォルトは Fill で、各スライドがカルーセルの寸法に追従します。固定幅を設定すると、隣接するスライドが一部見えるピーク効果を作れます。 #### ドット \{#dots\} カルーセル下部のページインジケーターです。スライドの総数と現在表示中のスライドをユーザーに伝えます。 **Show dots** トグルをオフにするとスライドインジケーターを非表示にできます。ドットが表示されている場合、以下のプロパティで見た目を調整できます: - **Color** — 非アクティブなドットの塗りつぶし色。 - **Active Color** — 現在表示中のスライドのドットの塗りつぶし色。 - **Size** — 各ドットの直径(ピクセル)。 - **Gap** — 隣接するドット間のスペーシング。 - **Padding** — ドット行とその上のカルーセルコンテンツとの間のスペース。 ## ボトムシート \{#bottom-sheet\} :::link ウォークスルー:[ボトムシートですべてのプランを表示する](show-plans-bottom-sheet) ::: **ボトムシート**は、画面の下から上にスライドして背後のコンテンツの上に重なって表示されるレイアウトパネルです。 シートは常に背後のコンテンツをぼかします。このぼかしはオフにできません。画面読み込み時ではなく、**Show all plans** リンクなどのタップ操作をトリガーにして表示してください。 ### 構造 \{#structure\} ボトムシートには2つのトップレベルレイヤーが含まれます: - **Heading** — シート上部のコンテナ。**Title** テキストレイヤーと **Close button** Close が事前に配置されています。必要に応じて編集または削除できます。 - **Content** — メインコンテナ。プロダクト、ボタン、リンク、その他の要素を配置できます。 {/* TODO: on-device GIF */} ### 初期表示 \{#initial-visibility\} デフォルトでは、ボトムシートは画面が描画されると同時に表示されます。必要なときだけ開くようにするには: 1. **シートのコンテンツを先に構築する** — 非表示レイヤーは編集できないため、コンテンツを入れ終わるまでシートを表示したままにする必要があります。 2. **Layers** パネルでボトムシートを選択します。 3. **Visibility** を **Hide** Hide に設定します。 シートはレイヤーツリーに残りますが、画面への描画は停止します。 ### ボトムシートのトリガー設定 \{#triggering-the-bottom-sheet\} 非表示のボトムシートを開くには、別の要素に **Show** アクションを設定します: 1. トリガーとなる要素(ボタンやテキストリンクなど)を選択します。 2. 右パネルの **Interactions** タブを開きます。 3. **Add trigger** > **On tap** をクリックし、**Add action** をクリックします。 4. **Action** を **Show** に設定し、ドロップダウンからボトムシートを選択します。 ## ディバイダー \{#dividers\} **水平ディバイダー**と**垂直ディバイダー**は、コンテンツを区切る細い線です。行を分割するには水平ディバイダーを、横コンテナ内の列を分割するには垂直ディバイダーを使います。右パネルで太さ、色、長さを調整できます。 --- # File: using-custom-fonts-in-flow-builder --- --- title: "フローBuilderでのカスタムフォント" description: "フローBuilderでカスタムフォントをアップロードして使用する方法を説明します。" --- フローを作成する際、アプリの他の部分に合わせてカスタムフォントを使用したい場合があります。カスタムフォントを追加してフローで使用する方法を説明します。 :::tip フローのデザインを始める前に、**Styles** パネルで[フォントを設定](onboarding-text)しておきましょう。こうすることで、変更がグローバルに反映されます。 ::: ## 組み込みフォント \{#built-in-fonts\} Builderでフローを作成すると、Adaptyはデフォルトでシステムフォントを使用します。通常、iOSではSF Pro、AndroidではRobotoになりますが、デバイスによって異なる場合があります。また、Arial、Times New Roman、Courier New、Georgia、Helveticaなどよく使われるフォントも選択できます。これらのフォントにはいくつかのスタイルオプションが用意されています。 これらのフォントはAdapty SDKの一部としては提供されておらず、プレビュー目的のみで使用されます。すべてのデバイスで完全に動作することを保証するものではありませんが、テストの結果、ほとんどのデバイスで特別な対応なしに認識されることが確認されています。また、[iOSでデフォルトで使用できるフォントを確認する](https://developer.apple.com/fonts/system-fonts/)こともできます。 ## カスタムフォントの追加 \{#add-a-custom-font\} デフォルトで提供されているフォント以外が必要な場合は、カスタムフォントを追加できます。 カスタムフォントを追加するには: 1. フォントドロップダウンのいずれかで **Upload new font** を選択します。 2. **Add custom font** ウィンドウで、以下のフィールドを入力します: - **Font name in Builder**:フォントの表示名を入力します。この名前はBuilder全体のフォントドロップダウンに表示されます。 - **iOS font name**:フォントのPostScript名を入力します。Font Book → PostScript nameで確認するか、[`UIFont` API](https://developer.apple.com/documentation/uikit/uifont)を使って調べることができます。 - **Android font name**:`res/font/` のファイル名を入力します。小文字、数字、アンダースコアのみ使用できます。 - **Font file**:フォントファイルをドラッグ&ドロップするか、**Select files** をクリックします。対応フォーマット:`.ttf`、`.otf`、`.woff`、`.woff2`。 3. **Save font** をクリックします。 :::warning アップロードしたフォントファイルはデバイスには送信されず、プレビューのみに使用されます。SDKはペイウォールのレンダリング時に使用するフォントを参照する文字列のみを受け取ります。そのため、同じフォントファイルをアプリのバンドルに含め、各プラットフォーム固有の正しいフォント名を指定する必要があります。それほど時間はかかりません。 ::: フォントファイルをAdaptyにアップロードすることで、そのフォントをアプリで使用する権利を有していることを確認したものとみなされます。 ## フォントファイルをアプリのバンドルに追加する \{#add-the-font-files-to-your-apps-bundle\} すでにアプリの別の場所でカスタムフォントを使用している場合は、同じ方法でペイウォール用のフォントを追加するだけです。まだ使用していない場合は、フォントファイルをアプリのプロジェクトとバンドルに含めてください。手順は以下をご覧ください: - iOS:[Appleの公式ドキュメント](https://developer.apple.com/documentation/uikit/adding-a-custom-font-to-your-app) - Android:[Androidの公式ドキュメント](https://developer.android.com/develop/ui/views/text-and-emoji/fonts-in-xml) :::important フォントバンドルをダウンロードすると、アーカイブにすべてのフォントバリエーションが含まれています。アプリのサイズを最小限に抑えるために、ペイウォールで実際に使用するフォントファイルのみをアプリのバンドルに追加してください。たとえば、ペイウォールで `OpenSans-Regular.ttf` のみを使用している場合、`OpenSans-Bold.ttf` はアプリのバンドルに含めないでください。 ::: --- # File: paywall-head-picture --- --- title: "背景" description: "フローBuilder でスクリーンを単色、グラデーション、画像、または動画の背景で塗りつぶします。" --- [**Screen settings**](paywall-layout-and-products#screen-settings) の **Fill** パネルから、任意のスクリーンに背景を設定できます。単色、グラデーション、画像、動画の4種類の背景タイプから選べます。 ## 画像 \{#image\} `.JPG`、`.PNG`、`.GIF`、`.WEBP` ファイルを最大 20 MB までアップロードできます。画像は背景全体を覆うようにスケーリングされます。 :::note 背景画像と動画は、**Safe area** が有効になっている場合でも、ノッチやシステムバーの裏側を含むビューポート全体に広がります。端のコンテンツが切れないよう、重要なコンテンツは端から離して配置してください。 ::: アプリのコードから実行時に背景画像を差し替えるには、[カスタムメディア ID](custom-media#custom-media-id) を有効にしてください。 ## 動画 \{#video\} `.MP4` または `.WEBM` ファイルを最大 50 MB までアップロードできます。プレビューは静止フレームで表示されますが、実機では実行時に動画が再生されます。 **Loop** を切り替えると、動画を繰り返し再生できます。 実行時に背景動画を差し替えるには、[カスタムメディア ID](custom-media#custom-media-id) を有効にしてください。 ## 単色 \{#solid-color\} 16進数の値を入力し、不透明度を 0〜100% で設定します。スウォッチから保存済みの[カラースタイル](builder-styling)を選ぶと、ブランドカラーを適用できます — 背景はライトテーマとダークテーマに自動的に追従します。 ## グラデーション \{#gradient\} 複数のストップを持つ線形グラデーションを作成できます。 - **Direction** — グラデーションの角度を 0〜360° で回転します。 - **Stops** — バー上をドラッグして位置を調整します。ストップをクリックすると、16進数の値と不透明度を編集できます。 --- # File: custom-media --- --- title: "画像、動画、アイコン" description: "フロービルダーの画面に画像・動画・アイコン要素を追加し、カスタムメディアIDでランタイムにメディアを切り替える方法を説明します。" --- フロービルダーの **Media** カテゴリには、Image・Video・Icon の3種類のメディア要素があります。 ## 画像 \{#image\} `.JPG`、`.PNG`、`.GIF` ファイルを最大 20 MB までアップロードできます。 - **Aspect** — 画像をコンテナに合わせる方法を設定します: - **Fit** — 画像をトリミングせずにコンテナ内に収まるようにスケーリングします。 - **Fill** — 画像をコンテナに合わせて引き伸ばします。 - **Cover** — 必要に応じてトリミングしながら、コンテナ全体を覆うようにスケーリングします。デフォルト値です。 - **Use custom media ID** — 後述の[カスタムメディアID](#custom-media-id)を参照してください。 ## 動画 \{#video\} `.MP4` または `.WEBM` ファイルを最大 50 MB までアップロードできます。 - **Aspect** — Fit、Fill、Cover のいずれかを選択します。デフォルトは Fill です。 - **Loop** — 動画を連続で再生します。デフォルトでオンです。 - **Use custom media ID** — 後述の[カスタムメディアID](#custom-media-id)を参照してください。 動画はエディターのプレビューでは再生されません。キャンバスには静止フレームが表示されます。デバイス上でのランタイム実行時は、デフォルトでミュート状態で再生されます。Loop がオンの場合、無限にループ再生されます。 ### 動画終了時にアクションをトリガーする \{#trigger-an-action-when-the-video-ends\} :::link メイン記事:[アクション](onboarding-actions) ::: Video 要素は、動画が末尾に達したときに発火する **On playback finished** トリガーをサポートしています。**Interactions** パネルで設定して、別の画面へ遷移したり、CTAを表示したり、その他のアクションを実行できます。 ## アイコン \{#icon\} バンドルされている [Tabler Icons](https://tabler.io/icons) ライブラリから、2種類のビジュアルスタイルで数千のアイコンを選択できます: - **Stroke** — アウトラインのみ。 - **Filled** — 塗りつぶし。 ピッカーでキーワード検索してアイコンを探せます。アイコンの色は **Color** ピッカーで設定します。保存済みの[カラースタイル](builder-styling)を選択するか、カスタムカラーを設定してください。 ## カスタムメディアID \{#custom-media-id\} :::important 画像や動画の[背景](paywall-head-picture)にもカスタムメディアIDを設定できます。 ::: 画像または動画要素にカスタムメディアIDを設定しておくと、アプリのコードからランタイムで差し替えることができます。たとえばユーザーが選択したアバターを表示するなど、[パーソナライズされたビジュアル](get-pb-paywalls#customize-assets)に活用してください。 フロービルダーでアップロードしたメディアはフォールバックとして機能します。ランタイム時にコードからそのIDのメディアが提供されない場合、フォールバックが表示されます。 Image または Video 要素でカスタムメディアIDを有効にするには: 1. アップロードエリアの下にある **Use custom media ID** チェックボックスを選択します。 2. メディアIDを入力します。 3. フォールバック用の画像または動画をアップロードします。 アプリのコードでIDを使ってメディアを取得する方法は、[Customize assets](get-pb-paywalls#customize-assets) のSDK APIをご参照ください。 --- # File: paywall-buttons --- --- title: "フローbuilder内のボタン" description: "フローbuilderでアクションボタンを追加・設定します。" --- ボタンはフローbuilder内でユーザーのタップに反応するインタラクティブな要素です。次の用途に使用できます: - プロダクトに紐付いてトランザクションを自動処理する購入用CTA - ナビゲーション — ユーザーを画面間で移動させる(次へ、戻る、閉じる、スキップ) - ユーティリティリンク — 購入の復元、利用規約、プライバシーポリシー :::info このセクションでは、Adapty SDK バージョン4.0以上で動作する新しいフローbuilderについて説明します。 ::: ## ボタンを追加する \{#add-buttons\} ボタンを追加するには: 1. **+** をクリックして **Button** を選択します。 2. ボタンの種類を選択します。 <img src="/assets/shared/img/button-type.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. 購入ボタン、リンク、閉じるボタンにはあらかじめアクションが設定されています。リンクの場合は[ユーザーの遷移先URLを設定](#links)してください。その他のボタンタイプの場合は、**Interactions** パネルに移動し、**Button triggers** セクションでボタンが実行する[アクション](onboarding-actions)を設定します。 <img src="/assets/shared/img/button-action.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **Design** パネルで[ボタンのデザイン](manage-paywall-ui-elements)を設定します。 ## ボタンの種類 \{#button-types\} ### 購入ボタン \{#purchase-buttons\} :::link 購入ボタンを機能させるには、プロダクトを画面にバインドし、**Products** 要素を追加してください。[ガイド](paywall-product-block)をご覧ください。 ::: 購入ボタンは、ユーザーが画面上で選択しているプロダクトのアプリ内課金を開始します。SDKがトランザクションを自動的に処理するため、アプリのコードで購入処理を実装する必要はありません。 購入ボタンを追加するには: 1. **+** をクリックして **Button** を選択し、ボタンのプリセットを選びます。 2. ボタンを選択した状態で、右パネルの **Interactions** タブを開きます。 3. **Add trigger** > **On tap** をクリックし、**Add action** をクリックします。 4. **Action** を **Purchase**、**Product** を `products.selectedProduct` に設定します。`products.selectedProduct` 変数は常に画面で現在選択されているプロダクトに解決されます。 :::tip 購入ボタンにアニメーションを付けて注目を集めることができます。ペイウォールビルダーでは現在 **Pulse** アニメーションタイプに対応しています。 アニメーションのスタイルは **Design** パネルで設定してください。 ::: <img src="/assets/shared/img/purchase-button.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### リンク \{#links\} :::important **Terms of Use** ボタンと **Privacy Policy** ボタンには **Open URL** アクションが組み込まれています。そこに遷移先URLを設定してください。Open URL が空の場合や[インラインリンク](onboarding-text#inline-link)が空の場合、プレビューおよび公開がブロックされます。 ::: 一部のストア要件に準拠するため、以下のリンクを追加できます: - 利用規約 - プライバシーポリシー - 購入の復元 リンクを追加するには: 1. **+** をクリックして **Button > Links** を選択します。これにより、購入の復元またはURLを開くといったあらかじめ定義されたアクションを持つインラインボタンの行が追加されます。含まれているボタンがすべて必要でない場合は、レイヤーパネルで不要なものを削除してください。 <img src="/assets/shared/img/add-links.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '500px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. 次に、ボタンのアクションを設定します: - **Restore purchases** ボタンはすでに購入の復元を処理します。 - 残りの各リンクについて: 1. ボタンをクリックして選択し、右側の **Interactions** タブに切り替えます。 2. フィールドにURLを貼り付けます。 3. デフォルトでは、シームレスなユーザー体験のためにURLはアプリ内ブラウザで開きます。外部ブラウザでユーザーを遷移させたい場合は、**Open in external browser** チェックボックスを選択してください。 <img src="/assets/shared/img/pb-links.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### フローを閉じる \{#close-flow\} **Close** ボタンはフローを自動的に閉じます。 閉じるボタンを追加するには、**+** をクリックして **Button > Close flow** を選択します。 <img src="/assets/shared/img/close-flow.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '500px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> :::tip **Absolute** ポジションを使用すると、閉じるボタンを画面の角に配置できます。 ::: [アクション](onboarding-actions)を使用して、他のボタンもフローを閉じるように設定できます。 ### カスタムボタン \{#custom-buttons\} 追加できるすべてのボタンは、タップ時に任意のアクションを実行するように設定できます: - 次の画面へ移動する - アラートを表示する - [変数](onboarding-variables)を設定する - [画面要素の表示・非表示を切り替える](onboarding-element-visibility) - URLを開く - 購入を復元する - 条件付きアクションを実行する --- # File: builder-tabs --- --- title: "タブ" description: "フロー内でコンテンツパネルを切り替えるタブナビゲーションを追加します。" --- **タブ**は、画面のセクションを切り替え可能なコンテンツパネルに分割します。ユーザーがタブヘッダーをタップすると、その下のパネルが対応する内容に切り替わります。 {/* TODO: on-device GIF */} ## タブの追加・削除・選択 \{#add-remove-and-select-tabs\} 各タブは2つのパーツで構成されています。 - **タブヘッダー** — クリックできるラベル(Tab 1、Tab 2 など)。 - **タブコンテンツ** — タブごとに1つのコンテナ。コンテンツコンテナに配置したものが、そのタブが選択されたときに表示されます。 **Add tab** をクリックすると、新しいタブが追加されます。追加した各タブには、対応するコンテンツコンテナが自動的に作成されます。 画面が最初に表示されたときに特定のタブをアクティブにするには、**Selected by default** をオンにしてください。 ## タブのスタイル設定 \{#style-the-tabs\} ### テンプレート \{#templates\} フロービルダーでは、すぐに使える3種類のタブテンプレートを用意しています。 - **Segment control** — 選択中のタブに角丸の枠が付いた、ピル形状のスイッチャー。 - **Button Tabs** — ボタン風のスタイルを持つ独立したタブ。 - **Underline** — 選択中のタブをアンダーラインで示すテキストラベル。 ### タブの状態 \{#tab-states\} 各タブには状態切り替え(**Default / Selected**)があり、アクティブ状態と非アクティブ状態のスタイルをそれぞれ個別に設定できます。テキストスタイル、色、塗りつぶし、ボーダーを状態ごとに変更できます。 ## 選択グループ \{#selectable-group\} タブは**単一選択グループ**です。常にひとつのタブだけがアクティブになります。グループの管理は **Screen settings** パネルの [Selectable groups](paywall-layout-and-products#selectable-groups) セクションから行えます。 グループは2つの変数を提供します。 - `tabs.selectedOptionId` — 選択中のタブのID。条件式で使用できます。 - `tabs.selectedOptionTitle` — 選択中のタブのラベル。動的テキストで使用できます。 グループ名を変更した場合は、`tabs` の部分をカスタムの **Group ID** に置き換えてください。 詳細は [選択可能な要素とグループ](flow-selectable-elements) をご覧ください。 --- # File: builder-toggles --- --- title: "トグル" description: "ペイメントフローにトグルスイッチを追加します。" --- :::warning デフォルトでオンに設定されたトライアルトグルを使用するアプリは、Appleに拒否される可能性があります。デフォルトで「オン」になっているトグルは、App Store Review Guidelinesに基づき、ユーザーの明示的な選択なしにフライアルへの同意を示す不正なダークパターンとみなされる場合があります。 拒否を避けるため、トグルはデフォルトで **オフ** に設定し、ユーザー自身がトライアルを選択できるようにしてください。 ::: トライアルトグルは、ペイウォール上で標準プロダクトとトライアルベースのプロダクトをユーザーが切り替えられるバイナリスイッチです。ユーザーが状態を変更すると、プロダクトグループの入れ替え、変数の更新、要素の表示・非表示といったアクションを即座にトリガーできます。 トライアルトグルを追加するには、対象の画面で **+** をクリックし、**Trial toggle** を選択します。 各トライアルトグルは **Toggle** タイプの選択可能な要素です。選択可能な要素にはそれぞれ状態を反映する変数が割り当てられており、たとえば `trial` という名前のトグルには `True` または `False` の値を持つ `trial.is_selected` 変数が付与されます。 他の要素をトグルの状態に連動させるには、この変数を基にした条件付き[アクション](onboarding-actions)または[条件付き表示](onboarding-element-visibility)を設定してください。 --- # File: builder-reviews-and-testimonials --- --- title: "レビューと口コミ" description: "ペイウォールにレビュー、評価、ソーシャルプルーフを追加します。" --- **User Engagement** 要素カテゴリには、ペイウォールにレビュー、評価、ソーシャルプルーフを表示するための4つのテンプレートが用意されています。各テンプレートは完全に編集可能なコンポジションです。プレースホルダーテキストを置き換え、フローの他の部分に合わせて[カラースタイル](builder-styling)と[タイポグラフィ](onboarding-text)を適用してください。 ## レビュー \{#review\} 1つの評価、引用文、著者のクレジットを含むカードです。印象的なユーザーの言葉を紹介するのに使用します。 ## 評価 \{#rating\} 「17000+ rating」のような件数と星のリストです。評価の数の多さを強調するのに使用します。 ## アプリ評価 \{#app-rating\} 「4.9 / Based on 1000+ reviews」のようなサンプルサイズ付きのスコア表示です。高い総合評価を際立たせるのに使用します。 ## ソーシャルプルーフ \{#social-proof\} 「Join 50,000+ users」のようなメンバー数付きのアバターグループです。コミュニティの規模を強調するのに使用します。 --- # File: flow-timer --- --- title: "カウントダウンタイマー" description: "ペイウォールにカウントダウンタイマーを追加します。" --- **カウントダウンタイマー**は、設定した時間からゼロに向かってカウントダウンし、ゼロに達すると表示が停止します。 ## テンプレート \{#templates\} このカテゴリーには4つのビジュアルバリアントがあります: - **Blocks** — 日・時・分・秒をそれぞれラベル付きのセルに分けて表示します。 - **Inline Units** — 単位のサフィックスを付けた1行テキスト表示です。 - **Inline** — 数字のみの表示です。 - **Badge** — ピル形状の数字表示です。 ## 設定 \{#settings\} ### 時間を設定する \{#set-the-duration\} 右パネルの **Countdown** セクションで、開始時間を日・時・分・秒で入力します。 ### 動作を設定する \{#configure-the-behavior\} **Behavior** ドロップダウンでタイマーの開始タイミングを設定します: - **Every appear** — ユーザーが画面を開くたびに再スタートします。デフォルト設定です。 - **First appear** — 現在のアプリセッション中にユーザーが初めて画面を表示したときにスタートします。同じセッション中に戻ってきた場合はカウントを継続し、アプリを新たに起動するとリセットされます。 - **First appear (persisted)** — ユーザーが初めて画面を開いたときにスタートし、アプリを再起動してもカウントを継続します。 ### タイマー終了時にアクションをトリガーする \{#trigger-an-action-when-the-timer-ends\} :::link 関連記事:[アクション](onboarding-actions) ::: カウントダウンがゼロになったときにアクションを実行するには、**On timer end** トリガーを追加します。たとえば、別の画面に遷移したり、割引バッジを非表示にしたりすることができます。 --- # File: onboarding-quizzes --- --- title: "フローのクイズ" description: "Adapty フローにインタラクティブなクイズを追加して、ユーザーの好みを収集し、パーソナライズされたフローを実現しましょう — コード不要です。" --- クイズを使うと、あらかじめ定義した選択肢をユーザーに提示できます。入力フィールドと異なり、クイズにはテキスト入力欄がなく、ユーザーは用意された選択肢から選ぶだけです。好みの収集、ユーザーのセグメント分け、回答に基づくフローの分岐などに活用できます。 ### クイズを追加する \{#add-a-quiz\} 1. 左上の **+** をクリックします。 2. **Quiz** を選択します。 3. クイズの種類を選択します。 - **Icon/image/emoji options:** アイコン、画像、または絵文字とテキストラベルがセットになった選択肢を縦並びで表示します。 - **Icon/image/emoji grid:** アイコン、画像、または絵文字付きの選択肢をグリッド形式で表示します。 - **Rating:** 数値またはスター形式でユーザーが評価を表現できるスケールです。 ### 条件付きナビゲーションを設定する \{#set-up-conditional-navigation\} ユーザーの選択に応じて異なる画面へ誘導するには、クイズのオプションではなく**ナビゲーションボタン**に条件付きアクションを設定します。 1. ナビゲーションボタンを選択します。 2. **Interactions** パネルで、**On Tap** トリガーに **Conditional** アクションを追加します。 3. **Edit Action** ダイアログで **if** 行を設定します。 - 左側の `{}` をクリックし、**Elements → Screen → `<quizElementId>.selectedOptionId`** を選択してユーザーの選択を参照します。 - 演算子は `=` のままにします。 - 右側に一致させる elementId を入力します(例: `rock`)。 4. **then** の下で、アクションを **Navigate to** に設定し、遷移先の画面を選択します。 5. **else** の下で、フォールバックの **Navigate to** の遷移先を設定するか、**+ Add else/if** をクリックして他のオプション用の条件を追加します。 :::link クイズの回答の活用方法については、以下のガイドをご参照ください。 - [条件付きナビゲーション](onboarding-navigation-branching) - [変数](onboarding-variables) - [アクション](onboarding-actions) ::: ### クイズの種類を変更する \{#change-quiz-type\} デフォルトでは、クイズは **multi choice**(複数選択)です — ユーザーは複数の選択肢を同時に選べます。1つだけ選ばせたい場合は **single choice** に切り替えます。 1. クイズを含む画面を選択します。 2. **Screen settings** で **Selectable groups** までスクロールし、対象のクイズをクリックします。 3. **Edit group** ダイアログで **Group type** を開き、以下から選択します。 - **Single choice** — 一度に1つの選択肢しか選べません。 - **Multi choice** — 複数の選択肢を選べます。 4. **Save** をクリックします。 --- # File: builder-inputs-and-forms --- --- title: "フロービルダーでのインプットとフォーム" description: "テキストフィールドやチェックボックスなどのインタラクティブなフォーム要素を追加する。" --- インプットを使用すると、名前、メールアドレス、生年月日などのテキストデータをユーザーから収集できます。入力された値を保存して、フロー内の別の箇所(例:後のスクリーンでユーザーを名前で呼びかけるなど)で参照することもできます。 ## インプットを追加する \{#add-an-input\} 1. 左上の **+** をクリックします。 2. **Input** を選択します。 3. インプットタイプを選択します: - **Text:** 任意の短いテキスト入力。 - **Email:** メールアドレス。オプションで形式バリデーションあり。 - **Password:** セキュアなテキスト入力。要件を設定可能。 - **Number:** 数値。形式を設定可能。 - **Phone number:** 電話番号。 - **Date:** 日付ピッカーを開く。 - **Time:** 時刻ピッカーを開く。 - **Date and time:** 日付と時刻の複合ピッカーを開く。 ## インプットを設定する \{#configure-an-input\} :::link レイアウト、スタイル、表示設定などのビジュアル設定の詳細については、[要素のスタイリング](builder-styling) を参照してください。 ::: すべてのインプットタイプで、**Design** タブから以下の項目を設定できます: - **Type:** インプットタイプを変更します(Text、Email、Password、Number、Phone number、Date、Time、Date and time)。 - **Element ID:** フロー内の別の箇所でインプットの値を参照するための識別子。後述の [インプット値を使用する](#use-input-values) を参照してください。 - **Placeholder:** 空のフィールド内に表示されるヒントテキスト。 - **State:** さまざまな状況でのインプットの見た目を定義します。**Default**、**Active**、**Invalid**、**Disabled** を切り替えて、それぞれに異なるビジュアルを適用できます。 - **Typography:** フィールド内に表示される値のテキストスタイル。 - **Leading and trailing icons:** インプットフィールド内にアイコンを追加します。 一部の設定は特定のインプットタイプにのみ対応しています: | 設定 | インプットタイプ | |----------------------------|---------------------------| | Clear button | Text、Email | | Validate email format | Email | | Show password icon | Password | | Edit password requirements | Password | | Number format | Number | | Date/time format | Date、Time、Date and time | | Min and max date | Date、Date and time | ## インプット値を使用する \{#use-input-values\} すべてのインプットは自動的に変数として利用できます。セットアップや **On Submit** アクションは不要です。値はインプットの **Element ID**(**Input Settings** で設定)を通じて参照されます。 フロー内の別の箇所でインプット値を使用するには(例:コピーのパーソナライズ、別フィールドへの入力、条件付きナビゲーションなど)、変数を挿入して以下を選択します: **Element > Screen > `<elementId>.value`** :::link 保存されたインプット値の使い方については、以下のガイドを参照してください: - [条件付きナビゲーション](onboarding-navigation-branching) - [変数](onboarding-variables) ::: ## インプットのバリデーション \{#input-validation\} バリデーションの動作はインプットタイプによって異なります。すべてのインプットは読み取り専用の Boolean 変数 `<elementId>.isValid` を公開しており、入力値がそのインプットのバリデーションルールを満たしているかどうかを反映します。条件付きアクションや条件付き表示制御で活用できます(例:メール形式が正しくなるまで「次へ」ボタンを非表示にするなど)。 :::note - `isValid` 変数は読み取り専用です。値を設定することはできません。 - 空のインプットは常に有効と見なされます。 - テキストインプットにはバリデーションルールがありません。`textInput.isValid` は常に `True` を返します。 ::: | インプットタイプ | バリデーションの動作 | |---|---| | Text | 組み込みのバリデーションルールはありません。 | | Email | オプション。**Design** パネルで **Validate email format** を有効にすると、入力値がメール形式チェックで検証されます。 | | Phone number | 電話番号形式の組み込みチェック。ビルダーで設定することはできません。ルールは実行時に評価されます。 | | Password | 設定可能。後述の [パスワード要件](#password-requirements) を参照してください。 | | Number | 形式ベース。入力値は選択した数値形式と一致する必要があります。後述の [数値形式](#number-format) を参照してください。 | | Date、Time、Date and time | 組み込み。ピッカーは有効な日付または時刻の値のみを受け付けます。 | **Invalid** [ビジュアルステート](builder-styling#input-states) は、ユーザーがフォームを送信したとき(例:キーボードで Enter または Done を押したとき)に有効になります。それまでは、インプットは **Active** または **Default** ステートで表示されます。 ### パスワード要件 \{#password-requirements\} パスワードインプットは設定可能なバリデーションルールをサポートしています。**Design** パネルの **Edit password requirements** をクリックしてルールエディタを開きます。有効になったルールはインプットの下にライブチェックリストとして表示され、各ルールが満たされると同時にチェックマークが付きます。 利用可能なルール: - **Min length** — 最小文字数。デフォルト: 8。 - **Max length** — 最大文字数。デフォルト: 32。 - **Uppercase letter** — 大文字(A〜Z)を1文字以上含む。 - **Lowercase letter** — 小文字(a〜z)を1文字以上含む。 - **Number** — 数字を1文字以上含む。 - **Special character** — 英数字以外の文字(例:`!@#$%`)を1文字以上含む。 すべての有効なルールが満たされた場合にのみ、パスワードが有効と見なされます。 ### 数値形式 \{#number-format\} **Number** インプット設定の **Format** ドロップダウンで、入力値の解析方法を制御します: - **Integer** — 整数のみ(例:`4`)。 - **Decimal (Point)** — ピリオドを小数点区切り文字とする小数(例:`4.89`)。 - **Decimal (Comma)** — カンマを小数点区切り文字とする小数(例:`4,89`)。 選択した形式と一致しない値は無効と見なされます。 ## インプットイベントでアクションをトリガーする \{#trigger-actions-on-input-events\} :::link メイン記事:[アクション](onboarding-actions) ::: **Interactions** パネルで、ユーザーの入力に応じたアクションを実行できます: - **On changed** — ユーザーがインプットの値を変更したときに発火します。すべてのインプットタイプで利用可能です。 - **On submit** — ユーザーがキーボードで Enter または Done を押してテキストインプットを送信したときに発火します。日付と時刻のピッカーにはこのトリガーはありません。 --- # File: onboarding-navigation-branching --- --- title: "ナビゲーションと分岐" description: "静的ルートと動的分岐を使って、ユーザーを画面ごとにガイドします。" --- ナビゲーションと分岐を使うと、フローの各ステップでユーザーを案内できます。静的ルートで全ユーザーをコア画面に誘導し、動的ナビゲーションでユーザーの選択に応じてフローを変化させることが可能です。 :::link ナビゲーションはアクションタイプの一つです。アクションの詳細については、[アクション](onboarding-actions)を参照してください。 ::: <div style={{ maxWidth: '560px', margin: '0 auto 2rem', position: 'relative', aspectRatio: '16/9', width: '100%' }}> <iframe style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%' }} src="https://www.youtube.com/embed/OLl-WziDMhU?si=_eUtsmbEuFAaLj1r" title="YouTube video player" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerPolicy="strict-origin-when-cross-origin" allowFullScreen /> </div> ## 画面間を移動する \{#navigate-between-screens\} 静的・動的ナビゲーションは、さまざまなフロー要素を使って設定できます。 ### 静的ナビゲーション \{#static-navigation\} 静的ナビゲーションは、すべてのユーザーを同じ画面に誘導します。設定手順は以下のとおりです。 1. ユーザーがタップできる任意の要素(ボタン、クイズの回答、トグルなど)を選択します。 2. 右側の **Interactions** パネルを開き、**Add trigger** をクリックします。 クイズの選択肢をタップした際に、別途ボタンをタップしなくてもすぐに画面遷移させたい場合は、ボタンではなくクイズオプションの要素をここで選択してください。 3. **On tap** トリガーを設定します: - **Action**: **Navigate to screen** を選択します。 - **Destination**: 遷移先の画面を選択します。 ### ダイナミックナビゲーション \{#dynamic-navigation\} ダイナミックナビゲーションは、クイズの回答・トグル要素の状態・カスタム属性に基づいてユーザーをルーティングします。 [選択可能な要素](flow-selectable-elements)はどれでもダイナミックナビゲーションの条件として使用できます。 設定手順: 1. ユーザーをナビゲートする要素を選択します。 2. 右側の **Interactions** パネルを開き、**Add trigger** をクリックします。 クイズの選択肢をタップした瞬間に(別途ボタンをタップしなくても)ユーザーをナビゲートしたい場合は、ボタンの代わりにクイズ選択肢の要素をここで選択してください。 3. **On tap** トリガーを設定します: - **Action**: **Conditional** を選択します。 - **Conditions**: 条件付きナビゲーションアクションを設定します。詳細は[こちら](onboarding-actions#conditional-actions)をご覧ください。 ## フローを閉じる \{#close-flow\} ユーザーの操作フローでフローを閉じる必要がある場合、ボタンまたは単一回答クイズを使って設定できます。 1. タップ時にフローを閉じる要素を追加・選択します。 2. 右側の **Interactions** パネルを開き、**Add trigger** をクリックします。 3. **On tap** トリガーを設定します。 - **Action**: **Close flow** を選択します。 --- # File: onboarding-actions --- --- title: "アクション" description: "ビルダーでユーザーインタラクションによってトリガーされるアクションを定義します。" --- **Interactions** パネルでは、フロー内の要素がタップ、要素の表示、フォームの送信などのイベントにどう応答するかを定義できます。各イベントに対して、画面間のナビゲート、要素の表示/非表示、URLを開く、変数の設定など、1つ以上のアクションを割り当てます。ユーザーデータに基づいてフローをカスタマイズするには、条件を使用します。 各インタラクションは3つのパーツで構成されます: 1. **Element**: インタラクションを開始する画面コンポーネント — ボタン、クイズの回答、入力フィールドなど。 2. **Trigger**: ロジックを起動するイベント — タップ、要素の表示、フォームの送信など。 3. **Action**: フローが応答として実行するタスク。1つのトリガーに対して複数のアクションを順番に実行できます。 ## インタラクションの設定 \{#set-up-interactions\} インタラクションを設定するには: 1. 画面上または **Layers** パネルで要素を選択します。 2. 右側の **Interactions** パネルに切り替えて、**Add trigger** をクリックします。 3. **Button triggers** セクションで、[トリガータイプ](#trigger-types) を選択します。 4. **Add action** をクリックし、アクション名をクリックして、**Edit action** ウィンドウのドロップダウンから [アクションタイプ](#action-types) を選択します。 5. 選択した [アクションタイプ](#action-types) に応じて、アクションのプロパティを設定します。 6. 必要に応じて **Add action** をクリックして、同じトリガーにさらにアクションを追加します。 ## トリガータイプ \{#trigger-types\} トリガーは、ユーザーの操作、要素の状態変化、または画面の読み込みに応じて発火します。**On screen appear** はすべての要素に対して有効で、その他の要素固有のものです。 | トリガー | 発火するタイミング | 対応要素 | |---|---|---| | **On screen appear** | 画面が読み込まれたとき | すべての要素 | | **On tap** | ユーザーが要素をタップしたとき | [ボタン](paywall-buttons)、[クイズオプション](onboarding-quizzes)、[トグル](builder-toggles)、[カウントダウン](flow-timer)、[ビデオ](custom-media) | | **On changed** | ユーザーが入力値を変更したとき(タイピング、日付や時刻の選択) | すべての [入力要素](builder-inputs-and-forms) | | **On submit** | ユーザーがキーボードの Enter または Done を押してテキスト入力を送信したとき | [テキストベースの入力](builder-inputs-and-forms) | | **On timer end** | [Countdown](flow-timer) 要素がゼロに達したとき | [Countdown](flow-timer) | | **On playback finished** | [Video](custom-media) が末尾に達したとき | [Video](custom-media) | [Loader](builder-loaders-and-progress-bars) など、組み込みのインタラクションを持たない要素に対しては、**On screen appear** が唯一利用可能なトリガーです。 ## アクションタイプ \{#action-types\} :::important ユーザーを別の画面に移動させる **ナビゲーションアクション** は、常にリストの最後のアクションにしてください。その後に配置されたアクション(「Set Variable」など)は、アプリがすでに画面を切り替えているため実行されない場合があります。 ::: ### 画面へナビゲート \{#navigate-to-screen\} これはユーザーを画面間で移動させるための主要なアクションです。ユーザーを指定した目的の画面に移動させます。 このアクションでは、目的の画面を設定するだけです。動的ナビゲーションを有効にしたい場合は、[ナビゲーションと分岐](onboarding-navigation-branching) または [条件付きアクション](#conditional-actions) セクションを参照してください。 ### 次へナビゲート \{#navigate-next\} フローの画面順序において、ユーザーを次の画面に進めます。エディタでの画面の順序がユーザーに表示したい順序と一致している、線形のフローに使用します。 ### 前へナビゲート \{#navigate-back\} シーケンス内の前の画面ではなく、ナビゲーション履歴内の前の画面にユーザーを戻します。 ### URLを開く \{#open-url\} :::tip テキストにリンクを挿入するには [インラインリンク](onboarding-text#inline-link) を使用してください。 ::: 特定のウェブアドレスを開きます。アプリのネイティブ画面の外にあるウェブページ、記事、またはソーシャルメディアプロフィールにユーザーを送る際に使用します。 このアクションでは、2つの設定を構成できます: - **URL address**: URLアドレスを設定します。さらに動的にすることもできます — 例えば、クイズの回答や送信されたデータに基づいて異なるページにユーザーをナビゲートするなど。これを行うには、Variable icon をクリックして使用したい変数を選択します。 - **Open in external browser**: 外部リンクをどこで開くかを定義します。デフォルトでは、ユーザーをアプリ内にとどめるためにアプリ内ブラウザで開きます。外部ブラウザでリンクを開きたい場合は、**Open in external browser** チェックボックスを選択します。 ### フローを閉じる \{#close-flow\} 現在のフローを閉じます。 ### 要素を表示/非表示 \{#showhide-elements\} 画面上の特定の要素を表示または非表示にします。 このアクションは、**Design** パネルの **Visibility** で設定された初期状態を上書きします。**Visibility** が **Hide** に設定されている場合、**Show** アクションで表示されます。 :::important 対象要素が設定されていない **Show** または **Hide** アクションは、[プレビューと公開をブロックします](builder-save-publish#troubleshooting)。対象を選択するかアクションを削除してください。 ::: ### アラートを表示 \{#show-alert\} ネイティブシステムのポップアップウィンドウを表示します。ユーザーは続行するために **Ok** をタップする必要があります。 アラートには **Title** と **Message** を設定する必要があります。どちらも変数を使用してコンテンツを動的にすることができます。これを行うには、Variable icon をクリックして使用したい変数を選択します。 :::important 空または不完全な設定の **Show alert** アクションは、[プレビューと公開をブロックします](builder-save-publish#troubleshooting)。両方のフィールドを入力するかアクションを削除してください。 ::: ### 変数を設定 \{#set-variable\} フロー内の変数の値を更新します。このアクションを追加する前に、左側の **Variables** パネルで変数を作成してください([変数](onboarding-variables) を参照)。 **Add variable** をクリックして、必要な数の変数とその値を設定します。 :::important 割り当てのない **Set variable** アクションは、[プレビューと公開をブロックします](builder-save-publish#troubleshooting)。少なくとも1つの割り当てを設定するかアクションを削除してください。 ::: ### 購入 \{#purchase\} オンボーディング内のボタンやインタラクションから直接購入フローをトリガーします。フローを離れることなく、ユーザーがサブスクリプションを購読したりプロダクトを購入したりできるようにするために使用します。 このアクションでは、2つの動作を設定できます: - **In-app store**: ネイティブ購入を開始します。**Product** を特定のプロダクトに設定するか、画面上でのユーザーの現在の選択に対して `products.selectedProduct` に設定します。 - **Web payment**: ネイティブ購入をトリガーする代わりに、ユーザーを [ウェブペイウォール](web-paywall) に送ります。ウェブベースのサブスクリプションオファーなど、アプリ外でトランザクションを処理したい場合に使用します。 :::important 対象の **Product** または **Web Paywall URL** が設定されていない **Purchase** アクションは、[プレビューと公開をブロックします](builder-save-publish#troubleshooting)。対象を割り当てるかアクションを削除してください。 ::: ### 購入を復元 \{#restore-purchases\} デバイスで購入の復元フローをトリガーします。ユーザーが別のデバイスで以前にサブスクリプションを購入した場合や、アプリを再インストールした後にエンタイトルメントへのアクセスを回復する必要がある場合にタップします。 このアクションには設定するものはありません — Adapty がネイティブストアフローを通じて復元を処理します。 **Restore purchases** アクションは、**Links** ボタンプリセットの **Restore** リンクにも事前設定されています([購入の設定](paywall-product-block#restore-purchases) を参照)。 ## カスタムアクション \{#custom-actions\} カスタムアクションは、独自のアプリコードが処理する **Action ID** という名前を発火させます。組み込みのアクションタイプが必要なことをカバーしていない場合に使用します。 Adapty がトリガーを提供し、アプリが動作を実装します: 1. ビルダーで、要素のインタラクションに **Action ID** を割り当てます。 2. ユーザーがインタラクションをトリガーすると、フローがIDをアプリに渡します。 3. アプリがIDと照合して、コードを実行します。 ### カスタムアクションの設定 \{#set-up-a-custom-action\} 1. **Edit action** ウィンドウで、アプリが認識する文字列の **Action ID** を割り当てます(例:`show_discount`)。 2. アプリのコードに、このAction IDのハンドラーを実装します。実装の詳細とコード例については、[ペイウォールアクションの処理](handle-paywall-actions) を参照してください。 :::important **Action ID** が設定されていない **Custom** アクションは、[プレビューと公開をブロックします](builder-save-publish#troubleshooting)。Action IDを割り当てるかアクションを削除してください。 ::: ### カスタムアクションでできること \{#what-you-can-do-with-custom-actions\} カスタムアクション自体は何もしません。ビルダーで静的なAction IDを設定し、アプリのコードがそのIDを受け取ったときに何をするかを処理します。以下のすべてのユースケースは同じパターンに従います:フローでIDを割り当て、コードで処理する。 - **アプリ内イベントをトリガーする**: `viewed_special_offer` などのIDを発火させ、アプリが受け取ったときにアナリティクスにイベントを記録します。 - **システム権限をリクエストする**: `request_location` などのIDを発火させ、アプリからOSの権限プロンプトを呼び出します。Adaptyはプロンプトを表示しません — アプリが表示します。 - **ネイティブ認証を開始する**: `login_google` などのIDを発火させ、独自のログイン画面を表示します。フローはユーザーをサインインさせることはできません。 - **ビジネスロジックを適用する**: `apply_discount` などのIDを発火させ、コンテンツをアンロックするかアプリの状態を変更します。 - **クイズの回答をアプリに渡す**: 各オプションに異なるAction IDを割り当て(例:`goal_weight_loss` と `goal_muscle`)、コードでIDを読み取ります。IDを使用して後でセグメント化できる [カスタムユーザー属性](setting-user-attributes#custom-user-attributes) を設定します。アクションは固定IDのみを持つため、選択を報告する唯一の方法はこれです — フローは選択された値を送信できません。 :::important カスタムアクションは、ユーザーがオプションを選択した瞬間に発火します。ユーザーが回答を変更すると、フローは新しいAction IDも発火させます。アプリはその後、両方を順番に受け取ります — 例えば、`goal_weight_loss`、次に `goal_muscle`。最新のシグナルが優先されるように、ハンドラーを冪等にしてください。 ::: ### カスタムアクションにできないこと \{#what-custom-actions-cant-do\} カスタムアクションは静的です。Action IDはフローをビルドするときに固定されます — [変数](onboarding-variables) や [ユーザー入力](builder-inputs-and-forms) を読み取ることはできません。アクションが発火すると、アプリはそのIDのみを受け取り、ユーザーが入力したメールアドレス、電話番号、その他の入力値は受け取れません。入力フィールドは、分岐とパーソナライズのための変数としてフロー内に留まります。これらの値をアプリで使用するには、独自のUIまたはAPIを通じて収集してください。 ## 条件付きアクション \{#conditional-actions\} 条件付きアクションを使用して、ユーザーデータに基づいてフローを異なるパスに分岐させます。 一般的なユースケースには以下が含まれます: - 画面にクイズがあり、回答に基づいてユーザーを異なる画面にナビゲートしたい場合。この場合、ボタンに条件付きアクションを追加します。 - 異なるユーザーグループに異なるプロダクトやオファーを提供したい場合。それらを異なる画面に配置し、ナビゲーションボタンに条件を設定します。 - 以前のアプリセッションですでにチュートリアルを完了したユーザーに対して、特定のステップをスキップしたい場合。 条件付きアクションは if / else-if / else チェーンのように機能します。アプリは上から下にルールを読み取り、最初の一致で停止します: 1. **IF**: フローが主条件を確認します。 - True の場合?フローはすぐに THEN アクションを実行して停止します。 - False の場合?フローは次のセクションにスキップします。 2. **ELSE IF**: ここに追加のチェックを追加できます(例:「Premiumでない場合、ユーザーはトライアル中ですか?」)。 3. **ELSE**(フォールバック):上記のルールのいずれも一致しなかった場合、フローはこの最終セクションのアクションを実行します。 :::important - ルールが追加されているがアクションが割り当てられていない場合、条件が一致しても何も実行されません。 - 不完全なルール(オペレーターまたは値がない)は、[プレビューと公開をブロックします](builder-save-publish#troubleshooting)。 ::: 各ルールについて、評価する変数と実行するアクションを選択します。1つのルールに複数のアクションを設定できます。 :::important フローは1つのルールのみを実行します — 最初に一致したものです。**IF** と **ELSE IF** の両方を同時に実行する必要がある場合は、両方のアクションを **IF** に追加してください。 ::: 条件で使用するための要素を選択可能にし、グループに整理する方法については、[選択可能な要素とグループ](flow-selectable-elements) を参照してください。 ## トラブルシューティング \{#troubleshooting\} 必須フィールドが欠けているアクションはプレビューと公開をブロックします。完全なリストについては、[フローの保存と公開](builder-save-publish#troubleshooting) を参照してください。 --- # File: builder-loaders-and-progress-bars --- --- title: "プログレスインジケーターとローダー" description: "フローのステップ進行状態とビジー状態を表示します。" --- **Progress** カテゴリには、マルチスクリーンフローのステップ進行を示すタイプと、その場でビジー状態を示すタイプの2種類の要素があります。 ## プログレスインジケーター \{#progress-indicators\} ### インジケーターのスタイル \{#indicator-styles\} **Progress** 要素は、複数画面のフローにおけるユーザーの現在位置を示します。このカテゴリには3つの視覚的なバリアントがあります: - **Linear** — ユーザーが進むにつれて塗りつぶされる1本のバー。 - **Segmented** — 各ステップを表す個別のバーが順番に塗りつぶされていく。 - **Connectors** — 線でつながれたラベル付きの円(例:Step 1、Step 2、Step 3 の順序)。 ### ステップとスクリーンの対応を設定する \{#match-steps-to-screens\} デフォルトでは、プログレスインジケーターはフロー内のすべてのスクリーンをトラッキングします。特定のスクリーンのみに限定したい場合は、**Screens** ドロップダウンから選択してください。または、除外したいスクリーンを開き、**Include screen in progress indicator** チェックボックスのチェックを外してください。 ステップ数をより細かく制御したい場合は、**One segment per screen** をオフにしてください。 :::warning ステップの位置は、ユーザーが実際に見る順番ではなく、画面リストに従って決まります。非線形フローでは、インジケーターに表示されるステップが先に進んだり戻ったりすることがあります。 ::: ### ステップの状態 \{#step-states\} 各ステップには **Completed**、**Current**、**Upcoming** の3つの状態があります。Progress Indicator 内のステップを選択すると、右パネルで状態のスタイルを編集できます。**Apply changes to all states** を使用すると、編集内容を他の2つの状態にコピーできます。 1つのステップを編集すると、同じインジケーター内のすべてのステップに影響します。 ### レイアウトと配置 \{#layout-and-positioning\} プログレスインジケーターはグローバル要素のため、[コンテナ](builder-containers)の内側に配置することはできません。また、位置の設定も不可で、デフォルトで絶対配置が使用されます。ユーザーが画面をスクロールしても、インジケーターは固定されたまま、コンテンツがその下でスクロールします。 インジケーター周囲のスペースを調整するには、要素を移動するのではなく、**Spacing** セクションの **Margin** および **Padding** コントロールを使用してください。レイアウトがずれて見える場合は、インジケーターと隣接する要素の両方でマージンまたはパディングを調整してください。 ## ローダー \{#loaders\} **ローダー**は、処理が進行中であることを示すアニメーション要素です。たとえば、パーソナライズされたプランを作成するためにクイズの回答を処理している場合などに使用します。 このカテゴリには3つのテンプレートがあります。 - **Spinner** — 円形のスピナー。 - **Spinner with label** — キャプション付きの円形スピナー(例:「読み込み中...」)。 - **Loader** — 処理の進行に合わせて塗りつぶされる横バー。 {/* - **Loader with label** — A horizontal bar with a caption and percentage (e.g., "Analyzing... 47%"). */} :::warning ローダーを表示・非表示にするには**トリガー**が必要です。**Interactions**タブを開いてロジックを設定してください。たとえば、ユーザーがクイズを送信した後に表示するなどが可能です。 ::: --- # File: onboarding-variables --- --- title: "変数" description: "フローで動的なデータを表示するために変数を使用します。" --- 変数を使うと、フロー内に動的なコンテンツ(プロダクトの価格、オファーの詳細、各ユーザーのコンテキストに応じて更新されるデータなど)を表示できます。要素の表示制御や画面コンテンツのパーソナライズにも活用できます。 変数パネルを開くには、左パネルの **{ }** アイコンをクリックします。パネルには3つのタブがあります: - **[カスタム](#custom-variables)**: 自分で作成・管理する変数です。 - **[プロダクト](#product-variables)**: ストアからローカライズされたプロダクトおよびオファーのデータを取得する組み込み変数です。 - **[エレメント](#element-variables)**: キャンバス上のエレメントの状態に紐付けられた変数です。 ## カスタム変数 \{#custom-variables\} ### カスタム変数を作成する \{#create-a-custom-variable\} 1. 変数パネルで **+** をクリックします。 2. 変数の名前を入力します。 3. タイプを選択します:String、Number、または Boolean。 4. 初期値を設定します。これはフローが開始したときに変数が保持する値です。 5. **Create variable** をクリックします。 :::tip ドット付きの名前を使うと関連する変数をグループ化できます。例:`user.score` や `user.goal`。 ::: ### インタラクションを通じて変数を更新する \{#update-a-variable-via-an-interaction\} :::link 詳しくは[アクション](onboarding-actions)の記事をご覧ください。 ::: 任意の要素に **Set up variables** アクションを追加することで、実行時に変数の値を更新できます。 1. キャンバス上の要素を選択します。 2. **Interactions** タブで **Add trigger** をクリックします。 3. **On tap** を選択し、**Add action** をクリックします。**Action type** ドロップダウンから **Set up variables** を選択します。 4. **Add variable** をクリックします。変数を選択し、新しい値を設定します。 :::tip 例えば、ユーザーがクイズで選んだ回答に応じて `user.goal` に異なる値を設定し、その変数を使って別の画面へ誘導することができます。 ::: ## プロダクト変数 \{#product-variables\} プロダクト変数は、アプリストアからローカライズされたデータを直接取得します。テキストフィールドで使用すると、ローカライズされた価格、タイトル、オファーの詳細を表示できます。また、条件に使用すると、オファーの対象資格に基づいてコンテンツを表示または非表示にできます。 | 変数 | 説明 | 例 | | :--- | :--- | :--- | | `prod_title` | プロダクトのローカライズされたタイトル | Premium Subscription | | `prod_price` | 1請求期間あたりのローカライズされた価格 | $9.99 | | `prod_price_per_day` | サブスクリプション価格を請求期間の日数で割った値。サブスクリプション以外は空。 | $0.33 | | `prod_price_per_week` | サブスクリプション価格を請求期間の週数で割った値。サブスクリプション以外は空。 | $2.33 | | `prod_price_per_month` | サブスクリプション価格を1か月に換算した値。サブスクリプション以外は空。 | $9.99 | | `prod_price_per_year` | サブスクリプション価格を1年に換算した値。サブスクリプション以外は空。 | $119.88 | | `offer_price` | 初回オファーまたはプロモーションオファーのローカライズされた価格。ユーザーがいずれのオファーも対象外の場合は空。 | $0.99 | | `offer_billing_period` | オファーのローカライズされた請求期間。トライアルおよび一括払いオファーの場合は `offer_full_duration` と同じ。対象外の場合は空。 | 1 week | | `offer_full_duration` | オファーのローカライズされた合計期間。対象外の場合は空。 | 1 month | | `is_free_trial` | ユーザーが無料トライアル付きオファーの対象である場合に `true` を返す。 | true | | `is_pay_up_front` | ユーザーが一括払いオファーの対象である場合に `true` を返す。 | true | | `is_pay_as_you_go` | ユーザーが従量払いオファーの対象である場合に `true` を返す。 | true | :::tip `is_free_trial`、`is_pay_up_front`、`is_pay_as_you_go` を条件付き表示と組み合わせることで、ユーザーが対象となるオファーに応じて要素の表示・非表示を切り替えられます。たとえば、`is_free_trial` が `true` の場合のみ無料トライアルのタイムラインを表示する、といった使い方が可能です。 ::: オファー変数の値は、ユーザーが対象となるオファーの種類によって異なります。例として、週次サブスクリプション「Premium Subscription」($5)に3種類のオファーがある場合を見てみましょう。 - **Pay As You Go**: 最初の3週間は3ドル(週ごとに請求)、その後は週5ドル。 - **Pay Up Front**: 最初の3週間は8ドル(即時請求)、その後は週5ドル。 - **Free Trial**: 最初の1週間無料、その後は週5ドル。 この例では、`prod_title` は「Premium Subscription」を返し、`prod_price` は5ドルを返します。オファー変数の値は、ユーザーが対象となるオファーによって異なります: | 変数 | Pay As You Go | Pay Upfront | Free Trial | | :--- | :--- | :--- | :--- | | `offer_price` | $3 | $8 | $0 | | `offer_billing_period` | 1週間 | 3週間 | 1週間 | | `offer_full_duration` | 3週間 | 3週間 | 1週間 | Pay Upfront および Free Trial オファーの場合、`offer_billing_period` と `offer_full_duration` は同じ値を返します。Pay As You Go の場合、請求期間は1週間ですが全期間は3週間となるため、両者の値は異なります。 :::note オファーの詳細や設定方法については、[オファー](offers)をご覧ください。 ::: ## 要素変数 \{#element-variables\} 要素変数は、ユーザーの選択内容(クイズでの選択、現在のタブ、トライアルトグルのオン/オフなど)を記録します。 要素変数のタイプはグループによって異なります: - **単一選択(Single choice)**: 単一選択クイズとタブ: - `selected_id`: 条件で使用する要素ID - `selected_title`: 動的テキストで使用する要素タイトル - **複数選択(Multi-choice)**: 複数選択クイズ: - `selected_ids`: 条件で使用する要素IDのリスト - `selected_titles`: 動的テキストで使用する要素タイトルのリスト - **トグル(Toggle)**: トライアルトグル: - `is_selected`: Boolean値 よくあるユースケースとしては、以下のようなものがあります: - トライアルトグルが有効かどうかに応じて異なるコンテンツを表示する。 - クイズの回答に基づいて[ユーザーを異なる画面に誘導する](onboarding-navigation-branching) ## テキストに変数を使用する \{#use-variables-in-text\} テキスト要素に変数を挿入するには: 1. キャンバス上のテキスト要素を選択します。 2. **Design** タブで **Content** フィールドを見つけ、テキストを入力します。 3. フィールド内の **{ }** アイコンをクリックします。 4. リストから変数を選択します。 :::tip 変数は他の要素でも使用できます: - リンクやアラートに変数を使って動的にする - 変数に基づいた動的な条件を作成する。例えば、`if experience.current > experience.target, navigate to...` のような条件が作れます ::: ### スタイル変数 \{#style-variables\} 変数単体にリッチテキスト書式を適用することはできません。**Content** フィールドで変数を選択して太字、斜体、下線、取り消し線、色の変更を適用しても、効果はありません。 リッチテキストの設定はテキストブロック全体にのみ適用されます。テキストにスタイルを設定するには、**Design** タブの **Typography** セクションを使用するか、保存済みの[テキストスタイル](onboarding-text#set-up-text-styles)を適用してください。 ### フロー内でコンテンツを再利用する \{#reuse-content-across-screens\} ボタンのラベル「Continue」、繰り返し使うコール・トゥ・アクション、複数の画面に表示する免責事項など、フロー内で同じコンテンツが何度も登場することがあります。機能説明のような長めのテキストを複数の画面で使い回す場合も同様です。各要素にいちいち入力する代わりに、カスタム変数に保存しておきましょう。ユーザーによって異なる画面に誘導する場合でも、表示される文言を統一できます。 1. [カスタム変数を作成](#create-a-custom-variable)して、タイプを String に設定し、初期値に再利用したいテキストを入力します。たとえば、変数名を `button.navigation`、値を `Continue` にします。 2. テキストを表示したい各要素の **Content** フィールドにこの変数を挿入します。 テキストをすべての箇所で変更するには、変数の初期値を一度更新するだけです。その変数を使用しているすべての要素が自動的に更新されるため、各画面を手作業で編集する必要はありません。 --- # File: onboarding-element-visibility --- --- title: "条件付き表示" description: "条件に基づいて要素を表示または非表示にする。" --- 要素に条件を追加することで、その表示・非表示を制御できます。条件付き要素は、指定した条件を満たすユーザーにのみ表示されます。 :::important **Show** または **Hide** [アクション](onboarding-actions)を使って要素を表示・非表示にした場合、そのアクションはその要素に設定された **Visibility** 条件より優先されます。 固定の基準に基づいて常に表示・非表示にしたい要素には **Visibility** 条件を使用してください。ユーザーの操作に応じて表示状態を変えたい場合(例:クイズの質問に答えた後にボタンを表示するなど)はアクションを使用してください。 ::: 要素に条件を追加するには: 1. キャンバスまたはレイヤーパネルで要素を選択します。 2. 右パネルの **Visibility** セクションで **Conditional** を選択します。 3. 3つのタブからプロパティタイプを選んで条件を設定します: - **Custom**:自分で作成・管理する変数。ユーザーの操作によって値を更新できます。詳細は[変数](onboarding-variables)をご覧ください。 - **Products**:価格や名前など、フロー内のプロダクトのプロパティ。 - **Elements**:トライアルトグルがオンかどうかなど、フロー内の他の要素の状態。 4. 一致させる **Value** を入力します。 5. 必要に応じて演算子をクリックして変更します。 6. (任意)**Add condition** をクリックして条件を追加します。セレクターを使って、すべての条件を満たす場合と、いずれか1つを満たす場合を切り替えられます。 --- # File: paywall-dark-mode --- --- title: "ダークモード" description: "Adaptyのフローにダークモードを設定して、ユーザー体験を向上させる方法を説明します。" --- Adapty のフローはダークモードをデフォルトでサポートしています。カラースタイルにはライトとダークの2つのカラーが設定されており、スタイルを要素に適用すると、デバイスの現在のモードに応じて適切な値が自動的に使用されます。Adapty にはあらかじめ設定済みのカラースタイルが用意されており、独自のスタイルを作成することもできます。 ## カラースタイルを設定する \{#configure-color-styles\} 各**カラースタイル**では、ライトとダークのカラーをそれぞれ定義します。要素に名前付きスタイルを適用すると、2つのカラーが自動的に切り替わります。 カラースタイルは左側の **Style** > **Colors** で管理できます。 カラースタイルを追加するには: 1. **Style** > **Colors** で **Create style** をクリックします。 2. ライトとダークのカラーをそれぞれ選択します。 スタイルの名前を変更するには、スタイルの横にある **⋮** をクリックして **Rename** を選択します。 ## ステータスバーのテーマを設定する \{#set-the-status-bar-theme\} **Screen settings** パネルで **Status bar** が有効になっている場合、テーマを個別に設定できます。**Status bar theme** オプションから **Light**、**Dark**、または **Auto** を選択してください。 ## ライト&ダークモードをプレビューする \{#preview-light--dark-modes\} フローが各モードでどのように表示されるかを確認するには、プレビューエリア下部の太陽/月アイコンのトグルを使用します。 ## ダークモードを削除する \{#remove-dark-mode\} ダークモードのサポートを完全に削除するには、**Style** > **Colors** パネルで **⋮** > **Delete dark theme** をクリックします。 --- # File: add-paywall-locale-in-adapty-paywall-builder --- --- title: "フローの言語設定を追加する(フローBuilder)" description: "Adaptyのフローbuilderでローカライズされたコンテンツを追加し、ユーザーの言語で世界中にリーチしましょう。" --- フローをローカライズすると、複数の言語で利用できるようになります。フロービルダーでは、ローカライズは画面ごとに管理され、各画面には翻訳の進捗を確認できる完了率が表示されます。 :::tip 他の言語を追加する前に、デフォルトのロケールでフローの設定を完成させておきましょう。 ::: ## ローカライズの追加と設定 \{#add-and-set-up-localization\} 1. 左パネルで Localizations をクリックし、次に **Add locale** をクリックします。追加する言語を選択してください。 2. 追加した各ロケールは、ローカライズテーブルの列として表示され、デフォルト言語の値があらかじめ入力されています。 3. 未翻訳の項目だけに絞り込みたい場合は、左パネルの **Missing only** トグルをオンにします。テーブルが未翻訳の行だけを表示するようにフィルタリングされます。 ## 外部翻訳のためのエクスポートとインポート \{#export-and-import-for-external-translation\} ローカライズファイルをエクスポートして翻訳者と共有し、翻訳済みの結果をインポートできます。 上部のツールバーで **Import / Export** をクリックします。 ### エクスポートファイルの形式 \{#export-file-format\} エクスポートすると、翻訳可能な要素ごとに1行ずつ記録された `.tsv`(タブ区切り)ファイルが生成されます。列の内容は以下のとおりです: | 列 | 説明 | |--------|-------------| | `Screen` | その要素が属する画面(例:`Welcome`、`Quiz`) | | `Element` | 画面内の要素を示す自動生成の識別子。**Interactions** > **Element ID** で変更できます。 | | `Property` | プロパティの種類(例:`content`) | | `[default_locale]` | デフォルト言語コード(例:`en`) | | `[locale]` | 追加したロケールごとの列(例:`fr`、`es`) | 例: ``` Screen Element Property en fr es Welcome title content Turn words into art Transformez les mots en art Welcome subtitle content Create stunning images in seconds with AI Créez des images en quelques secondes Quiz quiz-title content What will you create? ``` :::note 未翻訳の行はロケール列を空白のままにしておいてください — Adapty は未翻訳として扱います。 ::: ### インポートファイルの要件 \{#import-file-requirements\} - **形式**:`.tsv`(タブ区切り値) - **ヘッダー**:`Screen`、`Element`、`Property`、および少なくとも1つのロケール列が必要です - **ロケール列名**:フローにすでに追加されているロケールコードと一致している必要があります。フローに存在しないロケールコードが含まれるファイルをインポートするとエラーになります。 - **部分インポート**:行の一部だけを含めることもできます。ファイルに含まれていない行は現在の値が保持されます。 ## 手動で翻訳する \{#translate-manually\} ローカライズテーブルの任意のセルに直接翻訳を入力することもできます。 特定の行を操作するには、コンテキストメニュー(**⋮**)を開いてください: - **Reset to default**:その行の翻訳をデフォルト言語の値に戻します。 ## ローカライズをプレビューする \{#preview-the-localization\} 翻訳を確認するには、フロービルダーでアクティブなロケールを切り替え、各画面を確認します。 --- # File: add-flow-remote-config-locale --- --- title: "リモートコンフィグでフローをローカライズする" description: "フローのリモートコンフィグにロケールを追加して、言語や地域ごとに異なる値を提供する方法を説明します。" --- フローのリモートコンフィグには、ロケールごとに個別の JSON ペイロードを持たせることができます。実行時に SDK はユーザーのロケールに一致するペイロードを返すため、新しいアプリバージョンをリリースすることなく、翻訳済みのテキスト、異なる画像、その他のロケール固有の値を提供できます。 ## ロケールを追加する \{#add-a-locale\} フローのリモートコンフィグにロケールを追加するには: 1. Flow Builder でフローを開きます。 2. 画面プレビュー上部のリモートコンフィグアイコンをクリックします。 3. エディタ上部の **Add locale** をクリックします。 4. ダイアログに入力します: - **Code**: ロケールコード(例: `en`、`fr`、`de`)。 - **Name**: 表示名(例: English、French)。 Adapty はロケール用の新しい列を JSON エディタに追加します。 ## ロケールごとに値を編集する \{#edit-values-per-locale\} 各ロケールの列は独自の JSON 形式のデータを受け付けます。列をまたいで同じキーを使い、各ロケールの値を翻訳してください。 たとえば、英語の列: ```json showLineNumbers { "title": "Try for free!", "cta": "Continue", "trial_days": 7 } ``` スペイン語の列: ```json showLineNumbers { "title": "¡Prueba gratis!", "cta": "Continuar", "trial_days": 7 } ``` 列は独立しており、一方を編集しても他方には影響しません。 ## アプリで一致するロケールを読み取る \{#read-the-matching-locale-in-your-app\} SDK は `AdaptyFlow.remoteConfigs` 上の各ロケールに対して 1 つの `AdaptyRemoteConfig` エントリを公開します。ユーザーのロケールに一致する `locale` を持つエントリを選び、その `dictionary` または `jsonString` を読み取って実行時に値を使用します。 ## ロケールをバックアップまたは移動する \{#back-up-or-move-locales\} エディタ上部の **Import/Export** メニューを使うと、リモートコンフィグのバックアップや、フロー間でのコピーができます。エクスポートされた JSON ファイルにはすべてのロケールのペイロードが含まれます。ファイル形式については[リモートコンフィグでフローをカスタマイズする](customize-flow-with-remote-config)を参照してください。 --- # File: customize-flow-with-remote-config --- --- title: "リモートコンフィグでフローをカスタマイズする" description: "リモートコンフィグの JSON ペイロードを使って Flow Builder のフローをカスタマイズします。" --- :::important このガイドは Flow Builder のフローに対するリモートコンフィグについて説明しています。Flow Builder を使わずに作成したクラシックなペイウォールについては、[リモートコンフィグでペイウォールをデザインする](customize-paywall-with-remote-config) をご覧ください。 ::: リモートコンフィグを使うと、SDK が実行時に読み込むカスタム JSON ペイロードを保存できます。タイトル、画像、フォント、カラー、フィーチャーフラグなどの値を、新しいアプリリリースなしに設定できます。 ## リモートコンフィグを使う \{#work-with-remote-config\} フローのリモートコンフィグを開くには、フローエディターの画面プレビュー上部にある Remote Config アイコンをクリックします。 **JSON** ビューでは、任意の JSON 形式のデータを入力できます。エディターには追加したロケールごとに 1 列が表示されます。 :::warning リモートコンフィグに無効な JSON が含まれている場合、フローを**保存**も**公開**もできません。プレビューと公開をブロックする問題の全一覧については、[フローの保存と公開](builder-save-publish#troubleshooting) をご覧ください。 ::: このデータには後から SDK を通じて `AdaptyFlow` の `remoteConfigs` 配列でアクセスできます。Adapty はロケールごとに `AdaptyRemoteConfig` エントリを 1 件保存するため、ユーザーのロケールに一致するものを選び、パース済みの `dictionary` または生の `jsonString` を読み取ってフローを実行時に調整します。リモートコンフィグの使用例をいくつか紹介します。 <Tabs> <TabItem value="Titles" label="タイトル" default> ```json showLineNumbers { "screen_title": "Today only: Subscribe, and get 7 days for free!" } # Test titles or other texts ``` </TabItem> <TabItem value="Images" label="画像"> ```json showLineNumbers { "background_image": "https://adapty.io/media/paywalls/bg1.webp" } # Test images on your flow ``` </TabItem> <TabItem value="Fonts" label="フォント"> ```json showLineNumbers { "font_family": "San Francisco", "font_size": 16 } # Test fonts ``` </TabItem> <TabItem value="Color" label="カラー"> ```json showLineNumbers { "subscribe_button_color": "purple" } # Test colors of buttons, texts etc. ``` </TabItem> <TabItem value="HTML" label="HTML"> ```json showLineNumbers { "photo_gallery": "https://adapty.io/media/paywalls/link-to-html-snippet.html" } # Any HTML code that can be displayed in the flow ``` </TabItem> <TabItem value="Soft/Hard Paywall" label="ソフト/ハードペイウォール"> ```json showLineNumbers { "hard_paywall": true } # By setting it to true, you disallow skipping the paywall without subscribing # You have to handle this logic in your app ``` </TabItem> <TabItem value="Translations" label="翻訳"> ```json showLineNumbers { "title": { "en": "Try for free!", "es": "¡Prueba gratis!", "ru": "Попробуй бесплатно!" } } ``` </TabItem> </Tabs> これらのパターンを組み合わせたり、独自のキーを定義して代替コピー、レイアウト、または動作をテストしたりすることもできます。 次に、[プレースメントを作成](create-placement) してフローを追加します。その後、[iOS アプリでフローをレンダリング](present-remote-config-paywalls) します。 ## ロケールを追加する \{#add-a-locale\} フローをローカライズするには、エディター上部の **Add locale** をクリックしてロケールを選択します。 Adapty はそのロケール用の新しい列をエディターに追加します。各列は独立して編集できます。実行時には、SDK がユーザーの選択に一致する `locale` を持つ `AdaptyRemoteConfig` エントリを返します。 ## JSON のインポートとエクスポート \{#import-and-export-json\} エディター上部の **Import/Export** メニューを使うと、すべてのロケールのリモートコンフィグを一括でバックアップ、共有、または編集できます。 - **Export JSON**: すべてのロケールを含む単一の JSON ファイルをダウンロードします。 - **Import JSON**: 同じ形式の JSON ファイルをアップロードします。アップロードしたファイルで現在のリモートコンフィグが置き換えられます。 ファイルはロケールコードをトップレベルのキーとして使用し、各ロケールのペイロードを値として持ちます。 ```json showLineNumbers { "en": { "title": "Get Premium", "cta": "Continue", "trial_days": 7, "features": ["sync", "export", "ai"] }, "fr": { "title": "Passez à Premium", "cta": "Continuer", "trial_days": 7, "features": ["synchronisation", "exportation", "IA"] } } ``` 各ロケールブロックは、ロケール列に直接入力するのと同じ JSON 構造に従います。 --- # File: paywall-device-compatibility-preview --- --- title: "フローのプレビュー" description: "最適なエクスペリエンスを実現するため、デバイス間でのフローの互換性をプレビューします。" --- フローをさまざまな画面タイプでプレビューする方法は2つあります。 - **デバイスでのプレビュー**: 開発のどの段階でも、実機でフローの見え方を確認できます。 - **Adapty ダッシュボードでのプレビュー**: デザイン中にフローをプレビューできます。 ## デバイスでのプレビュー \{#preview-on-devices\} 実機でフローをプレビューするには: 1. [App Store から Adapty アプリをダウンロードします](https://apps.apple.com/us/app/adapty/id6739359219)。 2. フロービルダーで **Test on device** をクリックします。 3. フローのロケールを選択します。 4. デバイスのカメラで QR コードをスキャンするか、リンクを開きます。これにより、Adapty モバイルアプリでフローが開きます。 :::note テストモードでは、Adapty はストア内のプロダクトにアクセスできないため、フローに表示される価格は実際のものではありません。 ::: ### トラブルシューティング \{#troubleshooting\} --- no_index: true --- 以下のいずれかの問題がある場合、フローを公開またはプレビューすることはできません。 - 設定が不完全なインタラクション。よくある例: - ターゲットURLが設定されていない **Open URL** アクション。 - 遷移先が設定されていない **Navigate to screen** アクション — アクション設定後に遷移先のスクリーンが削除された場合も発生します。 - 演算子または値が設定されていない **conditional action**。 - 変数や値の割り当てがない **Set Variable** アクション。 - プロダクトが未設定(アプリ内ストア)またはWeb Paywall URLが未設定(Web決済)の **Purchase** アクション。 - Action IDが設定されていない **Custom** アクション。 - タイトルまたはメッセージが空の **Show alert** アクション。 - 要素が選択されていない **Show** または **Hide** アクション。 - **要素のないスクリーン**。 - **プロダクトが紐付けられていない**プロダクト要素 — 参照しているプロダクトを削除した場合に発生することがあります。 - 無効な**リモートコンフィグ**のJSONはデリバリープロセス全体を破壊します — ドラフトの保存さえできなくなります。 ## Adapty ダッシュボードでのプレビュー \{#preview-in-the-adapty-dashboard\} :::tip フローが公開の準備ができているか確認するには、[実機でプレビュー](#preview-on-devices)してエラーなく表示されることを確認してください。 ::: フロービルダーのプレビューエリアを使って、さまざまな画面タイプでフローをプレビューできます。これにより、さまざまなデバイスや画面サイズでフローが適切に表示されることを確認できます。 プレビュー下のコントロールを使うと、次のことができます。 - プレビューするデバイスを選択する。 - 横向きと縦向きのプレビューモードを切り替える。 - ライトモードとダークモードを切り替える。 - ロケールを切り替える。 :::tip - 言語によって単語の長さが異なり、画面レイアウトが変わることがあるため、必ず各ロケールをプレビューしてください。 - カスタム変数をプレビューするには、初期値を設定してください。たとえば、`name` 変数を追加した場合、初期値を `Jane Doe` に設定してプレビューできます。 ::: --- # File: builder-save-publish --- --- title: "フローの保存と公開" description: "フローをドラフトとして保存し、ユーザーに公開する" --- [フロービルダー](adapty-flow-builder)では、保存と公開が分かれています。ドラフトは Adapty ダッシュボード上での作業内容を保持し、公開すると現在のバージョンが SDK を通じてユーザーに提供されます。この記事では、両方の操作とその使い分けについて説明します。 ## フローをドラフトとして保存する \{#save-a-flow-as-a-draft\} :::warning 無効な[リモートコンフィグ](customize-flow-with-remote-config)がある場合、ドラフトを保存できません。 ::: フロービルダーは1分ごとに進行状況を自動保存します。 手動でドラフトを保存するには、フロービルダーの右上にある **Save draft** をクリックするか、**Cmd/Ctrl + S** を押してください。 ドラフトはダッシュボード内でのみ有効です。フローがすでに[プレースメント](placements)に割り当てられている場合でも、ユーザーがアプリで見る内容には影響しません。 ## フローを公開する \{#publish-a-flow\} 公開すると、フローの現在のバージョンが SDK を通じてユーザーに提供されます。公開後、新しいバージョンは同じフローの以前に公開されたバージョンを置き換えます。 フローを公開するには、ペイウォールビルダー右上の **Publish to Live** をクリックします。 次に何が起こるかは、フローがすでにプレースメントに割り当てられているかどうかによって異なります。 - **フローがすでにプレースメントにある場合**: 次回そのプレースメントへのリクエスト時から、ユーザーに新しいバージョンが表示されます。 - **フローがプレースメントにない場合**: フローをユーザーに表示するには、[プレースメント](create-placement)にフローを追加してください。 :::tip フローは、すべてのアクション、画面、プロダクト要素が完全に設定されると公開できるようになります。よくある設定漏れについては[トラブルシューティング](#troubleshooting)をご覧ください。 ::: ## フローのステータス \{#flow-status\} 各フローには、フロー一覧にステータスが表示されます。ステータスは、フローの保存・公開ライフサイクルにおける現在の状態を示します。 | ステータス | 意味 | | :----- | :------ | | **Draft** | フローは一度も公開されていません。下書きのみが存在するため、ユーザーにはまだ表示されません。 | | **Dirty** | フローは公開済みですが、まだ公開されていない保存済みの編集があります。再度公開するまで、ユーザーには最後に公開されたバージョンが表示されます。 | | **Publishing** | 公開処理が進行中です。 | | **Failed** | 最後の公開試行が失敗しました。公開済みのバージョンがある場合、ユーザーには引き続きそのバージョンが表示されます。 | | **Published** | 最新の保存済みバージョンが公開中です。未公開の編集はありません。 | | **Archived** | フローは削除されました。 | ## トラブルシューティング \{#troubleshooting\} --- no_index: true --- 以下のいずれかの問題がある場合、フローを公開またはプレビューすることはできません。 - 設定が不完全なインタラクション。よくある例: - ターゲットURLが設定されていない **Open URL** アクション。 - 遷移先が設定されていない **Navigate to screen** アクション — アクション設定後に遷移先のスクリーンが削除された場合も発生します。 - 演算子または値が設定されていない **conditional action**。 - 変数や値の割り当てがない **Set Variable** アクション。 - プロダクトが未設定(アプリ内ストア)またはWeb Paywall URLが未設定(Web決済)の **Purchase** アクション。 - Action IDが設定されていない **Custom** アクション。 - タイトルまたはメッセージが空の **Show alert** アクション。 - 要素が選択されていない **Show** または **Hide** アクション。 - **要素のないスクリーン**。 - **プロダクトが紐付けられていない**プロダクト要素 — 参照しているプロダクトを削除した場合に発生することがあります。 - 無効な**リモートコンフィグ**のJSONはデリバリープロセス全体を破壊します — ドラフトの保存さえできなくなります。 公開前に問題を確認するには、[Adapty アプリ](paywall-device-compatibility-preview)でフローをプレビューしてください。プレビューでフローが読み込めない場合は、エラーメッセージで詳細を確認してください。 --- # File: flow-metrics --- --- title: "フローの指標" description: "フローのパフォーマンス指標を追跡・分析して、サブスクリプション収益を改善しましょう。" --- Adapty はフローのパフォーマンスを測定するための各種指標を収集しています。ペイウォールの指標とは異なり、フロー指標にはコンプリーション(完了)トラッキングが含まれているため、フローの各画面でユーザーがどこで離脱しているかを把握できます。ビューは数分ごとに更新されますが、それ以外の指標はリアルタイムで更新されます。このドキュメントでは、利用可能な指標の概要、定義、および計算方法について説明します。 :::important フローの収益は、フローが表示された後に発生したすべてのトランザクションから計算されます。 ::: フロー指標はフロー一覧ページで確認でき、すべてのフローのパフォーマンスの概要を提供します。この統合ビューでは、各フローの集計指標が表示され、効果を比較して改善点を特定できます。 各フローのより詳細な分析を行うには、フロー詳細指標に移動してください。選択したフローに特有の包括的な指標が表示され、パフォーマンスを深く把握できます。 ## 指標のコントロール \{#metrics-controls\} システムは選択した期間に基づいて指標を表示し、左側の列のパラメーターに従って3段階のインデントレベルで整理します。 公開済みフローの指標は、フローの公開日から現在の日付までの期間をカバーします。下書きおよびアーカイブ済みのフローも指標テーブルに含まれますが、データがない場合は指標が表示されません。 ### 指標データの表示オプション \{#view-options-for-metrics-data\} フローページでは、指標データに対して2つの表示オプションが用意されています。 - プレースメント別表示:フローに関連付けられた[プレースメント](placements)ごとに指標がグループ化されます。同じフローが異なるプレースメントでどのようなパフォーマンスを発揮しているかを比較する際に使用します。 - オーディエンス別表示:フローのターゲット[オーディエンス](audience)ごとに指標がグループ化されます。異なるオーディエンスセグメントに特有の指標を評価する際に使用します。 フローページ上部のドロップダウンで、希望する表示方法を選択できます。 ### インストール日で指標をフィルタリング \{#filter-metrics-by-install-date\} **Filter metrics by install date** チェックボックスを使用すると、トランザクションやビューが発生した日時ではなく、ユーザーがアプリをインストールした日時に基づいてデータを分析できます。特定のコホートのユーザー獲得パフォーマンスを測定する際に便利です。 ### 期間の設定 \{#time-ranges\} 時間範囲を使用して指標データを分析でき、日・週・月・カスタム日付範囲などの特定の期間に絞り込むことができます。 ### フィルターとグループ \{#filters-and-groups\} Adapty はニーズに合わせた指標分析のフィルタリングとカスタマイズツールを提供しています。指標ページでは、さまざまな時間範囲、グループ化オプション、フィルタリング機能を利用できます。 - フィルター項目:アトリビューション(ソース、広告グループ、広告セット、クリエイティブ、キャンペーン)、国、ストア。 - グループ項目:フロー(デフォルト)、国、またはストア。グループ化オプションは、そのディメンションにデータがある場合にのみドロップダウンに表示されます。たとえば、すべてのフロービューが単一の国からの場合、「国」は表示されません。 利用可能なコントロール、フィルター、グループ化オプション、およびその使用方法の詳細については、[こちらのドキュメント](controls-filters-grouping-compare-proceeds)をご参照ください。 ### 単一指標チャート \{#single-metric-chart\} チャートセクションでは、データをシンプルな棒グラフで表示します。チャートを使うと次の情報をすばやく確認できます。 - 各指標の正確な数値。 - 期間ごとのデータ。 チャートの横には合計値が表示され、全体像を一目で把握できます。 矢印アイコンをクリックするとチャートを拡大できます。 ### 指標の合計サマリー \{#total-metrics-summary\} 単一指標チャートの横には、指標の合計サマリーセクションがあります。このセクションでは、特定の時点での選択した指標の累計値が表示されます。ドロップダウンメニューを使って表示する指標を変更できます。 ## 指標の定義 \{#metrics-definitions\} ### ビューとユニークビュー \{#views--unique-views\} **ビュー**は、ユーザーがフローを開始した(最初の画面に到達した)回数をカウントします。同じユーザーが2回開始した場合、ビューは2としてカウントされますが、ユニークビューは1となります。この指標は、フローが表示された頻度を把握するのに役立ちます。 ### コンプリーションとユニークコンプリーション \{#completions--unique-completions\} **コンプリーション**は、ユーザーがフローの最後の画面に到達した回数をカウントします。同じユーザーが2回完了した場合、コンプリーションは2としてカウントされますが、ユニークコンプリーションは1となります。 ### ユニークコンプリーション率 \{#unique-completions-rate\} ユニークコンプリーション数をユニークビュー数で割った値です。この指標を使用して、ユーザーがフローをどのように進んでいるか、また途中でどこで離脱しているかを把握できます。 ### 収益(Revenue) \{#revenue\} **収益(Revenue)** は、フローに紐づいた購入および更新からの総収益(USD)を表示します。これはApp Store / Google Play コミッションを含む、控除前の金額です。 ### 手取り収益(Proceeds) \{#proceeds\} [**手取り収益(Proceeds)**](analytics-cohorts#revenue-vs-proceeds) は、App Store / Google Play がコミッションを差し引いた後、税金控除前に受け取る金額を示します。 :::important アプリが手数料軽減プログラムに登録されている場合は Adapty にお知らせください。正確な計算のために、[アプリの設定](general)で[スモールビジネスプログラム](app-store-small-business-program)および[手数料軽減サービスプログラム](google-reduced-service-fee)のステータスを指定してください。 ::: ### 純手取り収益(Net proceeds) \{#net-proceeds\} ストアのコミッションと税金の両方が差し引かれた最終的な収益です。 ### ARPPU \{#arppu\} ARPPU は課金ユーザー1人あたりの平均収益です。総収益をユニーク課金ユーザー数で割って計算されます。例:$15,000 の収益 ÷ 1,000 人の課金ユーザー = ARPPU $15。 ### ARPU \{#arpu\} ARPU はフローを視聴したユーザー1人あたりの平均収益です。総収益をユニークビューアー数で割って計算されます。 ### ARPAS \{#arpas\} ARPAS はアクティブサブスクライバー1人あたりの平均収益です。総収益を、トライアルまたはサブスクリプションを有効化したサブスクライバー数で割って計算されます。例:$5,000 の収益 ÷ 1,000 人のサブスクライバー = ARPAS $5。 ### CR purchases と Unique CR purchases \{#cr-purchases--unique-cr-purchases\} **購入へのコンバージョン率**は、フローのビューのうち何パーセントが購入につながったかを示します。例:100 ビューから 10 件の購入 = 10% のコンバージョン率。 **Unique CR purchases** は、フローを視聴したユニークユーザーのうち何パーセントが購入を行ったかを測定します。ユーザーが何度視聴しても1回としてカウントされます。 ### CR trials と Unique CR trials \{#cr-trials--unique-cr-trials\} **トライアルへのコンバージョン率**は、フローのビューのうち何パーセントがトライアル開始につながったかを示します。例:100 ビューから 10 件のトライアル = 10% のコンバージョン率。 **Unique CR trials** は、フローを視聴したユニークユーザーのうち何パーセントがトライアルを開始したかを測定します。ユーザーが何度視聴しても1回としてカウントされます。 ### 購入(Purchases) \{#purchases\} **購入(Purchases)** は更新を除く、フローでのすべてのトランザクションをカウントします。対象は以下のとおりです。 - 新規直接購入。 - フローで有効化されたトライアルのコンバージョン。 - プラン変更(アップグレード、ダウングレード、クロスグレード)。 - フローでのサブスクリプション復元(自動更新なしで期限切れになった後に再開した場合など)。 この指標は、フローからの新規トランザクションの全体像を把握するのに役立ちます。 ### トライアル(Trials) \{#trials\} **トライアル(Trials)** は、フローを通じて無料トライアル期間を開始したユーザー数をカウントします。この指標を使用して、トライアルオファーが有料化前にどれだけのユーザーを引き付けているかを追跡できます。 ### キャンセルされたトライアル(Trials cancelled) \{#trials-cancelled\} **キャンセルされたトライアル(Trials cancelled)** は、トライアル期間中に自動更新をオフにしたユーザー数を示します。サービスを試した後、有料サブスクリプションへの継続を断ったユーザーの数を把握できます。 ### 返金(Refunds) \{#refunds\} **返金(Refunds)** は、理由を問わず返金が行われた購入およびサブスクリプションの件数をカウントします。 ### 返金率(Refund rate) \{#refund-rate\} **返金率(Refund rate)** は、初回購入のうち返金された割合を示します。例:1,000 件の初回購入から 5 件の返金 = 0.5% の返金率。更新はこの計算に含まれません。 --- # File: fallback-flows --- --- title: "フォールバックフロー" description: "デバイスがオフラインのときもフローを表示し続けるために、Adapty でローカルのフォールバックフローを設定します。" --- スムーズなユーザー体験を維持するために、[フロー](adapty-flow-builder)の**フォールバックバージョン**を設定しておくことが重要です。 アプリがフローをリクエストすると、Adapty SDK はサーバーに接続してその設定を取得しようとします。デバイスが Adapty に接続できない場合(ネットワーク障害やサーバー停止など)、SDK はローカルデータにフォールバックします。 - ユーザーがすでにそのフローを一度見たことがある場合、SDK はキャッシュされたコピーを表示します。 - キャッシュが存在しない場合、SDK はアプリにバンドルされたフォールバック設定ファイルを読み込みます。 Adapty はこれらのフォールバックファイルを自動的に生成します。フローのフォールバックバンドルはペイウォールと共有されており、プラットフォームごとの単一の JSON ファイルに両方のフォールバックバリアントが含まれています。SDK は必要なセクションを読み込みます。 :::important フローのフォールバックは **Adapty SDK 4.0 以降**のバンドルに含まれています。ダウンロードダイアログで古い SDK バージョンを選択した場合、ファイルにはペイウォールとオンボーディングのバリアントのみが含まれており、フローは含まれません。フローのフォールバックを利用する前に、アプリがフロー対応の SDK リリースを使用していることを確認してください。 ::: ## 始める前に \{#before-you-start\} 1. フロービルダーで[フロー](adapty-flow-builder)を作成します。 2. フロー用の[プレースメントを作成](create-placement)します。 ## フォールバックファイルのダウンロード \{#download-the-fallback-file\} 1. **[Placements](https://app.adapty.io/placements)** ページを開きます。 2. 右上の **Fallbacks** ボタンをクリックします。 3. ドロップダウンからターゲットプラットフォームを選択します。 4. アプリに組み込んでいる SDK バージョンに合ったものを選びます。フローを含むバンドルを受け取るには、**Adapty SDK v4.0.0 and higher**(またはそれ以降のオプション)を選択してください。 ブラウザがプラットフォームごとの JSON ファイル(例:`ios_4_0_0_fallback.json`)をダウンロードします。 <details> <summary>フローフォールバックエントリの例(クリックして展開)</summary> ```json "PLACEMENT_ID": { "data": [ { "developer_id": "PLACEMENT_ID", "variation_id": "cb1c0ef8-aecd-4a53-a6f3-b98266e66884", "flow_id": "daf25858-3fa2-4981-8500-9c8a30e5b7e6", "flow_name": "FLOW_NAME", "flow_version_id": "FLOW_VERSION_ID", "placement_audience_version_id": "a9eb3ab8-3178-477d-84d4-ef9d3978e48b", "audience_name": "All Users", "ab_test_name": "", "cross_placement_info": null, "weight": 100, "variations": [ { "variation_id": "cb1c0ef8-aecd-4a53-a6f3-b98266e66884", "paywall_id": "PAYWALL_ID", "paywall_name": "PAYWALL_NAME", "ab_test_name": "", "products": [], "revision": 1, "custom_payload": null, "weight": 100 } ], "remote_configs": [] } ], "meta": { "placement": { "developer_id": "PLACEMENT_ID", "is_tracking_purchases": true, "audience_name": "All Users", "placement_audience_version_id": "a9eb3ab8-3178-477d-84d4-ef9d3978e48b", "revision": 0, "ab_test_name": "" } } } ``` 正確な構造は SDK バージョンによって異なる場合があります。手動で作成するのではなく、必ず Adapty が生成したファイルをご使用ください。 </details> ## ダウンロード後の手順 \{#after-the-download\} ファイルをアプリのコードに追加し、プラットフォーム固有のセットアップガイドに従ってください。ペイウォールのフォールバックを読み込む API は、アプリがフロー対応 SDK リリースになった時点でフローのフォールバックも読み込みます。 - [iOS](ios-use-fallback-paywalls) ## 制限事項 \{#limitations\} フォールバックフローはハードコードされてローカルに保存されるため、ライブフローの完全な動的機能は利用できません。 - **プレースメントごとに 1 つのバリアント。** プレースメントに複数のフロー(異なるオーディエンス、A/B テストのバリアント)がある場合、フォールバックファイルは最も高いウェイトを持つバリアント、または最も広いオーディエンスのバリアントを使用します。 - **A/B テストなし。** ライブフローの A/B テストはサーバー側で解決されますが、フォールバックは常に単一の選択されたバリアントを表示します。 - **リモート更新なし。** フォールバックを更新するには新しいアプリのリリースが必要です。リモートコンフィグで通常行うような実行時の更新は、ライブフローを通じて行ってください。 - **デフォルトロケールのみ。** フォールバックは `en` ロケールを使用します。ローカライズされたバリアントはバンドルされません。 --- # File: create-product --- --- title: "プロダクトを作成する" description: "Adapty で新しいサブスクリプションプロダクトを作成するためのステップバイステップガイド。収益管理を効率化できます。" --- Adapty でのプロダクト作成方法は、ストアにすでにプロダクトが存在するかどうかによって異なります。 - **[App Store や Google Play にプロダクトがまだない場合は、Adapty でプロダクトを作成してストアに直接プッシュする](#create-product-and-push-to-store)** - **[App Store や Google Play にすでにプロダクトがある場合は、Adapty でプロダクトを作成して既存のストアプロダクトに接続する](#create-product-and-connect-existing-store-products)** :::tip [Developer CLI](developer-cli-reference#adapty-products-create) を使ってプログラムでプロダクトを作成することもできます。 ::: ## プロダクトを作成してストアにプッシュする \{#create-product-and-push-to-store\} :::warning 始める前に、必要なストアとのインテグレーションが設定済みであることを確認してください。 - [App Store](initial_ios) - [Google Play](initial-android) App Store のインテグレーションを以前に設定した場合は、[App Store Connect API キーの追加](app-store-connection-configuration#step-6-add-app-store-connect-api-key)も完了しているかご確認ください。 ::: <div style={{ maxWidth: '560px', margin: '0 auto 2rem', position: 'relative', aspectRatio: '16/9', width: '100%' }}> <iframe style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%' }} src="https://www.youtube.com/embed/qUpC2XG-r5E?si=7Komyv4_PUQ4FaEH" title="YouTube video player" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerPolicy="strict-origin-when-cross-origin" allowFullScreen /> </div> アプリに新しいプロダクトを追加するには: 1. Adapty のメインメニューから **[Products](https://app.adapty.io/products)** に移動します。 <img src="/assets/shared/img/products-tab.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. 右上の **Create product** をクリックします。Adapty はサブスクリプション、非消耗型(永続アクセスを含む)、消耗型アイテムなど、すべてのプロダクトタイプに対応しています。 3. **Create a new product and push to stores** を選択します。 <img src="/assets/shared/img/push-to-stores.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '400px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. 以下の情報を入力します。 - **Product name**: Adapty ダッシュボードで使用するプロダクト名を入力します。この名前は主に管理用ですので、Adapty ダッシュボード全体で使いやすい名前を自由に選んでください。 - **Access Level**: プロダクトが属する[アクセスレベル](access-level)を選択します。アクセスレベルは、プロダクトを購入した後に解放される機能を決定します。このリストには、事前に作成されたアクセスレベルのみ表示されます。`premium` アクセスレベルは Adapty でデフォルトで作成されていますが、[アクセスレベルを追加する](access-level)こともできます。 - **Subscription duration**: リストからサブスクリプションの期間を選択します。 - **Weekly/Monthly/2 Months/3 Months/6 Months/Annual**: サブスクリプションの期間。 - **Lifetime**: アプリのプレミアム機能を永続的に解放するプロダクトには、永続期間を使用します。 - **Non-Subscriptions**: サブスクリプションではなく、期間のないプロダクトには Non-Subscriptions を使用します。追加機能や消耗型プロダクトなどに利用できます。 - **Consumables**: 消耗型アイテムは複数回購入できます。アプリのライフサイクル中に使い切るものです。ゲーム内通貨や追加アイテムが例として挙げられます。消耗型プロダクトはアクセスレベルに影響しないことに注意してください。買い切り購入でアクセスレベルを付与するには、**Non-Subscriptions** を使用してください。 - **Price (USD)**: プロダクトの USD 価格です。この価格を基準に、全国の価格が自動的に計算・設定されます。後から[国や地域ごとに価格をカスタマイズ](edit-product#set-country-specific-prices)することもできます。 <img src="/assets/shared/img/create-product-push.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '400px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. **Save & Continue** をクリックします。 6. App Store に公開する予定がある場合は、App Store 向けのプロダクト情報を設定します。 - **Product ID**: プロダクトの恒久的なユニーク ID を作成します。 - **Product group**: App Store Connect で作成した既存のプロダクトグループを選択するか、**Create new Product Group** をクリックしてグループ名を設定します。Adapty がグループを作成した後、ドロップダウンから選択できます。 - **Screenshot**: 提供するアイテムやサービスが明確に表示されているアプリ内課金のスクリーンショットをアップロードします。このスクリーンショットは App Store の審査にのみ使用され、App Store 上には表示されません。スクリーンショットのサイズとフォーマットの要件は[こちら](https://developer.apple.com/help/app-store-connect/reference/app-information/screenshot-specifications/)をご確認ください。 <img src="/assets/shared/img/push-app-store.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '400px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 7. **Push data to App Store** をクリックします。 :::warning このアプリで初めてのプロダクトの場合は、App Store Connect で手動で審査に提出する必要があります。これは初回のみ必要です。審査が完了すると、Adapty 上のプロダクトのステータスは自動的に更新されます。 ::: 8. Google Play に公開する予定がある場合は、Google Play 向けのプロダクト情報を設定します。 - **Base Product ID**: プロダクトの恒久的なユニーク ID を作成します。 - **Subscription**: Google Play Console で作成した既存のサブスクリプショングループを選択するか、**Create new Product Group** をクリックしてグループ名と ID を設定します。Adapty がグループを作成した後、ドロップダウンから選択できます。 :::note グレース期間とアカウント保留期間は、Play Store のルールに従ってデフォルト値が自動設定されます。後から Google Play Console で変更できます。 ::: <img src="/assets/shared/img/push-google-play.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '400px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 9. **Push data to Play Store** をクリックします。 10. iOS の場合は、ドロップダウンから **Free duration** を選択して初回オファー(無料トライアル)を設定します。この初期設定では無料トライアルの初回オファーを追加できます。メインプロダクトがストアの審査に通過したら、ストアコンソールの既存 ID を紐付けることで[さらにオファーを追加](offers)(プロモーションオファーやウィンバックオファーなど)できます。 <img src="/assets/shared/img/intro.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '400px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> :::important 初回オファーは Google Play と自動的に同期されません。App Store とは異なり、Google Play には「初回オファー」という独立したタイプがありません。無料トライアルや割引オファーはすべて、ベースプランの**オファー**として設定します。[Google Play Console でオファーを作成し、Adapty プロダクトに紐付けてください](google-play-offers)。 ::: 11. 最後に **Save** をクリックしてプロダクトの作成を確定します。 ## プロダクトを作成して既存のストアプロダクトに接続する \{#create-product-and-connect-existing-store-products\} :::warning 始める前に、以下を確認してください。 - 必要なストアとのインテグレーションが設定済みであること: - [App Store](initial_ios) - [Google Play](initial-android) - 必要なストアでプロダクトが作成済みであること: - [App Store](app-store-products) - [Google Play](android-products) **プロダクトをまだ作成していない場合**は、[ストアへのプッシュ](#create-product-and-push-to-store)ガイドに従って、Adapty とストアの両方に同時に作成することをおすすめします。 ::: <div style={{ maxWidth: '560px', margin: '0 auto 2rem', position: 'relative', aspectRatio: '16/9', width: '100%' }}> <iframe style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%' }} src="https://www.youtube.com/embed/nlkdKCF0SwY?si=VVigzHcpv3waKJmI" title="YouTube video player" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerPolicy="strict-origin-when-cross-origin" allowFullScreen /> </div> アプリに新しいプロダクトを追加するには: 1. Adapty のメインメニューから **[Products](https://app.adapty.io/products)** に移動します。 <img src="/assets/shared/img/products-tab.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. 右上の **Create product** をクリックします。Adapty はサブスクリプション、非消耗型(永続アクセスを含む)、消耗型アイテムなど、すべてのプロダクトタイプに対応しています。 3. **Connect an existing store product** を選択します。 <img src="/assets/shared/img/existing-product.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '400px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. 以下の情報を入力します。 - **Product name**: Adapty ダッシュボードで使用するプロダクト名を入力します。この名前は主に管理用ですので、Adapty ダッシュボード全体で使いやすい名前を自由に選んでください。 - **Access Level ID**: プロダクトが属する[アクセスレベル](access-level)を選択します。アクセスレベルは、プロダクトを購入した後に解放される機能を決定します。このリストには、事前に作成されたアクセスレベルのみ表示されます。`premium` アクセスレベルは Adapty でデフォルトで作成されていますが、[アクセスレベルを追加する](access-level)こともできます。 - **Subscription duration**: リストからサブスクリプションの期間を選択します。 - **Weekly/Monthly/2 Months/3 Months/6 Months/Annual**: サブスクリプションの期間。 - **Lifetime**: アプリのプレミアム機能を永続的に解放するプロダクトには、永続期間を使用します。 - **Non-Subscriptions**: サブスクリプションではなく、期間のないプロダクトには Non-Subscriptions を使用します。追加機能や消耗型プロダクトなどに利用できます。 - **Consumables**: 消耗型アイテムは複数回購入できます。アプリのライフサイクル中に使い切るものです。ゲーム内通貨や追加アイテムが例として挙げられます。消耗型プロダクトはアクセスレベルに影響しないことに注意してください。買い切り購入でアクセスレベルを付与するには、**Non-Subscriptions** を使用してください。 - **Price (USD)**: プロダクトの USD 価格です。プロダクトがすでにストアにある場合、この値はストアの実際の価格には影響しません。リストから任意の値を選択できます。後から Adapty ダッシュボード上で[地域ごとの価格をカスタマイズ](edit-product#set-country-specific-prices)することもできます。 <img src="/assets/shared/img/product-info.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '400px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. **Continue** をクリックします。 6. 各ストアのプロダクト情報を設定します。 - **App Store:** - **App Store Product ID:** デバイス上でプロダクトにアクセスするために使用する一意の識別子です。リストから選択してください。リストに表示されない場合は、App Store Connect での設定を確認し、正しくこのアプリに紐付けられているかご確認ください。 - **Play Store:** - **Google Play Product ID:** Play Store でのプロダクト識別子です。リストから選択してください。リストに表示されない場合は、Google Play Console での設定を確認し、正しくこのアプリに紐付けられているかご確認ください。 - **Base Plan ID:** Play Store でプロダクトのベースプランを定義するために使用する ID です。Play Store でサブスクリプションのプロダクト ID を追加する際は、ベースプラン ID の指定が必要です。ベースプランは、請求期間、更新タイプ(自動更新またはプリペイド)、および関連する価格を含むサブスクリプションの基本情報を定義します。Adapty では、同じサブスクリプションでも異なるベースプランの組み合わせはそれぞれ別のプロダクトとして扱われます。 - **Legacy fallback product**: フォールバックプロダクトは、古いバージョンの Adapty SDK(バージョン 2.5 以前)を使用するアプリ専用です。Google Play Console でプロダクトを後方互換としてマークすることで、Adapty は古い SDK バージョンで購入可能かどうかを識別できます。このフィールドには `<subscription_id>:<base_plan_id>` の形式で値を指定してください。 - **Stripe**: - **Stripe Product ID**: Stripe でのプロダクトの一意の識別子です。 - **Stripe Price ID**: Stripe の価格オブジェクトには価格金額だけでなく、税の扱い、ボリュームティア、サブスクリプション間隔なども含まれます。1 つのプロダクトに複数の価格を設定できるため、Adapty でプロダクトを作成する際は正しい価格 ID を指定してください。 - **Paddle**: - **Paddle Product ID**: Paddle でのプロダクトの一意の識別子です。 - **Paddle Price ID**: Paddle の価格オブジェクトには価格金額だけでなく、税の扱い、ボリュームティア、サブスクリプション間隔なども含まれます。1 つのプロダクトに複数の価格を設定できるため、Adapty でプロダクトを作成する際は正しい価格 ID を指定してください。 7. **オプション:** **Add custom store** をクリックすることで、任意のカスタムストアのプロダクトを追加できます。**Manage custom store info** ウィンドウでは、既存のカスタムストアを選択するか、新しいストアを追加してプロダクトと紐付けることができます。Adapty は App Store、Google Play、Stripe からのトランザクションのみを追跡することにご注意ください。カスタムストアの場合は、Adapty サーバーサイド API の Set transaction メソッドを使ってトランザクションを送信する必要があります。 8. **Save product** をクリックしてプロダクトの作成を完了します。プロダクトのステータス同期には最大 5 分かかる場合がありますので、テーブルに反映されるまでお待ちください。 9. 必要に応じて、プロダクトに[オファーを作成](create-offer)できます。オファーを追加するには **Yes, add offers** をクリックし、不要な場合は **No, thanks** をクリックします。 :::note 初回オファーは、プロダクトをストアにプッシュする際にのみ Adapty 上で作成されます。インポート時や既存のプロダクトの場合、初回オファーは同期されず Adapty には表示されませんが、アプリ内では正しく機能します。 ::: ## 次のステップ \{#next-steps\} おめでとうございます!Adapty にプロダクトを追加できました。次は何をしますか? - 初回オファーやプロモーションオファーをまだ設定していない場合は、今すぐ[設定](offers)できます。 - 設定済みの場合や後回しにする場合は、[ペイウォールの設定](quickstart-paywalls)に進んでアプリ内課金を有効にしましょう。 - ストアプロダクトの調整(地域別価格の設定やグレース期間の設定など)が必要な場合は、App Store Connect または Google Play Console で行ってください。 - 後から[プロダクトを編集する](edit-product)方法もご確認ください。 --- # File: edit-product --- --- title: "プロダクトの編集" description: "Adapty のサブスクリプションプロダクトを編集・管理して、収益トラッキングを改善しましょう。" --- Adapty では、プロダクトの名前、アクセスレベル、地域別価格、接続されているストア ID を編集したり、価格変更の履歴を追跡する監査ログを確認したりできます。サブスクリプションの期間はプロダクト作成後に変更できないため、変更が必要な場合は新しいプロダクトを作成してください。 :::warning プロダクトはどれでも編集できますが、すでに公開中のペイウォールで使用しているプロダクトを変更すると、アナリティクスに不整合が生じる可能性があります。 **アクセスレベル、App Store プロダクト ID、Play Store プロダクト ID の編集は推奨しません**。アナリティクスの精度に影響を与える恐れがあります。プロダクト ID のタイポなど、間違いを修正する場合に限り編集してください。 そのプロダクトをこれ以上使用しない場合は、新しいプロダクトを作成し、ペイウォールと A/B テストを更新することを強くお勧めします。 ::: ## プロダクトを編集する \{#edit-product\} プロダクトを編集するには: 1. Adapty のメインメニューから **[Products](https://app.adapty.io/products)** に移動します。 2. テーブル内のプロダクト行をクリックするか、プロダクトの横にある三点メニューをクリックして **Edit** を選択します。 3. 表示された **Edit** ウィンドウで必要な変更を加えます。このウィンドウのオプションについては、[プロダクトの作成](create-product)セクションをご覧ください。 4. **Save** をクリックします。 :::warning App Store Connect や Google Play Console で行った変更は Adapty に同期されません。Adapty に表示される価格はプロダクト作成時に設定されたものであり、ストアで価格を変更しても自動的に更新されません。 これは収益アナリティクスには影響しません。Adapty は収益データをストアから直接取得します。ダッシュボードの価格フィールドはあくまで参照用です。 ::: :::note アクセスレベルを変更した場合、その変更は新規サブスクリプションにのみ適用されます。既存のサブスクライバーは現在のアクセスレベルが維持され、次のサブスクリプション更新時に自動的に更新されます。 ::: <img src={require('./img/edit-product.png').default} style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## 国別価格を設定する \{#set-country-specific-prices\} Adapty ダッシュボード上で地域ごとに異なる価格を設定でき、その国別価格は App Store Connect や Google Play Console のプロダクトに自動的に反映されます。 国別価格を設定するには: 1. [編集用にプロダクトを開きます](#edit-product)。 2. **Download** をクリックして、ストアから正しい形式で現在の価格をエクスポートするか、新しい CSV ファイルを作成します。 <img src={require('./img/download-prices.webp').default} style={{ border: '1px solid #727272', /* border width and color */ width: '500px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. CSV ファイルで価格を更新します。[フォーマット](#csv-file-format)に従ってください。ある国の価格を変更しないまま残したり、ファイルに含めなかったりした場合、何も変更されません。CSV をアップロードすると、Adapty は価格を比較して異なるものだけを更新します。 4. **Edit** ウィンドウで **Upload** をクリックし、CSV ファイルを選択します。 <img src={require('./img/upload-prices.webp').default} style={{ border: '1px solid #727272', /* border width and color */ width: '500px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. 既存のサブスクライバーにも変更を適用したい場合は、**Apply to existing subscribers** を選択します。 6. 適用される変更内容を確認して、**Save changes** をクリックします。 <img src={require('./img/country-level-price.webp').default} style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### CSV ファイルのフォーマット \{#csv-file-format\} :::tip 同じアプリに類似したプロダクトがある場合や、異なるアプリで同じ価格を設定したい場合は、同じ CSV ファイルを再利用できます。 ::: CSV で価格を編集する最も簡単な方法は、[現在の価格が含まれたファイルをダウンロードして直接編集する](#set-country-specific-prices)ことです。 ご自身で作成する場合は、ファイルに以下のカラムが必要です: - `region_name` - `region_code` - `app_store_currency` - `app_store_requested_price` - `play_store_currency` - `play_store_requested_price` 例: ``` region_name,region_code,app_store_currency,app_store_requested_price,play_store_currency,play_store_requested_price United States,US,,8.99,,8.99 United Arab Emirates,AE,USD,8.99,AED,39.99 Germany,DE,USD,8.99,USD,8.99 ``` ## 監査ログを確認する \{#view-audit-log\} Adapty は各プロダクトのすべての価格変更を記録しているため、誰がいつ変更を行ったかを追跡できます。監査ログを確認するには: 1. Adapty のメインメニューから **[Products](https://app.adapty.io/products)** に移動します。 2. プロダクトの横にある三点メニューをクリックして **Audit log** を選択します。 監査ログテーブルには、各価格変更の日付、チームメンバーの名前と役割、変更件数が表示されます。 イベントの詳細な CSV を取得するには、そのイベントの行にあるダウンロードアイコンをクリックします。 <img src={require('./img/audit-log.webp').default} style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> --- # File: delete-product --- --- title: "プロダクトを削除する" description: "アプリの収益フローを妨げることなく、Adapty でサブスクリプションプロダクトを削除する方法をご確認ください。" --- 削除できるのは、ペイウォールで使用されていないプロダクトのみです。 プロダクトを削除するには: 1. Adapty メインメニューから **[Products](https://app.adapty.io/products)** に移動します。 2. プロダクトの横にある **3-dot** ボタンをクリックし、**Delete** を選択します。 <img src="/assets/shared/img/delete-product.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. 削除しようとしているプロダクトの名前を入力します。 <img src="/assets/shared/img/b945add-delete_product.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. **Delete forever** をクリックします。 --- # File: add-product-to-paywall --- --- title: "ペイウォールにプロダクトを追加する" description: "Adaptyのペイウォールにプロダクトを追加・管理する方法を説明します。" --- アプリのユーザーが[ペイウォール](paywalls)でプロダクトを表示・選択できるようにするには、以下の手順に従ってください。 1. [ペイウォールの設定](create-paywall)中に、**Products** タイトルの下にある **Add product** をクリックします。 2. 表示されるドロップダウンリストから、顧客に表示するプロダクトを選択します。リストには事前に作成済みのプロダクトのみ表示されます。プロダクトの順序はSDK側でそのまま反映されるため、ペイウォールを設定する際は表示順序を考慮することが重要です。また、必要に応じてプロダクトにオファーを指定することもできます。 <img src="/assets/shared/img/0479b51-ad_product_to_paywall.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. ペイウォールのステータスに応じて、**Create as draft** または **Save and publish** をクリックします。 なお、ペイウォールを作成した後は、ペイウォールの指標に影響を与える可能性があるため、プロダクトの編集・追加・削除は推奨されません。 --- # File: app-store-offers --- --- title: "App Store のオファー" description: "App Store のオファーを設定・管理してユーザーの継続率を高めましょう。" --- :::info このガイドを進める前に、[ストアのプロダクト](quickstart-products)を設定してください。 ::: App Store のオファーとは、自動更新サブスクリプション向けの特別割引・トライアル・値引きのことです。新規ユーザーの獲得やコンバージョン向上に役立つ割引やバンドルオファーが含まれます。 App Store には 4 種類のオファーがあり、Adapty はすべてに対応しています。 - **新規ユーザー向け[初回オファー](#introductory-offers)**: - 無料または割引サブスクリプション期間 - 対象は新規ユーザーのみ(初回オファーを使用したことがない、またはサブスクリプションを持ったことがないユーザー) - Adapty のプロダクトにリンクする必要はありません。Adapty は対象ユーザーがプロダクトを購入する際にオファーを自動的に適用します。 - **[プロモーションオファー](#promotional-offers)および[ウィンバックオファー](#win-back-offers)**: - Adapty は購入時にこれらのオファーを自動的に適用しますが、先にプロダクトとペイウォールにオファーを設定する必要があります。 - プロモーションオファーには、無料サブスクリプション期間・割合割引・固定価格割引が含まれます。すべてのユーザーが対象になれます。 - ウィンバックオファーには、無料サブスクリプション期間またはパーセント割引が含まれます。対象は解約済みユーザーのみです。 - **オファーコード**:詳細は [iOS でオファーコードを使う](making-purchases#redeem-offer-codes-in-ios)をご覧ください。 :::important App Store のオファーを使用するには、[サブスクリプションキー](app-store-connection-configuration#step-4-for-trials-and-special-offers--set-up-promotional-offers)を Adapty ダッシュボードにアップロードしてください。 ::: ## 初回オファー \{#introductory-offers\} Adapty は、ユーザーが対象の場合、iOS で初回オファーを自動的に適用します。 販売するプロダクトで初回オファーを有効にするには、App Store Connect で作成するだけで済みます。 1. App Store Connect でアプリを開き、**Monetization > Subscriptions** に切り替えます。 2. サブスクリプショングループを選択し、対象のサブスクリプションに移動します。サブスクリプションには期間が設定されている必要があります。 3. **View all Subscription Pricing** をクリックし、**Introductory offers** タブに切り替えます。**Set up introductory offer** をクリックします。 4. 初回オファーを利用可能にする国と地域を選択します。 5. 初回オファーの開始日と終了日を選択します。終了日を設けない場合は **No end date** を選択してください。**Next** をクリックします。 6. 初回オファーの種類を選択します。選択内容に応じて、オファーの期間と価格も設定する必要があります。詳細は [Apple のドキュメント](https://developer.apple.com/help/app-store-connect/manage-subscriptions/set-up-introductory-offers-for-auto-renewable-subscriptions)をご覧ください。 7. 内容を確認して **Confirm** をクリックします。 この設定が完了したら、Adapty での追加作業は不要です。対象ユーザーがプロダクトを購入する際にオファーが自動的に有効になります。オファーの対象ユーザーにのみ、このプロダクトを含むペイウォールが表示されるようにしてください。 ## プロモーションオファー \{#promotional-offers\} Adapty は、ユーザーが対象の場合、プロモーションオファーを自動的に適用します。まず App Store Connect でオファーを設定してから、Adapty のプロダクトとペイウォールに追加してください。 1. App Store Connect でアプリを開き、左メニューから **Monetization > Subscriptions** に切り替えます。 2. サブスクリプショングループを選択し、対象のサブスクリプションに移動します。サブスクリプションには期間が設定されている必要があります。 3. **View all Subscription Pricing** をクリックし、**Promotional offers** タブに切り替えます。**Set up promotional offer** をクリックします。 4. プロモーションオファーの詳細を設定します。これらの値は作成後に変更できず、再利用されるため、慎重に選択してください。 - **Promotional offer reference name**:プロモーションオファーの名前。ユーザーには表示されません。 - **Promotional offer identifier**:プロモーションオファーの識別コード。Adapty にオファーを追加する際に使用します。 5. プロモーションオファーの種類を選択します。種類によって、ユーザーが割引価格で支払うか無料期間を得るかが決まります。割引の場合は **Pay as you go** または **Pay up front** を選択し、無料サブスクリプション期間の場合は **Free** を選択してください。その後、オファーの期間と価格を設定します。詳細は [Apple のドキュメント](https://developer.apple.com/help/app-store-connect/manage-subscriptions/set-up-promotional-offers-for-auto-renewable-subscriptions)をご覧ください。 6. 必要に応じて国や地域ごとに異なる価格を設定し、**Next** をクリックします。 7. 内容を確認して **Confirm** をクリックします。 8. Adapty に[プロモーションオファーを追加](create-offer)します。 ## ウィンバックオファー \{#win-back-offers\} :::important ウィンバックオファーを作成する前に、サブスクリプションが App Review によって承認されている必要があります。 ::: Adapty は、ユーザーが対象の場合、ウィンバックオファーを自動的に適用します。まず App Store Connect でオファーを設定してから、Adapty のプロダクトとペイウォールに追加してください。 1. App Store Connect でアプリを開き、左メニューから **Monetization > Subscriptions** に切り替えます。 2. サブスクリプショングループを選択し、対象のサブスクリプションに移動します。サブスクリプションには期間が設定されている必要があります。 3. **View all Subscription Pricing** をクリックし、**Win-back offers** タブに切り替えます。**Create offer** をクリックします。 4. ウィンバックオファーの詳細を設定します。これらの値は作成後に変更できません。 - **Reference name**:オファーの名前。ユーザーには表示されません。 - **Offer identifier**:オファーの識別コード。Adapty にオファーを追加する際に使用します。 5. オファーの種類・期間・価格を設定します。詳細は [Apple のドキュメント](https://developer.apple.com/help/app-store-connect/manage-subscriptions/set-up-win-back-offers)をご覧ください。 6. 内容を確認して **Confirm** をクリックします。 7. Adapty に[オファーを追加](create-offer)します。 ## 次のステップ \{#next-steps\} オファーを追加したら、続けて以下の設定を行ってください。 - **Google Play アプリ**もお持ちの場合は、[Google Play のオファー](google-play-offers)を設定してください。 - **プロモーションオファーまたはウィンバックオファー**がある場合は、[Adapty に追加](create-offer)してください。 - **初回オファーのみ**でプロモーションオファーやウィンバックオファーがない場合は、これで完了です。[Adapty のオファー処理の仕組み](create-offer#how-adapty-works-with-offers)のセクションも参考になるかもしれません。 --- # File: google-play-offers --- --- title: "Google PlayのオファーGoogle Play" description: "Google Playのオファーを設定してアプリの収益化とリテンションを向上させましょう。" --- Google Playでは、あらゆる種類のオファー(無料トライアルや割引支払いなど)は**オファー**として追加されます。オファーを作成するには、まずサブスクリプションを作成し、自動更新ベースプランを追加する必要があります。 オファーは常にサブスクリプションのベースプランに対して作成されます。下のスクリーンショットでは、`premium_access`(1)というサブスクリプションに、`1-month`(2)と`1-year`(3)という2つのベースプランが含まれているのを確認できます。 <img src="/assets/shared/img/c0b1dfa-001930-November-03-XYnbieeu.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Google Play Consoleでオファーを作成するには: 1. **Add offer**をクリックし、リストからベースプランを選択します。 <img src="/assets/shared/img/75a5d69-eb0bc9a-001931-November-03-eQdthUMx.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. オファーIDを入力します。後で分析やAdaptyダッシュボードで使用されるため、わかりやすい名前をつけてください。 <img src="/assets/shared/img/ff282c2-c0b1dfa-001930-November-03-XYnbieeu.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. 利用資格の条件を選択します: 1. **New customer acquisition**:過去にこのオファーを利用したことのない新規サブスクライバーのみが対象になります。最も一般的なオプションで、デフォルトとして使用することを推奨します。 2. **Upgrade**:他のサブスクリプションからアップグレードするユーザーが対象になります。たとえば、ブロンズからゴールドプランへのアップグレードなど、既存のサブスクライバーにより高額なプランを訴求したい場合に使用します。 3. **Developer determined**:アプリのコードからオファーの利用対象を制御できます。無料または割引サブスクリプションを繰り返し有効化される可能性があるため、本番環境での使用には注意が必要です。解約済みサブスクライバーのウィンバックに適したオファータイプです。 <img src="/assets/shared/img/ee302dc-a506e5a-001934-November-03-TVBLOz2L.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. オファーに最大2つの料金フェーズを追加します。利用可能なフェーズタイプは3種類あります: 1. **Free trial**:設定した期間(最短3日)、サブスクリプションを無料で使用できます。最も一般的なオファーです。 2. **Single payment**:最初にまとめて支払うことでサブスクリプションが割引になります。例えば、通常は月額$9.99のプランが、このオファータイプでは最初の3ヶ月で$19.99(30%割引)になります。 3. **Discounted recurring payment**:最初の`n`期間、サブスクリプションが割引になります。例えば、通常は月額$9.99のプランが、このオファータイプでは最初の3ヶ月間、毎月$4.99(50%割引)になります。 オファーには2つのフェーズを設定できます。この場合、最初のフェーズはFree trialとし、2番目はSingle paymentまたはDiscounted recurring paymentにする必要があります。この順番で適用されます。 <img src="/assets/shared/img/d6267f3-a48f79e-001936-November-03-A13wutRh.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> :::important ペイウォールビルダーで作成したペイウォールは、複数フェーズのGoogle Playサブスクリプションオファーのうち、最初のフェーズのみを表示します。ただし、ユーザーがプロダクトを購入した際には、Google Playで設定したとおりすべてのオファーフェーズが適用されますのでご安心ください。 ::: 5. アプリで使用するためにオファーをアクティベートします。 <img src="/assets/shared/img/d3fc09b-f149ba6-001937-November-03-MO9Gz3ap.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 6. [AdaptyへのオファーAdaptyへのオファーの追加](create-offer)に進みます。 :::note オファーIDは、異なるベースプラン間で同じものを使用できます。 ::: ## 次のステップ \{#next-steps\} オファーを追加したら、次のセットアップに進みます: - **App Storeにもアプリがある**場合は、[App Storeガイド](app-store-offers)をご覧ください。 - **Google Playのみにアプリがある**場合は、[このガイド](create-offer)に従ってAdaptyにオファーを追加してください。 --- # File: create-offer --- --- title: "Adaptyへのオファーの追加" description: "Adaptyのツールを使って特別なサブスクリプションオファーを作成・管理しましょう。" --- Adaptyでは、新規・既存・解約済みのサブスクライバーに対してトライアルや割引を提供できます。 App Store ConnectやGoogle Play Consoleで設定した後、Adaptyに追加するには2つのステップが必要です: 1. [ストアのオファーIDを使ってAdaptyのプロダクトにオファーを追加する。](#1-create-offer) 2. [フローまたはペイウォールでオファーを表示する。](#2-display-offer) :::warning 初回オファー(App Store)は、ユーザーが対象である場合に自動的に適用されます。Adaptyのプロダクトに追加する必要はありません。 このガイドでは、プロモーションオファー(App Store)、ウィンバックオファー(App Store)、およびすべてのGoogle Playオファーの設定方法を説明します。 ::: ## 0. 開始前の確認事項 \{#0-before-you-start\} Adaptyでオファーの設定を始める前に、以下を確認してください: 1. 必要なオファーをストアで作成済みであること: - [App Store](app-store-offers) - [Google Play](google-play-offers) 2. Adaptyで[プロダクト](create-product)を作成し、IDを追加済みであること。 3. App Storeの場合:[プロモーションオファー用のアプリ内購入キー](app-store-connection-configuration#step-4-for-trials-and-special-offers--set-up-promotional-offers)をアップロード済みであること。 ## 1. Adaptyのプロダクトにオファーを追加する \{#1-add-offer-to-product-in-adapty\} Play StoreおよびApp Storeのプロモーションオファー、またはApp StoreのWin-backオファーをアプリストアで設定したら、Adaptyへの追加はシンプルです: 1. Adaptyのメインメニューから[**Products**](https://app.adapty.io/products)を開き、オファーを追加したいプロダクトを探します。 2. オファーを追加したいプロダクトを見つけ、**Actions**列のプロダクト横にある**3-dot**ボタンをクリックして**Edit**を選択します。 3. **Edit product**ウィンドウで、**+**をクリックして**Add offers**を選択します。 4. **Add offer**をクリックします。 5. プロダクトのオファー詳細を入力します。 オファーのフィールドは以下のとおりです: - **Offer name**:Adaptyで識別しやすいようにオファー名を入力します。任意の名前を使用できます。 - **App Store Offer type**:追加するApp Storeオファーのタイプ(PromotionalまたはWin-back)を選択します。(初回オファーは追加不要です—対象の場合は自動的に適用されます。) - **App Store Offer ID**:[App Storeで設定した](app-store-products)オファーの固有IDです。 - **Play Store Offer ID**:同様に、[Play Storeで設定した](android-products)オファーの固有IDです。 :::tip **App Store Offer ID**または**Play Store Offer ID**フィールドが非アクティブの場合は、**Products**タブに切り替えてプロダクトIDを選択してください。 ::: 6. (任意)**Add offer**をクリックして、必要に応じてオファーを追加します。 7. **Save**をクリックしてオファーをプロダクトに追加します。 ## 2. オファーを表示する \{#2-display-offer\} オファーをプロダクトに紐付けたら、ユーザーがそのプロダクトを見る場所—フローまたはペイウォール—に表示します。 ### フローにオファーを追加する \{#add-offer-to-flow\} [フロービルダー](adapty-flow-builder)では、オファーはProductsエレメントのプロダクトに紐付けられます。まずプロダクトエレメントを追加してプロダクトを割り当ててください—[購入の設定](paywall-product-block)を参照してください。 オファーを紐付けるには: 1. キャンバス上で、オファーを表示するプロダクトカードを選択します。 2. 右側のパネルの**Product**で、プロダクトを選択し、**Select offer (optional)**ドロップダウンからオファーを選びます。 ### ペイウォールにオファーを追加する \{#add-offer-to-paywall\} :::info **live**ステータスのペイウォールにオファーを追加することはできません。既存のペイウォールにオファーを追加したい場合は、[複製](duplicate-paywalls)して新しいペイウォールでプロダクトを設定してください。 ::: アプリのユーザーが[ペイウォール](paywalls)内でオファーを確認・選択できるようにするには、次の手順に従ってください: 1. ペイウォールの作成または編集時に、**General**タブでオファーを追加したプロダクトを追加します。 2. このプロダクトに作成したオファーを**Offer**リストから選択します。リストはオファーが設定されているプロダクトにのみ表示されます。 3. 必要に応じてプロダクトとオファーを追加できますが、各プロダクトにつき1つのオファーのみ追加できます。 ## Adaptyでのオファーの動作について \{#how-adapty-works-with-offers\} オファーの動作について以下の点にご注意ください: - ユーザーがオファーの対象である場合、Adaptyは購入時に設定したオファーを自動的に適用します。 - App StoreでプロダクトにIntroductory offerとPromotional offerの両方が設定されている場合、対象ユーザーはまずIntroductory offerを受け取ります。その期間が終了した後、ユーザーがまだPromotional offerの対象であり、Adaptyでそのオファーを設定している場合、再度プロダクトを購入しようとしたときに適用されます。 - オファーの適用方法をより細かく制御したい場合や、特定のケースでオファーなしにプロダクトを販売したい場合は、いくつかの選択肢があります: - App StoreまたはGoogle Play Consoleで対象条件を設定する - App StoreまたはGoogle Play Consoleでオファーなしの別プロダクトを作成する - Adaptyでオファーなしの別プロダクトを作成し、両方のプロダクトバリアントを含むペイウォールを[プレースメント](placements)に追加して、オーディエンス[セグメント](segments)を使ってどのペイウォールをどのユーザーに表示するかを制御する。たとえば、**Subscription product**や**Paid access level**に基づいたセグメントを作成したり、[カスタム属性](profiles-crm)を使って独自のロジックを実装したりすることができます。 --- # File: create-access-level --- --- title: "アクセスレベルの作成" description: "ユーザーセグメンテーションを改善するために、Adaptyでアクセスレベルを作成・割り当てる方法を説明します。" --- アクセスレベルを使うと、プロダクトIDをハードコードすることなく、アプリ内でユーザーに許可する操作を制御できます。各プロダクトは、ユーザーが特定のアクセスレベルを得られる期間を定義します。ユーザーが購入を行うと、Adaptyはサブスクリプションの場合は一定期間、永続購入の場合は永続的にアプリへのアクセスを付与します。 Adapty ダッシュボードでアプリを作成すると、`premium` アクセスレベルが自動的に生成されます。これはデフォルトのアクセスレベルとして機能し、削除することはできません。 :::tip [Developer CLI](developer-cli-reference#adapty-access-levels-create) を使用してアクセスレベルをプログラムで作成することもできます。 ::: 新しいアクセスレベルを作成するには: 1. Adaptyのメインメニューから **[Products](https://app.adapty.io/access-levels)** に移動し、**Access levels** タブを選択します。 <img src="/assets/shared/img/access-level-list.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. **Create access level** をクリックします。 <img src="/assets/shared/img/b8646ca-image.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. **Create access level** ウィンドウで、IDを設定します。このIDはモバイルアプリ内での識別子として機能し、ユーザーが購入した際に追加機能へのアクセスを有効にします。また、この識別子はアプリ内で他のアクセスレベルと区別するためにも役立ちます。わかりやすく、理解しやすいIDを設定してください。 4. **Create access level** をクリックして、アクセスレベルの作成を確定します。 --- # File: assigning-access-level-to-a-product --- --- title: "プロダクトにアクセスレベルを割り当てる" description: "サブスクリプション管理を最適化するために、プロダクトにアクセスレベルを割り当てます。" --- すべての[プロダクト](product)には、購入時にユーザーが対応するコンテンツにアクセスできるよう、アクセスレベルを関連付ける必要があります。Adapty はサブスクリプションの期間を自動的に判別し、それをアクセスレベルの有効期限として設定します。永続アクセスのプロダクトを購入した場合、アクセスレベルは有効期限なしで永続的に有効になります。 プロダクトにアクセスレベルを紐付けるには: 1. [プロダクトの設定](create-product)中に、**Access Level ID** リストからアクセスレベルを選択します。 <img src="/assets/shared/img/access-level-product.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. **Save** をクリックします。 --- # File: give-access-level-to-specific-customer --- --- title: "特定の顧客にアクセスレベルを付与する" description: "Adaptyの高度なツールを使用して、顧客に特定のアクセスレベルを割り当てます。" --- Adapty ダッシュボードから、特定の顧客のアクセスレベルを手動で調整できます。これはサポート対応などの場面で特に便利です。たとえば、素晴らしいレビューを投稿してくれたお礼として、ユーザーのプレミアム利用期間を1週間延長したい場合などに活用できます。 ## Adapty ダッシュボードで特定の顧客にアクセスレベルを付与する \{#give-access-level-to-a-specific-customer-in-the-adapty-dashboard\} 1. Adapty のメインメニューから **[Profiles and Segments](https://app.adapty.io/placements)** に移動します。 <img src="/assets/shared/img/profiles-list.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. アクセスを付与したい顧客をクリックします。 3. **Add access level** をクリックします。 <img src="/assets/shared/img/add-access-level.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. 付与するアクセスレベルと、その顧客に対する有効期限を選択します。 5. **Apply** をクリックします。 ## API で特定の顧客にアクセスレベルを付与する \{#give-access-level-to-a-specific-customer-via-api\} Adapty API を使用して、サーバーから顧客にアクセスレベルを付与することもできます。紹介報酬やプロダクトに関連するその他のイベントに対してボーナスを提供する場合に便利です。詳しくは [サーバーサイド API でアクセスレベルを付与する](api-adapty/operations/grantAccessLevel) のページをご覧ください。 --- # File: local-access-levels --- --- title: "ローカルアクセスレベル" description: "一時的な障害発生時にアクセスレベルを管理します。" --- :::important 以下の点に注意してください: - ローカルアクセスレベルは、Adapty SDK バージョン 3.12 以降でサポートされています。 - セキュリティ上の理由から、Android ではデフォルトでローカルアクセスレベルが無効になっています。必要な場合は、SDK のアクティベーション時に有効にしてください: [Android](sdk-installation-android#enable-local-access-levels)、[React Native](sdk-installation-reactnative)、[Flutter](sdk-installation-flutter#enable-local-access-levels-android)。 ::: 設定した各プロダクトには [**アクセスレベル**](access-level) が紐付けられています。ユーザーが購入を行うと、Adapty SDK はそのアクセスレベルをユーザーの[プロファイル](profiles-crm)に付与します。アプリ内の有料コンテンツへのアクセス可否の判定には、このアクセスレベルを使用する必要があります。 Adapty SDK は非常に信頼性が高く、サーバーが利用できなくなるケースはほとんどありません。しかし、万が一そのような状況が発生しても、ユーザーが気づくことはありません。 ユーザーが購入を行ったとき、Adapty がレスポンスを受信できない場合、SDK はストアで直接購入を検証する処理に切り替わります。これによりアクセスレベルはアプリ内でローカルに付与され、有効にするための追加設定は不要です。SDK がバックグラウンドで自動的に処理するため、ユーザーは通常どおり購入したコンテンツにアクセスできます。 ローカルアクセスレベルの動作について、以下の点に注意してください: - ユーザーがオンラインに戻ると、トランザクション情報が自動的に Adapty サーバーへ送信され、サーバーはそのトランザクションをユーザープロファイルに適用して、更新されたプロファイルを SDK に返します。 - データが送信されるまで、更新された情報は Adapty アナリティクスに反映されません。 - ローカルアクセスレベルは、Adapty サーバーがダウンしている場合にのみ機能します。それ以外の場合、SDK はキャッシュされたデータを使用します。 - ローカルアクセスレベルは消耗型アイテムには機能しません。ただし、Adapty ダッシュボードで消耗型アイテムにサブスクリプションタイプ(月次、年次、週次など)が設定されている場合は除きます。 --- # File: choose-meaningful-placements --- --- title: "意味のあるプレースメントの選び方" description: "Adaptyを使ってフローとペイウォールのプレースメントを最適化し、ユーザーエンゲージメントと収益を向上させましょう。" --- [プレースメントを作成する](create-placement)際は、アプリの論理的なフローと、ユーザーに提供したいエクスペリエンスを考慮することが重要です。ほとんどのアプリでは、実験を実施できる能力を損なわずに済む[プレースメント](placements)の数は5つ以下が目安です。以下はプレースメントの構成例です。 <img src="/assets/shared/img/placement-flows.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 1. **オンボーディングフロー:** このステージは、ユーザーがアプリと最初に接触する場面です。フロー、オンボーディング、ペイウォールのプレースメントを組み合わせて、アプリの価値提案をユーザーに紹介する絶好の機会です。サブスクリプションの80%以上はオンボーディング中に有効化されるため、ここで最も収益性の高いサブスクリプションを訴求することが重要です。Adaptyを使えば、オーディエンスに応じて異なる[フロー](adapty-flow-builder)、[オンボーディング](onboardings)、[ペイウォール](paywalls)を簡単に設定でき、A/B テストで最適な選択肢を見つけることができます。たとえば、米国のユーザーに対してより高額なサブスクリプションを50%の確率で表示するA/B テストを実施できます。 2. **アプリ設定:** オンボーディング中にサブスクリプションしなかったユーザーに対して、アプリ内にフローまたはペイウォールのプレースメントを設置できます。これはアプリ設定内や、ユーザーが特定のターゲットアクションを完了した後などに配置できます。アプリ内のユーザーはサブスクリプションをより慎重に検討する傾向があるため、ここで提供するプロダクトはオンボーディング段階のものよりやや安価に設定するとよいでしょう。 3. **プロモ:** フローやペイウォールを複数回見てもサブスクリプションしなかったユーザーには、価格が高すぎるか、サブスクリプション自体に躊躇している可能性があります。この場合、最も手頃なサブスクリプションや永続アクセスプロダクトを含む特別オファーを表示できます。これにより、価格を重視するユーザーやサブスクリプションに懐疑的なユーザーの購買意欲を高めることができます。 ほとんどのアプリはこれと同様のロジックとプレースメント構成を持ち、ユーザージャーニーとフロー・ペイウォール・オンボーディング・A/B テストを表示してコンバージョンと収益を促進できる重要なポイントに沿って設計されます。各プレースメントで設定を行い、マネタイズ戦略を実験・最適化しましょう。 --- # File: create-placement --- --- title: "プレースメントを作成する" description: "Adapty でプレースメントを作成・管理して、フローとペイウォールのパフォーマンスを向上させましょう。" --- [プレースメント](placements)とは、モバイルアプリ内でフロー、ペイウォール、オンボーディング、または A/B テストを表示できる特定の場所のことです。たとえば、サブスクリプションの選択画面をスタートアップフローに表示したり、ゲームでコインが不足したときに消耗型アイテム(ゴールドコインなど)を表示したりできます。 同じフロー、ペイウォール、オンボーディング、または A/B テストを複数のプレースメントで表示したり、異なるユーザーセグメント(Adapty では「オーディエンス」と呼びます)に対して異なるコンテンツを表示したりすることも可能です。 適切なプレースメントの選び方については、[意味のあるプレースメントを選ぶ](choose-meaningful-placements)セクションをご参照ください。 :::tip [Developer CLI](developer-cli-reference#adapty-placements-create) を使ってプレースメントをプログラムで作成することもできます。 ::: :::info プレースメントの作成プロセスはフロー、ペイウォール、オンボーディングで似ていますが、1 つのプレースメントで複数のタイプを兼用することはできません。プレースメントの種類ごとに処理される指標が異なるためです。 ::: ## プレースメントを作成・設定する \{#create-and-configure-a-placement\} 1. Adapty のメインメニューから **[Placements](https://app.adapty.io/placements)** に移動します。作成したいプレースメントの種類に応じて、**Flows**、**Paywalls**、または **Onboardings** タブに切り替えます。 2. **Create placement** をクリックします。 <img src="/assets/shared/img/create-placement-2.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. **Placement name** を入力します。これは Adapty ダッシュボード内の内部識別子です。後から編集することもできます。 4. **Placement ID** を入力します。この ID は、Adapty SDK でプレースメントの[フロー](adapty-flow-builder)、[ペイウォール](paywalls)、[オンボーディング](onboardings)、[A/B テスト](ab-tests)を呼び出す際に使用します。各プレースメントで一意のため、後から編集することはできません。 次に、プレースメントにフロー、ペイウォール、オンボーディング、または A/B テストを割り当てます。Adapty は[セグメント](segments)に基づくユーザーセグメントである[オーディエンス](audience)をサポートしており、異なるユーザーグループに異なるコンテンツを表示できます。ターゲティングが不要な場合は、デフォルトの *All users* オーディエンスがすべてのユーザーをカバーします。 :::note 続行する前に、実行したいフロー、ペイウォール、オンボーディング、またはA/B テストと、指定したいオーディエンスを作成済みであることを確認してください。 ::: 1. **Placements/ Your placement** ウィンドウで、デフォルトの *All users* オーディエンスに表示するフロー、ペイウォール、オンボーディング、またはA/B テストを追加します。これを行うには、**Run flow**、**Run paywall**、または **Run A/B test** ボタン(ラベルはプレースメントの種類によって異なります)をクリックし、ドロップダウンリストから目的のフロー、ペイウォール、オンボーディング、またはA/B テストを選択します。 2. プレースメントで複数のオーディエンスを使用して、異なるユーザーグループ向けにパーソナライズされたコンテンツを作成したい場合は、**Add audience** ボタンをクリックして、リストから目的のユーザーセグメントを選択します。 <Zoom> <img src="/docs/img/placement-add-audience.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> </Zoom> 3. このオーディエンスに表示するフロー、ペイウォール、オンボーディング、またはA/B テストを追加します。 4. 必要な数のオーディエンスを追加します。 5. 複数のオーディエンスがある場合は、オーディエンスの優先順位が正しく設定されているか確認してください。 6. **Save and publish** ボタンをクリックします。 プレースメントを保存して公開したら、準備完了です。アプリのコードで **Placement ID** を使用してコンテンツを取得・表示してください。 ## 次のステップ \{#next-steps\} アプリにペイウォールを表示する: [iOS](ios-present-paywalls) | [Android](android-present-paywalls) | [React Native](react-native-present-paywalls) | [Flutter](flutter-present-paywalls) | [Unity](unity-present-paywalls) | [Kotlin Multiplatform](kmp-present-paywalls) | [Capacitor](capacitor-present-paywalls) アプリにオンボーディングを表示する: [iOS](ios-present-onboardings) | [Android](android-present-onboardings) | [React Native](react-native-present-onboardings) | [Flutter](flutter-present-onboardings) | [Unity](unity-present-onboardings) | [Kotlin Multiplatform](kmp-present-onboardings) | [Capacitor](capacitor-present-onboardings) --- # File: edit-placement --- --- title: "プレースメントを編集する" description: "Adaptyでプレースメントを編集して、フローとペイウォールの表示およびユーザーエンゲージメントを最適化する方法を説明します。" --- [プレースメント](placements)は、フロー、ペイウォール、オンボーディング、またはA/B テストを表示できるモバイルアプリ内の特定の場所を指します。たとえば、サブスクリプションの選択画面をスタートアップフローに表示したり、ゲームでコインが不足したときに消耗型アイテム(ゴールデンコインなど)を提示したりすることができます。 同じまたは異なるフロー、ペイウォール、オンボーディング、またはA/B テストを、複数のプレースメントやユーザーセグメント(Adaptyではオーディエンスと呼びます)に表示する柔軟性があります。 既存のプレースメントを編集するには: 1. Adaptyのメインメニューから **[Placements](https://app.adapty.io/placements)** に移動します。編集したいプレースメントの種類に応じて、**Flows**、**Paywalls**、または **Onboardings** タブに切り替えます。 2. 編集したいプレースメントをクリックします。 3. 右上の **Edit placement** をクリックします。 4. 必要な変更を加えます。このウィンドウのオプションについて詳しくは、[プレースメントを作成する](create-placement)セクションをご覧ください。 5. **Save and publish** ボタンをクリックして変更を確定します。 --- # File: export-placements --- --- title: "プレースメントのエクスポート" description: "Adaptyでプレースメントをエクスポートして、フローとペイウォールの表示状況やユーザーエンゲージメントを最適化する方法を学びましょう。" --- 複数のフロー、ペイウォール、オンボーディングを扱う場合、どのユーザーにどれが表示されているかを把握することが重要です。[プレースメント](placements)の設定をCSVファイルにエクスポートすると、各オーディエンスに対してどのフロー/ペイウォール/オンボーディングが表示されるかを確認でき、変更後や実験中のセットアップをレビューするのに役立ちます。 :::tip サーバーサイドAPIを利用したほうが便利な場合は、[APIでプレースメントをエクスポート](api-export-analytics/operations/retrievePlacementInfo)することもできます。 ::: フロー、ペイウォール、またはオンボーディングのプレースメントをエクスポートするには: 1. メインメニューの **[Placements](https://app.adapty.io/placements)** に移動します。**Flows**、**Paywalls**、または **Onboardings** タブに切り替えてください。各タイプのプレースメントは個別にエクスポートされます。 2. **Export to CSV** をクリックします。 <img src="/assets/shared/img/export-placement.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> エクスポートされたCSVファイルには、プレースメントに関する以下の情報が含まれます: - プレースメントID - プレースメント名 - オーディエンス名 - セグメント名 - クロスプレースメント A/B テスト名 - A/B テスト名 - フロー名、ペイウォール名、またはオンボーディング名(エクスポートしたタブによって異なります) :::note クロスプレースメント A/B テストはフローのプレースメントには対応していないため、フローのエクスポートではその列は空になります。 ::: --- # File: delete-placement --- --- title: "プレースメントの削除" description: "フローやペイウォールのパフォーマンスに影響を与えずに、Adapty でプレースメントを削除する方法をご確認ください。" --- [プレースメント](placements)は、モバイルアプリ内でフロー、ペイウォール、オンボーディング、または A/B テストを表示する特定の場所を指定するものです。 :::danger 任意のプレースメントを削除することは可能ですが、モバイルアプリで現在使用中のプレースメントを削除しないよう十分に注意してください。アクティブなフローやペイウォールのプレースメントを削除すると、[フォールバックペイウォールを設定している場合](fallback-paywalls)はそれが永続的に表示され続け、リリース済みのアプリバージョンでは動的なフローやペイウォールに切り替えることが一切できなくなります。 ::: 既存のプレースメントを削除するには、次の手順に従ってください。 1. Adapty のメインメニューから **[Placements](https://app.adapty.io/placements)** に移動します。削除したいプレースメントの種類に応じて、**Flows**、**Paywalls**、または **Onboardings** タブに切り替えます。 2. プレースメントの横にある **3-dot** ボタンをクリックし、**Delete** オプションを選択します。 <img src="/assets/shared/img/delete-placement.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. 表示された **Delete placement** ウィンドウで、削除しようとしているプロダクト名を入力します。 <img src="/assets/shared/img/8177c51-delete_placement.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **Delete forever** ボタンをクリックして削除を確定します。 --- # File: add-audience-paywall-ab-test --- --- title: "オーディエンスとフロー、ペイウォール、またはA/Bテストをプレースメントに追加する" description: "Adaptyで異なるオーディエンスセグメントに対してフローとペイウォールのA/Bテストを実施します。" --- Adaptyの**オーディエンス**は、[セグメント](segments)で定義されたユーザーのグループです。オーディエンスを使うことで、フロー、ペイウォール、オンボーディング、A/Bテストを適切なユーザーに表示できます。各グループに最適なコンテンツが届くよう、フィルターを使ってセグメントを作成しましょう。 [プレースメント](placements)にオーディエンスを追加すると、特定のユーザーグループに対してフロー、ペイウォール、オンボーディング、またはA/Bテストをターゲティングできます。オーディエンスをプレースメントに紐付けることで、適切なユーザーが、アプリの利用フローの適切なタイミングで、適切なコンテンツを目にできるようになります。 フロー、ペイウォール、オンボーディング、またはA/Bテストを追加したいプレースメントを開くか、[Placements](https://app.adapty.io/placements) メニューから新しく作成してください。 :::note 続行する前に、実行したいフロー、ペイウォール、オンボーディング、またはA/B テストと、指定したいオーディエンスを作成済みであることを確認してください。 ::: 1. **Placements/ Your placement** ウィンドウで、デフォルトの *All users* オーディエンスに表示するフロー、ペイウォール、オンボーディング、またはA/B テストを追加します。これを行うには、**Run flow**、**Run paywall**、または **Run A/B test** ボタン(ラベルはプレースメントの種類によって異なります)をクリックし、ドロップダウンリストから目的のフロー、ペイウォール、オンボーディング、またはA/B テストを選択します。 2. プレースメントで複数のオーディエンスを使用して、異なるユーザーグループ向けにパーソナライズされたコンテンツを作成したい場合は、**Add audience** ボタンをクリックして、リストから目的のユーザーセグメントを選択します。 <Zoom> <img src="/docs/img/placement-add-audience.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> </Zoom> 3. このオーディエンスに表示するフロー、ペイウォール、オンボーディング、またはA/B テストを追加します。 4. 必要な数のオーディエンスを追加します。 5. 複数のオーディエンスがある場合は、オーディエンスの優先順位が正しく設定されているか確認してください。 6. **Save and publish** ボタンをクリックします。 --- # File: change-audience-priority --- --- title: "プレースメントのオーディエンス優先度を変更する" description: "Adaptyでオーディエンスの優先度を調整して、ユーザーにパーソナライズされたオファーをターゲティングする方法。" --- 1つの[プレースメント](placements)に複数のオーディエンスを設定している場合、ユーザーが複数のオーディエンスに属することがあります。たとえば、「初心者」「ランナー」といったオーディエンスと「全ユーザー」のような汎用オーディエンスを定義している場合、ユーザーが複数のカテゴリに当てはまるとき、どのオーディエンスを優先して適用するかを決めることが重要です。 <img src="/assets/shared/img/afee54f-2.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> このような場合、オーディエンス優先度が重要になります。オーディエンス優先度は数値による順序で、#1 が最も高い優先度を持ちます。これにより、オーディエンスをチェックする順番が決まります。簡単に言うと、オーディエンス優先度はペイウォール、オンボーディング、またはA/Bテストを表示する際にどのオーディエンスを最初に適用するかを Adapty が判断するための指針です。優先度が低いオーディエンスは、条件に合うユーザーが他のより高い優先度のオーディエンスに割り振られてしまい、スキップされる可能性があります。 クロスプレースメントオーディエンス([クロスプレースメントA/Bテスト](ab-tests#ab-test-types)向けに作成されたもの)は、常に通常のオーディエンスより優先されます。 「全ユーザー」オーディエンスは、他のどのオーディエンスにも一致しないすべてのユーザーを含むフォールバックであるため、常に最低優先度となります。 プレースメントのオーディエンス優先度を調整するには: 1. 新しいプレースメントの作成中または既存のプレースメントの編集中に、**Edit priority** をクリックします。このボタンは、プレースメントに少なくとも3つのオーディエンス(「全ユーザー」とその他2つ)が追加されている場合にのみ表示されます。それ未満の場合は順序が自明のため(「全ユーザー」が最後)、ボタンは表示されません。 <img src="/assets/shared/img/edit-priority.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. 表示された **Edit audience priorities** ウィンドウで、オーディエンスをドラッグ&ドロップして正しい順序に並べ替えます。 <img src="/assets/shared/img/reorder_audiences.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. **Save** ボタンをクリックします。 --- # File: placement-metrics --- --- title: "プレースメント指標" description: "Adaptyのプレースメント指標を分析して、ペイウォールのパフォーマンスを改善しましょう。" --- Adaptyでは、アプリ内に複数のプレースメントを作成・管理でき、それぞれに異なるペイウォールやA/B テストを紐付けることができます。この柔軟性により、特定のユーザーセグメントをターゲットにしたり、異なるオファーや価格モデルを試したり、アプリの収益化戦略を最適化したりすることが可能です。 プレースメントのパフォーマンスやオファーに対するユーザーエンゲージメントに関する有益なインサイトを収集するため、Adaptyは表示されたペイウォールに関連するさまざまなユーザーインタラクションとトランザクションを追跡します。この強力な分析システムは、ビュー数、ユニークビュー数、購入数、トライアル数、返金数、コンバージョン率、収益などの指標を収集します。 収集された指標はリアルタイムで継続的に更新され、Adaptyの使いやすいダッシュボードから簡単にアクセスして分析できます。分析する時間範囲を自由にカスタマイズし、さまざまなパラメーターに基づいてフィルターを適用し、複数のプレースメント、ユーザーセグメント、プロダクト間で指標を比較することができます。 プレースメント指標はプレースメント一覧で確認でき、すべてのプレースメントのパフォーマンス概要を把握できます。この高レベルのビューでは、各プレースメントの集計指標が表示され、パフォーマンスの比較やトレンドの特定が可能です。 各プレースメントをより詳しく分析するには、プレースメントの詳細指標ページに移動します。このページでは、選択したプレースメントに特化した包括的な指標が表示されます。これらの指標により、特定のプレースメントのパフォーマンスをより深く把握し、有効性を評価してデータに基づいた意思決定を行うことができます。 <img src="/assets/shared/img/3e711fc-CleanShot_2023-07-26_at_14.55.042x.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### インストール日による指標のフィルタリング \{#filter-metrics-by-install-date\} --- no_index: true --- ペイウォール、トライアル、購入の指標は、2つの異なる日付でグループ化できます: - **イベント日** — ペイウォールが表示された日、トライアルが開始された日、または購入が行われた日。 - **インストール日** — ユーザーが初めてアプリを開いた日。 同じ日付範囲でも、この2つのビューは大きく異なる数値を示すことがあります。**Filter metrics by install date** チェックボックスで、ダッシュボードがどちらを使用するかを制御します: - **チェックなし(デフォルト)**:指標はイベント日でグループ化されます。 - **チェックあり**:指標はインストール日でグループ化されます。 **例。** 日付範囲を4月1日〜30日に設定し、トライアルを確認します。 - **チェックなし**:それらのユーザーがいつインストールしたかに関わらず、4月に*開始*されたトライアルを表示します。 - **チェックあり**:トライアルがいつ開始されたかに関わらず、4月に*インストール*したユーザーのトライアルを表示します。 特定のコホートのユーザー獲得パフォーマンスを測定するにはインストール日ビューを使用し、特定の期間のペイウォールやオンボーディングのアクティビティを測定するにはイベント日ビューを使用してください。 ### 指標のコントロール \{#metrics-controls\} システムは選択した時間帯に基づいて指標を表示し、4段階のインデントを持つ左側の列パラメーターに従って整理されます。 #### 指標データの表示オプション \{#view-options-for-metrics-data\} プレースメント指標ページでは、ペイウォールベースとオーディエンスベースの2つの表示オプションが用意されています。 <img src="/assets/shared/img/9d26b32-Export-1690376094858.gif" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ペイウォールベースのビューでは、指標はペイウォールに紐付いたプレースメントごとにグループ化されます。これにより、異なるプレースメント別に指標を分析できます。 オーディエンスベースのビューでは、指標はペイウォールのターゲットオーディエンスごとにグループ化されます。ユーザーは異なるオーディエンスセグメントに特有の指標を確認できます。 #### 時間範囲 \{#time-ranges\} 指標データを分析する時間範囲を選択でき、日、週、月、カスタム日付範囲など特定の期間に絞り込むことができます。 <img src="/assets/shared/img/15d2c3e-CleanShot_2023-07-26_at_16.49.272x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> #### 利用可能なフィルターとグループ化 \{#available-filters-and-grouping\} :::link メイン記事:[分析コントロール](controls-filters-grouping-compare-proceeds) ::: Adaptyは、ニーズに合わせて指標分析をフィルタリングおよびカスタマイズするための強力なツールを提供しています。Adaptyの指標ページでは、さまざまな時間範囲、グループ化オプション、フィルタリング機能が利用できます。 - ✅ フィルター対象:オーディエンス、ペイウォール、ペイウォールグループ、プレースメント、国、ストア - ✅ グループ化対象:セグメント、ストア、プロダクト #### 単一指標チャート \{#single-metrics-chart\} プレースメント指標ページの主要コンポーネントの1つがチャートセクションで、選択した指標を視覚的に表示して分析を容易にします。 プレースメント指標ページのチャートセクションには、選択した指標の値を視覚的に表す水平棒グラフが含まれています。グラフの各バーは指標の値に対応しており、サイズが比例しているため一目でデータを理解できます。水平線は分析対象の期間を示し、垂直列には指標の数値が表示されます。すべての指標値の合計はグラフの隣に表示されます。 <img src="/assets/shared/img/4623c5b-Export-1690375597411.gif" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> また、チャートセクションの右上にある矢印アイコンをクリックすると、ビューが拡張され、選択した指標がチャートの全幅で表示されます。 #### 合計指標サマリー \{#total-metrics-summary\} 単一指標チャートの隣には合計指標サマリーセクションが表示されます。ここでは特定の時点における選択した指標の累積値が確認でき、ドロップダウンメニューで表示する指標を変更することもできます。 <img src="/assets/shared/img/0f647cf-CleanShot_2023-07-26_at_14.55.492x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### 指標の定義 \{#metrics-definitions\} 包括的な定義でプレースメント指標のパワーを最大限に活用しましょう。収益からコンバージョン率まで、アプリの収益化戦略を強化し、成功へと導く有益なインサイトを得ることができます。 <img src="/assets/shared/img/771a0f0-Export-1690375049771.gif" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> #### 収益(Revenue) \{#revenue\} この指標は、特定のプレースメント内での購入および更新によって生成された収益の合計額(USD)を表します。収益の計算にはApple App StoreまたはGoogle Play Storeの手数料は含まれず、手数料控除前の金額として計算されます。 #### 手取り収益(Proceeds) \{#proceeds\} この指標は、特定のプレースメント内での購入および更新から、Apple App StoreまたはGoogle Play Storeの適用手数料を差し引いた後にアプリオーナーが実際に受け取る金額(USD)を表します。アプリの収益に直接貢献する純収益を反映しています。手取り収益の計算方法の詳細については、Adaptyの[ドキュメント](analytics-cohorts#revenue-vs-proceeds)を参照してください。 #### ARPPU \{#arppu\} ARPPUは「Average revenue per paying user(課金ユーザー1人あたりの平均収益)」の略で、特定のプレースメント内での課金ユーザー1人あたりの平均収益を測定します。総収益をユニーク課金ユーザー数で割って計算されます。例えば、総収益が15,000ドルで課金ユーザーが1,000人の場合、ARPPUは15ドルになります。 #### ARPAS \{#arpas\} ARPASは「Average revenue per active subscriber(アクティブサブスクライバー1人あたりの平均収益)」の略で、特定のプレースメント内でのアクティブサブスクライバー1人あたりの平均収益を測定します。総収益をトライアルまたはサブスクリプションを有効化したサブスクライバー数で割って計算されます。例えば、総収益が5,000ドルでサブスクライバーが1,000人の場合、ARPASは5ドルになります。この指標はサブスクライバー1人あたりの平均収益化ポテンシャルを評価するのに役立ちます。 #### ARPU \{#arpu\} オンボーディングプレースメント専用。ARPUはオンボーディングを閲覧したユーザー1人あたりの平均収益です。ユニーク閲覧者数で総収益を割って計算されます。 #### ユニーク購入コンバージョン率(Unique CR to purchases) \{#unique-cr-to-purchases\} 購入へのユニークコンバージョン率は、特定のプレースメント内での購入数をユニークビュー数で割って計算されます。購入数とユニークビュー数の比率に注目することで、特定のプレースメント内でユニーク訪問者を課金顧客に転換する効果についてのインサイトが得られます。 #### 購入コンバージョン率(CR to purchases) \{#cr-to-purchases\} 購入へのコンバージョン率は、特定のプレースメント内での購入数をペイウォールの総ビュー数で割って計算されます。特定のプレースメント内でのビューのうち購入に至った割合を示し、ペイウォールがユーザーを課金顧客に転換する効果についてのインサイトが得られます。 #### ユニークトライアルコンバージョン率(Unique CR to trials) \{#unique-cr-to-trials\} トライアルへのユニークコンバージョン率は、特定のプレースメント内で開始されたトライアル数をユニークビュー数で割って計算されます。特定のプレースメント内でのユニークビューのうちトライアル有効化に至った割合を測定し、ペイウォールがユニーク訪問者をトライアルユーザーに転換する効果についてのインサイトが得られます。 #### 購入数(Purchases) \{#purchases\} 購入数は、特定のプレースメント内でのペイウォール上のさまざまなトランザクションの累計合計を表します。この指標には以下のトランザクションが含まれます(更新は含まれません): - 特定のプレースメント内で直接行われた新規購入 - 特定のプレースメント内で最初に有効化されたトライアルのトライアル転換 - 特定のプレースメント内で行われたサブスクリプションのダウングレード、アップグレード、クロスグレード - 特定のプレースメント内でのサブスクリプション復元(自動更新なしで期限切れになったサブスクリプションが再有効化された場合など) これらのさまざまな種類のトランザクションを考慮することで、購入数指標は特定のプレースメント内での全体的な獲得および収益化活動の包括的なビューを提供します。 #### トライアル数(Trials) \{#trials\} トライアル数指標は、特定のプレースメント内で有効化されたトライアルの総数を表します。これらのプレースメント内でペイウォールを通じてトライアル期間を開始したユーザーの数を反映します。この指標はトライアル提供の効果を追跡し、トライアルから有料サブスクリプションへのユーザーエンゲージメントとコンバージョンに関するインサイトを得るのに役立ちます。 #### トライアルキャンセル数(Trials canceled) \{#trials-canceled\} トライアルキャンセル数指標は、特定のプレースメント内で自動更新機能がオフにされたトライアルの数を表します。これはユーザーが手動でトライアルを解約した場合に発生し、トライアル期間終了後にサブスクリプションを継続しないという意思を示しています。トライアルキャンセル数の追跡は、ユーザー行動に関する貴重な情報を提供し、特定のプレースメント内でユーザーがトライアルを離脱する割合を把握するのに役立ちます。 #### 返金数(Refunds) \{#refunds\} 返金数指標は、特定のプレースメント内での返金された購入およびサブスクリプションの数を表します。これには、顧客のリクエスト、支払いの問題、その他の返金ポリシーなど、さまざまな理由で取り消しまたは返金されたトランザクションが含まれます。 #### 返金率(Refund rate) \{#refund-rate\} 返金率は、特定のプレースメント内での返金数を初回購入数(更新は含まれません)で割って計算されます。例えば、返金が5件で初回購入が1,000件の場合、返金率は0.5%になります。 #### ビュー数(Views) \{#views\} ビュー数指標は、特定のプレースメント内のペイウォールがユーザーに閲覧された総回数を表します。ユーザーがそのプレースメント内のペイウォールを訪れるたびに、個別のビューとしてカウントされます。ビュー数の追跡により、ペイウォールに対するエンゲージメントとユーザーインタラクションのレベルを把握でき、アプリの特定エリア内でのユーザー行動やペイウォールの配置およびデザインの有効性についてのインサイトが得られます。 #### ユニークビュー数(Unique views) \{#unique-views\} ユニークビュー数指標は、特定のプレースメント内のペイウォールがユーザーに閲覧されたユニークなインスタンスの数を表します。各訪問を個別のビューとしてカウントする総ビュー数とは異なり、ユニークビュー数は、ユーザーがそのプレースメント内のペイウォールに何度アクセスしても、各ユーザーの訪問を1回としてカウントします。ユニークビュー数の追跡は、特定のプレースメント内でのユーザーエンゲージメントとペイウォールのリーチをより正確に測定するのに役立ちます。総訪問数ではなく個々のユーザーに注目しているためです。 #### 完了数とユニーク完了数(Completions & unique completions) \{#completions--unique-completions\} オンボーディングプレースメント専用。完了数はユーザーがオンボーディングプレースメントを完了した(最初から最後のスクリーンまで進んだ)回数をカウントします。同じユーザーが2回完了した場合、**完了数**は2ですが**ユニーク完了数**は1になります。 #### ユニーク完了率(Unique completions rate) \{#unique-completions-rate\} オンボーディングプレースメント専用。ユニーク完了数をユニークビュー数で割った値です。この指標は、オンボーディングプレースメントに対するユーザーのエンゲージメントを把握し、無視されていることに気づいた場合に改善を加えるのに役立ちます。 --- # File: create-paywall --- --- title: "ペイウォールを作成する" description: "Adaptyのペイウォールビルダーを使って、コンバージョン率の高いペイウォールを作成する方法を学びましょう。" --- [ペイウォール](paywalls)とは、提供するプロダクトを定義するAdaptyの設定です。Adaptyでは、アプリ内でプロダクトを取得する唯一の方法がペイウォールです。 表示方法に関わらず、ペイウォールは必ず必要です: - [**ペイウォールビルダー**](adapty-paywall-builder):ノーコードエディタで画面をデザインします。Adaptyがレンダリングと購入処理を行います。 - **カスタムペイウォール**:独自のUIを実装し、ペイウォールの設定を使ってプロダクトを取得します。 作成後は、ペイウォールを[プレースメント](placements)に割り当てます。プレースメントによって、ユーザーに表示されるペイウォールが決まります。公開中のペイウォールのプロダクトは固定されているため、指標は常に同じ組み合わせを反映し、異なるプロダクトや価格設定のパフォーマンスを比較できます。 :::tip [Developer CLI](developer-cli-reference#adapty-paywalls-create)を使ってプログラムでペイウォールを作成することもできます。 ::: <details> <summary>ペイウォール作成を始める前に(クリックして展開)</summary> 1. [プロダクトを少なくとも1つ作成する](create-product)。 2. (任意)[オファーを作成する](create-offer)。 </details> ## ペイウォールを作成する \{#create-paywall\} Adaptyダッシュボードで新しいペイウォールを作成するには: 1. Adaptyのメインメニューから[**Paywalls**](https://app.adapty.io/paywalls)に移動します。このページには、すべてのペイウォールとその指標の概要が表示されます。 2. **Create paywall** をクリックします。 3. **Paywalls / New paywall** ページで、Adaptyダッシュボード全体でこのペイウォールを識別するための **Paywall name** を入力します。 4. **Add product** をクリックします。 5. ユーザーに表示するプロダクトを選択します。 :::note - このリストのプロダクトの順序はSDKでも維持されるので、希望する順序に並べてください。 - ペイウォールが本番環境で表示された後は、ペイウォールの指標に影響する可能性があるため、プロダクトを変更することはできません。 ::: 6. プロダクトに無料トライアルやその他のオファーを提供する場合は、ここで追加してください。追加しないと利用できません。**Offer** リストから、このプロダクト用に[事前に作成した](create-offer)オファーを選択します。このリストはオファーが設定されているプロダクトにのみ表示されます。 7. **Create as a draft** をクリックしてペイウォールの作成を確定します。 ペイウォールが作成されました! <img src="/assets/shared/img/create-paywall.gif" style={{ border: '1px solid #727272', /* border width and color */ width: '900px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## 次のステップ \{#next-steps\} 最初のペイウォールを作成したら: 1. [プレースメント](placements)に追加します。プレースメントIDがハードコードされる唯一の要素になります。販売するプロダクトの取得にこれを使用します。 2. 次のペイウォールの作業方法は実装方法によって異なります: - [Adaptyペイウォールビルダー](adapty-paywall-builder)を使用する場合は、ノーコードエディタでペイウォールをデザインします。Adaptyがペイウォールのレンダリングと購入ロジックを処理するため、アプリのコードではペイウォールを表示するだけで済みます。 - カスタムペイウォールを使用する場合は、各プラットフォームでAdaptyを使ったアプリ内課金を実装するためのガイドを参照してください: - [iOS](ios-implement-paywalls-manually) - [Android](android-implement-paywalls-manually) - [React Native](react-native-implement-paywalls-manually) - [Flutter](flutter-implement-paywalls-manually) - [Unity](unity-implement-paywalls-manually) - [Kotlin Multiplatform](kmp-implement-paywalls-manually) --- # File: customize-paywall-with-remote-config --- --- title: "リモートコンフィグでペイウォールをデザインする" description: "Adapty のリモートコンフィグを使用してペイウォールをカスタマイズし、より精度の高いターゲティングを実現しましょう。" --- :::important このガイドはクラシックペイウォールのリモートコンフィグについて説明しています。フロービルダーについては、[フローのリモートコンフィグカスタマイズ](customize-flow-with-remote-config)をご参照ください。 ::: ペイウォールのリモートコンフィグは、柔軟な設定オプションを提供する強力なツールです。カスタム JSON ペイロードを使用して、ペイウォールを細かく調整できます。タイトル、画像、フォント、カラーなど、さまざまなパラメーターを定義することが可能です。 <details> <summary>ペイウォールのカスタマイズを始める前に(クリックして展開)</summary> 1. [プロダクトを作成する](create-product)。 2. [ペイウォールを作成してプロダクトを追加する](create-paywall)。 </details> リモートコンフィグを使ってペイウォールをカスタマイズするには: 1. Adapty メインメニューの [**Paywalls**](https://app.adapty.io/paywalls) セクションを開きます。 2. ペイウォールをクリックして開きます。 <img src="/assets/shared/img/remote-config.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. **Remote config** タブに切り替えます。 <img src="/assets/shared/img/remote-config-3.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> リモートコンフィグには 2 つの表示形式があります: - [テーブル](customize-paywall-with-remote-config#table-view-of-the-remote-config) - [JSON](customize-paywall-with-remote-config#json-view-of-the-remote-config) **Table** と **JSON** の両方のビューには同じ設定要素が含まれています。違いは好みの問題ですが、唯一の相違点はテーブルビューにコンテキストメニューが用意されている点で、ローカライズのエラー修正に役立ちます。 **Table** または **JSON** タブをクリックすることで、いつでも表示を切り替えられます。 どちらのビューでペイウォールをカスタマイズした場合でも、SDK から `AdaptyPaywall` の `remoteConfig` または `remoteConfigString` プロパティを使用してこのデータにアクセスし、ペイウォールを調整できます。また、[サーバーサイド API](api-adapty/operations/updatePaywall) を使用してリモートコンフィグの値をプログラム的に更新することで、ダッシュボードを手動で更新することなくペイウォールの設定を動的に変更することも可能です。リモートコンフィグの活用例をいくつか紹介します。 <Tabs groupId="current-os" queryString> <TabItem value="Titles" label="タイトル" default> ```json showLineNumbers { "screen_title": "Today only: Subscribe, and get 7 days for free!" } # Test titles or others texts ``` </TabItem> <TabItem value="Images" label="画像" default> ```json showLineNumbers { "background_image": "https://adapty.io/media/paywalls/bg1.webp" } # Test images on your paywall ``` </TabItem> <TabItem value="Fonts" label="フォント" default> ```json showLineNumbers { "font_family": "San Francisco", "font_size": 16 } # Test fonts ``` </TabItem> <TabItem value="Color" label="カラー" default> ```json showLineNumbers { "subscribe_button_color": "purple" } # Test colors of buttons, texts etc. ``` </TabItem> <TabItem value="HTML" label="HTML" default> ```json showLineNumbers { "photo_gallery": "https://adapty.io/media/paywalls/link-to-html-snippet.html" } # Any HTML code that can be displayed on the paywall ``` </TabItem> <TabItem value="Soft/Hard Paywall" label="ソフト/ハードペイウォール" default> ```json showLineNumbers { "hard_paywall": true } # By setting it to true, you disalow skipping paywall without subscribing # You have to handle this logic in your app ``` </TabItem> <TabItem value="Translations" label="翻訳" default> ```json showLineNumbers { "title": { "en": "Try for free!", "es": "¡Prueba gratis!", "ru": "Попробуй бесплатно!" } } ``` </TabItem> </Tabs> さまざまなオプションを組み合わせて独自の設定を作ることができます。これにより、タイトル、テキスト、画像、フォント、カラーなどをテストできます。 ### リモートコンフィグの JSON ビュー \{#json-view-of-the-remote-config\} リモートコンフィグの **JSON** ビューでは、任意の JSON 形式のデータを入力できます: <img src="/assets/shared/img/3356ff5-remote_config_JSON.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### リモートコンフィグのテーブルビュー \{#table-view-of-the-remote-config\} コードに慣れていない場合や JSON の値を修正したい場合は、Adapty の **Table** ビューが便利です。 <img src="/assets/shared/img/4c27b2f-remote_config_table.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> JSON をテーブル形式で表示するため、読みやすく理解しやすくなっています。カラーコーディングによって異なるデータ型を識別できます。 キーを追加するには、**Add row** ボタンをクリックします。値と型のマッピングを自動でチェックし、修正内容が無効な JSON につながる可能性がある場合はアラートを表示します。 <img src="/assets/shared/img/ef682d8-add_raw.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 追加の行オプションは、主に[ペイウォールのローカライズ](add-remote-config-locale)で役立ちます: <img src="/assets/shared/img/17bcf80-remote_config_table_options.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 次は[プレースメントを作成](create-placement)してペイウォールを追加しましょう。その後、モバイルアプリでリモートコンフィグのペイウォールを <InlineTooltip tooltip="リモートコンフィグペイウォールを表示する">[iOS](present-remote-config-paywalls)、[Android](present-remote-config-paywalls-android)、[React Native](present-remote-config-paywalls-react-native)、[Flutter](present-remote-config-paywalls-flutter)、[Unity](present-remote-config-paywalls-unity)</InlineTooltip> で表示できます。 --- # File: add-paywall-locale-in-adapty-paywall-builder --- --- title: "フローの言語設定を追加する(フローBuilder)" description: "Adaptyのフローbuilderでローカライズされたコンテンツを追加し、ユーザーの言語で世界中にリーチしましょう。" --- フローをローカライズすると、複数の言語で利用できるようになります。フロービルダーでは、ローカライズは画面ごとに管理され、各画面には翻訳の進捗を確認できる完了率が表示されます。 :::tip 他の言語を追加する前に、デフォルトのロケールでフローの設定を完成させておきましょう。 ::: ## ローカライズの追加と設定 \{#add-and-set-up-localization\} 1. 左パネルで Localizations をクリックし、次に **Add locale** をクリックします。追加する言語を選択してください。 2. 追加した各ロケールは、ローカライズテーブルの列として表示され、デフォルト言語の値があらかじめ入力されています。 3. 未翻訳の項目だけに絞り込みたい場合は、左パネルの **Missing only** トグルをオンにします。テーブルが未翻訳の行だけを表示するようにフィルタリングされます。 ## 外部翻訳のためのエクスポートとインポート \{#export-and-import-for-external-translation\} ローカライズファイルをエクスポートして翻訳者と共有し、翻訳済みの結果をインポートできます。 上部のツールバーで **Import / Export** をクリックします。 ### エクスポートファイルの形式 \{#export-file-format\} エクスポートすると、翻訳可能な要素ごとに1行ずつ記録された `.tsv`(タブ区切り)ファイルが生成されます。列の内容は以下のとおりです: | 列 | 説明 | |--------|-------------| | `Screen` | その要素が属する画面(例:`Welcome`、`Quiz`) | | `Element` | 画面内の要素を示す自動生成の識別子。**Interactions** > **Element ID** で変更できます。 | | `Property` | プロパティの種類(例:`content`) | | `[default_locale]` | デフォルト言語コード(例:`en`) | | `[locale]` | 追加したロケールごとの列(例:`fr`、`es`) | 例: ``` Screen Element Property en fr es Welcome title content Turn words into art Transformez les mots en art Welcome subtitle content Create stunning images in seconds with AI Créez des images en quelques secondes Quiz quiz-title content What will you create? ``` :::note 未翻訳の行はロケール列を空白のままにしておいてください — Adapty は未翻訳として扱います。 ::: ### インポートファイルの要件 \{#import-file-requirements\} - **形式**:`.tsv`(タブ区切り値) - **ヘッダー**:`Screen`、`Element`、`Property`、および少なくとも1つのロケール列が必要です - **ロケール列名**:フローにすでに追加されているロケールコードと一致している必要があります。フローに存在しないロケールコードが含まれるファイルをインポートするとエラーになります。 - **部分インポート**:行の一部だけを含めることもできます。ファイルに含まれていない行は現在の値が保持されます。 ## 手動で翻訳する \{#translate-manually\} ローカライズテーブルの任意のセルに直接翻訳を入力することもできます。 特定の行を操作するには、コンテキストメニュー(**⋮**)を開いてください: - **Reset to default**:その行の翻訳をデフォルト言語の値に戻します。 ## ローカライズをプレビューする \{#preview-the-localization\} 翻訳を確認するには、フロービルダーでアクティブなロケールを切り替え、各画面を確認します。 --- # File: add-remote-config-locale --- --- title: "リモートコンフィグを使ったペイウォールのローカライズ" description: "リモートコンフィグのロケールを追加して、Adapty のペイウォールをパーソナライズしましょう。" --- 多様な文化が共存する現代において、ペイウォールをさまざまな言語に対応させることは欠かせません。ローカライズによって、特定の地域のユーザーに合わせた体験を提供できます。各ペイウォールに複数言語のバージョンを追加することで、プロダクトが現地のオーディエンスに響くようになります。 Adapty のペイウォールビルダーを使わずにペイウォールをデザインしている場合でも、カスタムペイウォールをローカライズしたり、アプリを再デプロイせずにローカライズを管理したりすることができます。 1. Adapty ダッシュボードで変数を含むリモートコンフィグを作成します。変数はテキスト・メディア・その他のコンテンツタイプを表すことができます。 2. 各ロケールに変数の値を設定します。 3. アプリのコードで変数を処理します。 4. プロダクトを含むペイウォールを取得してロケールを送信すると、適切な変数の値が返されます。 こうすることで、ローカライズはアプリのコードにハードコードされず、いつでも調整できます。 テーブルビューでも JSON 形式でも、各言語の設定を簡単に調整できます。たとえば、文字列キーを翻訳したり、Boolean 値を切り替えたり(例:英語は `TRUE`、イタリア語は `FALSE`)、背景画像を差し替えたりすることも可能です。 ## リモートコンフィグで設定したペイウォールのローカライズを設定する \{#set-up-localization-for-remote-configured-paywalls\} 1. Adapty の [**Paywalls**](https://app.adapty.io/paywalls) セクションに移動します。 2. ペイウォールをクリックして開きます。 3. **Remote config** タブに移動します。 <img src="/assets/shared/img/switch_to_remote_config.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **Locales** をクリックして対応させたい言語を選択します。変更を保存すると、これらのロケールがペイウォールに追加されます。 <img src="/assets/shared/img/add_locale.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> これで、コンテンツを手動で翻訳したり、AI を使ったり、外部の翻訳者向けにローカライズファイルをエクスポートしたりできます。 ## AI を使ったペイウォールの翻訳 \{#translate-paywalls-with-ai\} AI による翻訳は、ペイウォールをローカライズするための迅速かつ効率的な方法です。 **String** と **List** の両方の値を翻訳できます。デフォルトではすべての行が選択されています(紫色でハイライト表示)。すでに翻訳済みの行は緑色でマークされ、新しい翻訳にはデフォルトで含まれません。選択されていない行や未翻訳の行はグレーで表示されます。 <img src="/assets/shared/img/localization-table.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> <img src="/assets/shared/img/localization-json.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 1. 翻訳する行を選択します。ID・URL・変数が含まれる行はチェックを外しておくと、AI による誤訳を防げます。 2. 翻訳する言語を選択します。 <img src="/assets/shared/img/localization-table-language.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. **AI Translate** をクリックして翻訳を適用します。選択した行が翻訳されてペイウォールに追加され、翻訳済みの行は緑色でマークされます。 ## 外部翻訳向けのローカライズファイルのエクスポート \{#exporting-localization-files-for-external-translation\} AI によるローカライズが普及しつつある一方、プロの人間翻訳者や実績のある翻訳会社を使うといった、より確実な方法を好む場合もあるでしょう。そのような場合は、ローカライズファイルをエクスポートして翻訳者に共有し、翻訳結果を Adapty にインポートし直すことができます。 **Export** ボタンでエクスポートすると、各言語の `.json` ファイルが個別に作成され、1 つのアーカイブにまとめられます。1 つのファイルだけが必要な場合は、言語ごとのメニューから直接エクスポートできます。 <img src="/assets/shared/img/localization-single-export.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 翻訳済みのファイルを受け取ったら、**Import** ボタンを使って一括またはファイルごとにアップロードします。Adapty は自動的にファイルを検証して、正しい形式かどうかを確認します。 ### インポートファイルの形式 \{#import-file-format\} インポートを成功させるには、インポートファイルが以下の要件を満たす必要があります。 - **ファイル名と拡張子:** ファイル名は表すロケールと一致し、拡張子は `.json` である必要があります。Adapty ダッシュボードでロケール名を確認してコピーできます。名前が認識されない場合、インポートは失敗します。 <img src="/assets/shared/img/locale-name.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> - **有効な JSON:** ファイルは有効な JSON である必要があります。そうでない場合、インポートは失敗します。 ## 手動ローカライズ \{#manual-localization\} 翻訳を微調整したり、特定のロケール向けに異なる画像を追加したり、リモートコンフィグを直接調整したりしたい場合もあるでしょう。 1. 翻訳したい要素を選んで新しい値を入力します。**String** と **List** の両方の値を更新したり、ロケールに適した画像に差し替えたりできます。 <img src="/assets/shared/img/032b429-remote_config_localization.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. 英語ロケールのコンテキストメニューを活用して、ローカライズの問題を効率的に解決できます。 - **Copy this value to all locales**:選択した行について、英語ロケールの値で他のすべてのロケールの変更を上書きします。 - **Revert all row changes to original values**:現在のセッション中に行った変更をすべて破棄し、最後に保存した状態に戻します。 <img src="/assets/shared/img/d7e70f1-remote_confi_loc_table_options.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ペイウォールにロケールを追加したら、アプリのコードにロケールコードを正しく実装してください。<InlineTooltip tooltip="アプリでのローカライズとロケールコードの使い方に関するガイド">[iOS](localizations-and-locale-codes), [Android](android-localizations-and-locale-codes)</InlineTooltip> を参照してください。 --- # File: web-paywall-configuration --- --- title: "Webペイウォールの設定" --- **Web paywall** ページで **Create web paywall** をクリックすると、Webペイウォールのデザインと支払い方法を設定する専用ページに移動します。 ## 支払い方法の設定 \{#set-up-a-payment-method\} まず、購入を処理する決済プロバイダーを連携する必要があります。利用可能なオプションは以下のとおりです: - Stripe - Paddle - Paypal - Solidgate :::important AdaptyでWebペイウォールのアナリティクストラッキングを正確に行うには、[プロダクトを追加](product)する際に、対応するStripe/Paddle/その他の決済プロバイダーのプロダクトIDも一緒に登録する必要があります。 ::: 決済プロバイダーを設定するには: 1. Webペイウォールの一覧ページで **Settings** をクリックし、**Integrations** タブに切り替えます。 2. 決済プロバイダーを選択し、画面上の連携手順に従います。 <img src="/assets/shared/img/web-paywall-configuration-1.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. ⚠️ Stripeを選択する場合、インターフェースに **Sandbox** と表示されていても、**Test Mode** 環境のキーを使用してください。そうしないとWebペイウォールが動作しません。Stripeの **Sandboxes** はまだサポートされていません。 <img src="/assets/shared/img/web-paywall-configuration-stripe.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### Apple Payドメイン認証の設定 \{#set-up-apple-pay-domain-verification\} **Settings > Domains** で、ドメイン認証に使用するメインの決済プロバイダーを選択します。次に、それぞれのプロバイダーでペイウォールのドメインを認証してください: **Stripe**: 1. [Payment method domain settings](https://dashboard.stripe.com/settings/payment_method_domains) にアクセスし、**Add a new domain** をクリックします。 2. `app.funnelfox.com` と個人用のペイウォールサブドメイン(`paywalls-....fnlfx.com` のような形式)を追加します。サブドメインを確認するには、**Settings > Domains** に移動して **Hosted subdomain** の値をコピーしてください。 **Paddle**: 1. Paddleコンソールで **Checkout > Website approval** に移動し、**Add a new domain** をクリックします。 2. `app.funnelfox.com` と個人用のペイウォールサブドメイン(`paywalls-....fnlfx.com` のような形式)を追加します。サブドメインを確認するには、**Settings > Domains** に移動して **Hosted subdomain** の値をコピーしてください。 Paddleの承認プロセスは手動なので、ドメインが `Pending` から `Approved` に変わるまで待つ必要があります。 **FunnelFox Billing**: [FunnelFox Billingの連携手順](https://funnelfox.com/docs/billing/integration-billing-funnelfox)に従ってください。 **SolidGate**: 1. SolidgateダッシュボードでDevelopers > Apple Pay Domains** に移動します。 2. **+ Add new domain** をクリックし、プロジェクトドメイン(FunnelFoxの **Settings > Domains** から確認)を貼り付けます。カスタムドメインがある場合はそちらも追加してください。 3. プレビューモードでApple Payを使用するには、`http://app.funnelfox.com/` も追加してください。 ## Webペイウォールの作成と設定 \{#create-and-configure-a-web-paywall\} 1. Webペイウォールの一覧ページで **Create a paywall** をクリックします。 2. ペイウォール名を入力し、**Create** をクリックします。 <img src="/assets/shared/img/web-paywall-configuration-2.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. 2つのサブスクリプションオプションとApple Pay購入ボタンを含む基本テンプレートに移動します。 最初の画面にはサブスクリプションプランの一覧が表示されます。2番目と3番目の画面はチェックアウト画面で、それぞれが提供するプランに対応しています。プランが1つだけの場合は、余分な画面を削除してください。プランが複数ある場合は、チェックアウト画面を複製する必要があります。 購入完了後にユーザーが最後に見る画面では、アプリに戻れることを明確に示す必要があります。 <img src="/assets/shared/img/web-paywall-configuration-10.gif" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. プラン一覧を設定します:プランと価格を追加または削除してください。画面に表示される価格やプランは動的に追加されないため、手動で設定する必要があります。 <img src="/assets/shared/img/web-paywall-configuration-8.gif" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. プランごとにチェックアウト画面を追加または設定します。ユーザーが購入ボタンをクリックする前に支払金額を確認できるよう、各チェックアウト画面に合計金額を表示することをお勧めします。 6. チェックアウト画面にはすでにApple Payボタンがあります。機能させるには、各画面で以下を設定してください: 1. **Product type**:トライアル期間または割引を追加するかどうかを選択します。 2. **Trial period**:トライアル期間の長さを入力します。 3. **Product**:決済プロバイダーからプロダクトを選択します。 :::important プロダクトがAdaptyに追加されていることを確認してください。そうでない場合、購入結果はデフォルト値になります。 ::: 4. **Subscription discount**:オプションで、決済プロバイダーからクーポンを選択します。 <img src="/assets/shared/img/web-paywall-configuration-6.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 7. 次に、プランとチェックアウト画面を紐付ける必要があります。プラン選択画面で **Continue** ボタンをクリックし、各プランの遷移先画面を選択します。 <img src="/assets/shared/img/web-paywall-configuration-9.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ペイウォールの準備が完了したら、Adaptyでこのペイウォールを有効化するためのリンクを取得する必要があります。取得方法は、テスト中か本番環境での公開かによって異なります: 1. **サンドボックステスト用**:右上の **Preview** をクリックしてリンクをコピーします。 2. **本番環境用**:右上の **Publish** をクリックします。**Home** をクリックし、**URL** 列からリンクをコピーします。 <img src="/assets/shared/img/web-paywall-configuration-11.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 以上です!このリンクを使用して[設定を続けてください](web-paywall#step-2-trigger-the-paywall)。 --- # File: fallback-paywalls --- --- title: "Fallback paywalls" description: "Use fallback paywalls to ensure seamless user experience in Adapty." --- To maintain a fluid user experience, it is important that you set up **fallback versions** for your [paywalls](paywalls) and [onboardings](onboardings). When your application loads a paywall, the Adapty SDK requests paywall configuration data from our servers. But what if the device cannot connect to Adapty due to network issues or server outages? * If the user accessed the paywall before, and the device cached its data, the application loads paywall data **from cache**. * If the device did not cache the paywall, the application looks for a locally stored configuration file. It allows the application to display the paywall without an error. Adapty automatically generates fallback configuration files for you to download and use. Each file contains platform-specific configurations for *all* your placements. ## Get started 1. [Download the fallback configuration file](/local-fallback-paywalls) from Adapty. 2. Use the Adapty SDK to configure your fallback paywalls: * [iOS](ios-use-fallback-paywalls) * [Android](android-use-fallback-paywalls) * [React Native](react-native-use-fallback-paywalls) * [Flutter](flutter-use-fallback-paywalls) * [Unity](unity-use-fallback-paywalls) * [Kotlin Multiplatform](kmp-use-fallback-paywalls) * [Capacitor](capacitor-use-fallback-paywalls) ## Limitations Fallback paywalls are hard-coded and locally stored, so they lack the dynamic capabilities of regular Adapty paywalls. * Fallback paywalls don't support [internationalization](paywall-localization). When Adapty generates the configuration file, it uses the default `en` locale. * Each placement can only have one fallback paywall. If your setup inlcudes different paywall configurations for different [audiences](audience), Adapty uses the configuration intended for "All users". * Fallback paywalls don't support [A/B testing](ab-tests). If a paywall participates in an A/B test, its fallback configuration file will include the variation with the highest weight. * Fallback paywalls cannot be [managed remotely](customize-paywall-with-remote-config). If you want to update the configuration file, you need to release a new version of the app on App Store / Google Play. --- # File: local-fallback-paywalls --- --- title: "フォールバックペイウォールをダウンロードする" description: "Adapty のローカルフォールバックペイウォールを使用して、シームレスなサブスクリプションフローを確保しましょう。" --- Adapty はプラットフォームごとに[フォールバックペイウォール](/fallback-paywalls)用の JSON 設定ファイルを自動生成します。これらのファイルにはオンボーディングのフォールバックデータも含まれています。 1 つのプレースメントに複数のペイウォールまたはオンボーディングがある場合、フォールバックバージョンには最も高いウェイトまたは最も広いオーディエンスを持つバリアントが含まれます。Adapty はペイウォールやオンボーディングを変更するたびにこれらのファイルを更新します。 フォールバック設定をダウンロードするには、以下の手順に従ってください。 1. **[Placements](https://app.adapty.io/placements)** ページを開きます。 2. **Fallbacks** ボタンをクリックします。 3. ドロップダウンからターゲットプラットフォーム(*iOS* または *Android*)を選択します。 4. SDK バージョンを選択してダウンロードを開始します。 <img src="/assets/shared/img/9c63367-placements.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## ダウンロード後の手順 \{#after-the-download\} 各プラットフォームのセットアップガイドに従ってください。 * [iOS](ios-use-fallback-paywalls) * [Android](android-use-fallback-paywalls) * [React Native](react-native-use-fallback-paywalls) * [Flutter](flutter-use-fallback-paywalls) * [Unity](unity-use-fallback-paywalls) * [Kotlin Multiplatform](kmp-use-fallback-paywalls) * [Capacitor](capacitor-use-fallback-paywalls) --- # File: paywall-metrics --- --- title: "ペイウォール指標" description: "サブスクリプション収益を向上させるために、ペイウォールのパフォーマンス指標を追跡・分析します。" --- Adapty はペイウォールのパフォーマンスをより正確に計測するための一連の指標を収集しています。ビューを除くすべての指標はリアルタイムで更新され、ビューは数分おきに更新されます。ビューを除くすべての指標は、ペイウォール内のプロダクトに紐付けられます。このドキュメントでは、利用可能な指標の定義と計算方法を説明します。 ペイウォール指標はペイウォール一覧ページで確認でき、すべてのペイウォールのパフォーマンスを一覧で把握できます。この統合ビューでは各ペイウォールの指標が集計表示され、効果の評価や改善点の特定に役立ちます。 各ペイウォールの詳細な分析には、ペイウォール詳細指標ページに移動します。ここでは選択したペイウォールに特化した詳細な指標を確認でき、パフォーマンスへの深い洞察が得られます。 ### インストール日でフィルタリング \{#filter-metrics-by-install-date\} --- no_index: true --- ペイウォール、トライアル、購入の指標は、2つの異なる日付でグループ化できます: - **イベント日** — ペイウォールが表示された日、トライアルが開始された日、または購入が行われた日。 - **インストール日** — ユーザーが初めてアプリを開いた日。 同じ日付範囲でも、この2つのビューは大きく異なる数値を示すことがあります。**Filter metrics by install date** チェックボックスで、ダッシュボードがどちらを使用するかを制御します: - **チェックなし(デフォルト)**:指標はイベント日でグループ化されます。 - **チェックあり**:指標はインストール日でグループ化されます。 **例。** 日付範囲を4月1日〜30日に設定し、トライアルを確認します。 - **チェックなし**:それらのユーザーがいつインストールしたかに関わらず、4月に*開始*されたトライアルを表示します。 - **チェックあり**:トライアルがいつ開始されたかに関わらず、4月に*インストール*したユーザーのトライアルを表示します。 特定のコホートのユーザー獲得パフォーマンスを測定するにはインストール日ビューを使用し、特定の期間のペイウォールやオンボーディングのアクティビティを測定するにはイベント日ビューを使用してください。 ### 指標コントロール \{#metrics-controls\} システムは選択した期間に基づいて指標を表示し、左側の列パラメータに3段階のインデントで整理します。 ライブのペイウォールの指標は、ペイウォールの開始日から現在までの期間を対象とします。非アクティブなペイウォールの指標は、開始日から選択した期間の終了日までの全期間を対象とします。下書きおよびアーカイブ済みのペイウォールも指標テーブルに含まれますが、データがない場合は指標なしで一覧表示されます。 #### 指標データの表示オプション \{#view-options-for-metrics-data\} ペイウォールページでは、プレースメントベースとオーディエンスベースの2つの表示オプションを利用できます。 プレースメントベースのビューでは、指標がペイウォールに関連付けられたプレースメント別にグループ化されます。これにより、プレースメントごとに指標を分析できます。 オーディエンスベースのビューでは、指標がペイウォールのターゲットオーディエンス別にグループ化されます。異なるオーディエンスセグメントごとの指標を評価できます。ペイウォール詳細ページ上部のドロップダウンから表示方法を選択できます。 #### 期間の選択 \{#time-ranges\} 日、週、月、カスタム期間など、さまざまな時間範囲を選択して指標データを分析できます。 #### 利用可能なフィルターとグループ化 \{#available-filters-and-grouping\} :::link 関連記事: [アナリティクスコントロール](controls-filters-grouping-compare-proceeds) ::: Adapty はニーズに合わせた指標分析のフィルタリングとカスタマイズのための強力なツールを提供しています。Adapty の指標ページでは、さまざまな期間、グループ化オプション、フィルタリング機能を利用できます。 - フィルター対象: オーディエンス、国、ペイウォール、ペイウォールの状態、ペイウォールグループ、プレースメント、国、ストア、プロダクト、プロダクトストア - グループ化: プロダクトとストア #### 単一指標チャート \{#single-metrics-chart\} ペイウォール指標ページの主要なコンポーネントの一つがチャートセクションで、選択した指標を視覚的に表示して分析を容易にします。 ペイウォール指標ページのチャートセクションには横棒グラフが含まれており、選択した指標の値を視覚的に表示します。チャートの各バーは指標の値に対応しており、サイズが比例しているため、一目でデータを把握できます。横の線は分析している期間を示し、縦の列は指標の数値を表示します。すべての指標値の合計はチャートの横に表示されます。 また、チャートセクション右上の矢印アイコンをクリックするとビューが展開され、選択した指標がチャートの全幅で表示されます。 #### 指標合計サマリー \{#total-metrics-summary\} 単一指標チャートの横には指標合計サマリーセクションが表示されます。特定の時点における選択した指標の累積値が表示され、ドロップダウンメニューから表示する指標を切り替えられます。 ### 指標の定義 \{#metrics-definitions\} #### Revenue \{#revenue\} この指標は、購入および更新から発生した収益の合計をUSDで表します。収益の計算にはApp Store / Play Storeの手数料が含まれておらず、手数料控除前の金額です。 #### Proceeds \{#proceeds\} この指標は、App Store / Play Storeの手数料を差し引いた後にアプリオーナーが実際に受け取る購入および更新からの金額(USD)を表します。 :::important アプリが手数料減額プログラムに登録している場合は、Adaptyにお知らせください。正確な計算のために、[アプリ設定](general)で[Small Business Program](app-store-small-business-program)および[Reduced Service Fee program](google-reduced-service-fee)の状態を指定してください。 ::: この指標はアプリの収益に直接貢献するネット収益を反映します。Proceedsの計算方法については、Adaptyの[ドキュメント](analytics-cohorts#revenue-vs-proceeds)を参照してください。 #### ARPPU \{#arppu\} ARPPUは課金ユーザー1人あたりの平均収益です。総収益を課金ユーザー数で割って計算します。例: $15,000の収益 ÷ 1,000人の課金ユーザー = $15のARPPU。 #### ARPAS \{#arpas\} ARPASはアクティブサブスクライバー1人あたりの平均収益で、トライアルまたはサブスクリプションを開始したサブスクライバー数で総収益を割って計算します。例えば、総収益が$5,000でサブスクライバーが1,000人の場合、ARPASは$5になります。この指標はサブスクライバー1人あたりの平均収益化ポテンシャルを評価するのに役立ちます。 #### 購入へのユニークコンバージョン率(CR) \{#unique-conversion-rate-cr-to-purchases\} 購入へのユニークコンバージョン率は、購入数をユニークビュー数で割って計算します。例えば、購入が10件でユニークビューが100件の場合、購入へのユニークコンバージョン率は10%になります。この指標はユニーク訪問者を有料顧客に転換する効果を把握するための比率です。 #### 購入へのCR \{#cr-to-purchases\} 購入へのコンバージョン率は、購入数を総ビュー数で割って計算します。例えば、購入が10件でビューが100件の場合、購入へのコンバージョン率は10%になります。この指標はビューが購入に結びつく割合を示し、ペイウォールのユーザー転換効果を把握するのに役立ちます。 #### トライアルへのユニークCR \{#unique-cr-to-trials\} トライアルへのユニークコンバージョン率は、開始されたトライアル数をユニークビュー数で割って計算します。例えば、トライアルが30件開始されてユニークビューが100件の場合、トライアルへのユニークコンバージョン率は30%になります。この指標はユニーク訪問者をトライアルユーザーに転換するペイウォールの効果を測定します。 #### 購入数(Purchases) \{#purchases\} 購入数はペイウォールで行われたさまざまなトランザクションの累計合計です。この指標には以下のトランザクションが含まれます(更新は含まれません): - ペイウォールで直接行われた新規購入 - ペイウォールで最初に開始されたトライアルのトライアル転換 - ペイウォールで行われたサブスクリプションのダウングレード、アップグレード、クロスグレード - ペイウォールでのサブスクリプション復元(自動更新なしで有効期限切れ後に再開された場合など) これらのさまざまなトランザクションを考慮することで、購入数指標はペイウォール全体の獲得・収益化アクティビティを包括的に把握できます。 #### トライアル数(Trials) \{#trials\} トライアル数は開始されたトライアルの総数を表します。ペイウォールを通じてトライアル期間を開始したユーザー数を反映します。この指標はトライアル提供の効果を追跡し、ユーザーエンゲージメントや有料サブスクリプションへの転換に関する洞察を提供します。 #### キャンセルされたトライアル数(Trials canceled) \{#trials-canceled\} キャンセルされたトライアル数は、自動更新機能がオフにされたトライアルの数を表します。これはユーザーが手動でトライアルを解約した場合に発生し、トライアル期間終了後にサブスクリプションを継続しないという意思決定を示します。キャンセルされたトライアルを追跡することで、ユーザー行動に関する貴重な情報が得られ、トライアルからの離脱率を把握できます。 #### 返金数(Refunds) \{#refunds\} 返金数は返金された購入およびサブスクリプションの件数を表します。これには、顧客からのリクエスト、支払いの問題、その他の返金ポリシーに基づいて取り消しまたは返金されたトランザクションが含まれます。 #### 返金率(Refund rate) \{#refund-rate\} 返金率は、返金数を初回購入数(更新は含まれません)で割って計算します。例えば、返金が5件で初回購入が1,000件の場合、返金率は0.5%になります。 #### ビュー数(Views) \{#views\} ビュー数はユーザーがペイウォールを閲覧した総回数を表します。ユーザーがペイウォールを訪れるたびに1ビューとしてカウントされます。例えば、ユーザーがペイウォールを2回訪れた場合、2ビューとして記録されます。ビュー数を追跡することで、ペイウォールへのエンゲージメントとユーザーインタラクションのレベルを把握し、ユーザー行動やペイウォールの配置・デザインの効果についての洞察が得られます。 #### ユニークビュー数(Unique views) \{#unique-views\} ユニークビュー数は、ユーザーがペイウォールを閲覧したユニークな回数を表します。総ビュー数が各訪問を別々にカウントするのとは異なり、ユニークビュー数は各ユーザーのペイウォールへのアクセス回数に関わらず1回としてカウントします。例えば、ユーザーがペイウォールを2回訪れた場合、1ユニークビューとして記録されます。ユニークビュー数を追跡することで、訪問総数ではなく個々のユーザーに着目したユーザーエンゲージメントとペイウォールのリーチのより正確な計測が可能になります。 :::warning `.logShowFlow()` (iOS SDK v4+) / `.logShowPaywall()` メソッドを使用して、ペイウォールのビューをAdaptyに必ず送信してください。送信しない場合、ペイウォールのビューが指標に反映されず、コンバージョン率が正確に計算されません。 ::: --- # File: migrate-paywalls --- --- title: "アプリ間でペイウォールを移行する" description: "AdaptyでペイウォールをAdapter他のアプリから移行する方法を学びます。" --- Adaptyを使えば、アプリごとにペイウォールを一から作り直す必要はありません。複数のアプリを管理している場合、ペイウォールビルダーで作成したペイウォールのビルダー設定を、別のアプリにそのまま移行できます。 移行でコピーされる視覚的な設定は次のとおりです: - ペイウォールおよびすべてのペイウォール要素のレイアウト設定 - メディア - ローカライズ 移行はビルダー設定のみが対象で、プロダクトやリモートコンフィグはコピーされません。 :::note カスタムフォントを使用したペイウォールビルダー設定を移行する場合は、表示が崩れる可能性があるため、実機でテストしてください。 ::: ## ペイウォールの移行 \{#migrate-paywall\} :::important 移行できるのは、**新しい** Adapty ペイウォールビルダーで作成されたペイウォールのみです。**レガシー**ペイウォールビルダーのペイウォールを移行するには、先に新しいペイウォールビルダーへ移行する必要があります。 ::: ペイウォールビルダーの設定を移行するには: 1. **新しいペイウォールの場合**:[ペイウォールの作成](create-paywall)を開始し、プロダクトを追加します。次に、**Build no-code paywall** をクリックしてテンプレートライブラリを開きます。 **既存のペイウォールの場合**:**Builder & Generator** タブの **Layout settings** セクションに移動し、**Change template** をクリックします。 2. ペイウォールテンプレートを編集中に、**Copy a design from your apps** ボックス内の **Choose paywall** をクリックします。 <img src="/assets/shared/img/migrate-paywall-builder.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. 設定のコピー元となるアプリとペイウォールを選択します。 <img src="/assets/shared/img/migrate-app.png" style={{ border: '1px solid #727272', /* border width and color */ width: '500px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **Copy Selected Paywall** をクリックします。 移行後は必要に応じて編集でき、元のペイウォールには影響しません。 --- # File: duplicate-paywalls --- --- title: "ペイウォールを複製する" description: "Adaptyでのペイウォールの複製と管理方法について学びましょう。" --- 既存のペイウォールに少し変更を加えたい場合、特にすでにモバイルアプリで使用中でアナリティクスへの影響を避けたい場合は、単純に複製するだけで大丈夫です。作成した複製は、必要に応じて一部またはすべてのプレースメントで元のペイウォールと置き換えて使用できます。 複製を作成すると、ペイウォールの名前・プロダクト・プロモーションなど、すべての設定がコピーされます。新しいペイウォールには元の名前に「Copy」が付加されるため、元のペイウォールと区別しやすくなります。 Adapty ダッシュボードでペイウォールを複製する手順は次のとおりです。 1. Adaptyのメインメニューから [**Paywalls**](https://app.adapty.io/paywalls) セクションを開きます。Adapty ダッシュボードのペイウォール一覧ページには、アカウント内のすべてのペイウォールが表示されます。 2. 複製したいペイウォールの隣にある **3-dot** ボタンをクリックし、**Duplicate** を選択します。 <img src="/assets/shared/img/duplicate.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. 新しいペイウォールを編集し、**Save** ボタンをクリックします。 4. 元のペイウォールがいずれかのプレースメントで使用中の場合、Adaptyは元のペイウォールを複製に置き換えるかどうかを確認するプロンプトを表示します。**Create and replace original** を選択すると、新しいペイウォールはすぐに **Live** 状態になります。または、**Draft** 状態の新しいペイウォールとして作成し、後でプレースメントに追加することもできます。 --- # File: archive-paywalls --- --- title: "ペイウォールのアーカイブ" description: "データを失わずにAdaptyで古いペイウォールをアーカイブする方法を説明します。" --- Adaptyを使い込んでペイウォールの設定を細かく調整していくうちに、現在の戦略やキャンペーンに合わなくなったペイウォールが増えていくことがあります。こうした未使用のペイウォールが `Inactive` のまま残っていると、ワークスペースが散らかり、必要なものを見つけにくくなります。この問題を解決するために、Adaptyでは不要なペイウォールをアーカイブする機能を提供しています。 アーカイブすることで、ペイウォールを完全に削除せず安全に保存でき、必要になったときにいつでも参照できます。また、アーカイブしたペイウォールはデフォルトの表示から除外できるため、ワークスペースがすっきりし、インターフェースも見やすくなります。このガイドでは、Adaptyでペイウォールを効率的にアーカイブする方法を説明し、ペイウォール管理をより細かくコントロールできるようにします。 ご注意:少なくとも1つのプレースメントで現在アクティブなライブのペイウォールはアーカイブできません。そのようなペイウォールをアーカイブしたい場合は、事前にすべてのプレースメントから削除してください。 :::note 非アーカイブのA/B テストで使用中のペイウォールはアーカイブできません。これにより、完了したA/B テストの詳細な指標を確認でき、紐付けられたペイウォールもそのデータの一部として保持されます。 ::: **ペイウォールをアーカイブするには:** 1. Adaptyのメインメニューで [**Paywalls**](https://app.adapty.io/paywalls) セクションを開きます。 2. アーカイブしたいペイウォールの横にある **3-dot** ボタンをクリックし、**Archive** オプションを選択します。 <img src="/assets/shared/img/archive-paywall.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. **Archive paywall** ウィンドウが表示されたら、アーカイブしたいペイウォールの名前を入力し、**Archive** ボタンをクリックします。 --- # File: restore-paywall --- --- title: "ペイウォールをアーカイブから戻す" description: "Adapty でペイウォールを復元して、ユーザーへのサブスクリプションサービスを途切れなく提供しましょう。" --- ペイウォールをアーカイブできる機能は、ペイウォール管理プロセスを効率化するうえで非常に役立ちます。不要になったペイウォールを非表示にしてワークスペースをすっきりさせたり、必要になった際にアーカイブ済みのペイウォールを復元して再活用したりと、柔軟な運用が可能です。 アーカイブ済みのペイウォールはデフォルトビューではフィルタリングされて表示されない場合があります。表示するには、**State** フィルターで **Archived** を選択してください。 **ペイウォールをアーカイブから元に戻すには** 1. Adapty メインメニューの [**Paywalls**](https://app.adapty.io/paywalls) セクションを開きます。 2. アーカイブ済みのペイウォールがリストに表示されていることを確認します。表示されていない場合は、右側のフィルターを更新してください。 <img src="/assets/shared/img/paywall-filter.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. アーカイブ済みペイウォールの横にある **3点ドット** ボタンをクリックし、**Back to active** を選択します。 <img src="/assets/shared/img/restore-paywall.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> --- # File: profiles-crm --- --- title: "Profiles/CRM" description: "Manage user profiles and CRM data in Adapty to enhance audience segmentation." --- Profiles is a CRM for your users. With Profiles, you can: 1. Find specific users by profile ID, customer user ID, email, or transaction ID. 2. View the user's event timeline, including billing issues, grace periods, and other [events](events). 3. Analyze user's properties such as subscription state, total revenue/proceeds, and more. 4. Grant the user a subscription. --- no_index: true --- import Callout from '../../../components/Callout.astro'; :::note イベントフィードのイベントはダッシュボードに届くまでに遅延が発生します。新しいプロファイルや属性の変更はすぐに反映されない場合があります。 ::: <img src="/assets/shared/img/profiles.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> :::link To understand how Adapty creates and links user profiles, see [How profiles work](how-profiles-work). ::: ## Finding users In the Profiles list, you can search for a specific user by: - **Profile ID**: Adapty's internal identifier for the user (also called Adapty ID). - **Customer user ID**: Your app's identifier for the user, if you've set one. - **Email**: The user's email, if sent as a custom attribute. - **Transaction ID**: The store transaction ID from a purchase. Click any row to open the user's full profile. ## Subscription state In the Profiles list, you can filter and sort users by subscription state. The state values are: | ユーザーの**状態** | 説明 | | :--------------------- | :----------------------------------------------------------- | | Subscribed | ユーザーは自動更新が有効なアクティブなサブスクリプションを持っています。 | | Auto-renew off | ユーザーは自動更新をオフにしましたが、サブスクリプション期間の終了までプレミアム機能にアクセスできます。 | | Subscription cancelled | ユーザーはサブスクリプションをキャンセルし、完全に終了しました。 | | Billing issue | サブスクリプションまたはトライアル終了後に請求の問題が発生し、ユーザーに課金できませんでした。 | | Grace period | サブスクリプションまたはトライアル終了後の課金試行時に請求の問題が発生したため、ユーザーは現在グレース期間中です。 | | Active trial | ユーザーはトライアル期間中のアクティブなサブスクリプションを持っています。 | | Trial cancelled | ユーザーはトライアルをキャンセルし、アクティブなサブスクリプションはありません。 | | Never subscribed | ユーザーはサブスクリプションを開始したことがなく、トライアルも利用したことがない無料ユーザーです。 | ## User attributes <img src="/assets/shared/img/ce8df4d-CleanShot_2023-06-26_at_20.32.232x.webp" style={{ border: '1px solid #727272', width: '700px', display: 'block', margin: '0 auto' }} /> You can send additional user properties to Adapty using the SDK. By default, Adapty sets: | Property | Description | | ---------------- | ------------------------------------------------------------ | | Customer user ID | An identifier of your end user in your system. | | Adapty ID | Internal Adapty identifier of your end user, called Profile ID. | | IDFA | The Identifier for Advertisers, assigned by Apple to a user's device. Requires App Tracking Transparency (ATT) permission on iOS 14+. Not available on Android. | | Country | Country of your end user. | | OS | The operating system used by the end user. | | Device | The end-user-visible device model name. | | Install date | The date when the user was first recorded in Adapty: <ul><li>The date the user was created. </li><li>If the user installed your app before you integrated Adapty, the install date reflects the date of their first transaction.</li><li>If applicable, the date provided during a historical data import.</li></ul> | | Created at | The date the user was created. | Send at least your internal user ID or user email. This lets you find users by these identifiers in the Profiles list. After you install the SDK, Adapty automatically collects user events from the payment queue and displays them in the user profile. The attributes in the table above are collected automatically — you do not need to send them. ### Custom attributes In the **Attributes** section of a profile, you can see custom attributes set via the SDK or API. You can also assign attributes manually using the **Add attribute** button. <img src="/assets/shared/img/378c1fb-add_attribute.webp" style={{ border: '1px solid #727272', width: '700px', display: 'block', margin: '0 auto' }} /> ## Granting a subscription In a profile, you can extend an active subscription or grant a user lifetime access to an access level — without requiring them to make a purchase. <img src="/assets/shared/img/b1d74fd-edit_paid_access_level.webp" style={{ border: '1px solid #727272', width: '700px', display: 'block', margin: '0 auto' }} /> This is most useful for: - Compensating a user after a billing or support issue. - Running manual promotions or beta programs. - Testing subscription flows without a real purchase. To grant access, open the user's profile, go to the **Access levels** section, and click **Edit**. Set the expiration date and save. The expiration date must be in the future and cannot be decreased once set. Adjusting it for active subscriptions does not affect ongoing payments. :::note Granting access does not create App Store or Google Play purchase events. The user's event feed and analytics will differ from a real purchase flow. ::: You can also grant access programmatically using the [Grant access level](api-adapty/operations/grantAccessLevel) API method. ## Sharing paid access between user accounts :::link Main article: [Sharing paid access between user accounts](sharing-paid-access-between-user-accounts) ::: ### Access sharing history When access levels are shared or transferred, the user’s profile shows a link to the connected profile — the profile that shared access, or the profile that received it. To view the connected profile, in the user’s **Profile**, click the link next to the access level. <img src="/assets/shared/img/profile-access-level-origin.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Next steps - To understand how Adapty creates and links profiles, see [How profiles work](how-profiles-work). - To configure the access sharing policy, see [Sharing paid access between user accounts](sharing-paid-access-between-user-accounts). - To grant access programmatically, see the [Grant access level](api-adapty/operations/grantAccessLevel) API method. --- # File: how-profiles-work --- --- title: "プロファイルの仕組み" description: "Adaptyがユーザープロファイルをどのように作成・追跡・紐付けするかを理解しましょう — 匿名プロファイル、識別済みユーザー、親/継承プロファイルの関係を含みます。" --- アプリのすべてのユーザーには、購入履歴・イベント・サブスクリプションの状態を追跡するAdaptyプロファイルが割り当てられます。プロファイルがどのように作成・紐付けされるかを理解することで、インテグレーションのバグを防ぎ、データの断片化を避け、[プロファイル](profiles-crm)セクションのデータを正しく解釈できます。 ## プロファイルの作成 \{#profile-creation\} Adaptyはユーザーがアプリを初めて起動したタイミングで、自動的にプロファイルを作成します。 **Customer User IDがない場合**、プロファイルは匿名になります。以下のタイミングで毎回新しい匿名プロファイルが作成されます: - ユーザーがアプリを再インストールしたとき - ユーザーがアプリからログアウトしたとき(アプリが`Adapty.logout()`を呼び出したとき) 購入はアプリのインストールに紐付けられ、永続的なユーザー識別情報には紐付けられません。 **Customer User IDがある場合**、プロファイルは再インストールやデバイスをまたいで維持されます。Customer User IDを使うことで、次のことが可能になります: 1. 再インストールや複数デバイスにまたがってユーザーを追跡できます。 2. [**Profiles**](profiles-crm)セクションでCustomer User IDからユーザーを検索できます。 3. [サーバーサイドAPI](getting-started-with-server-side-api)でCustomer User IDを使用できます。 4. AdaptyはCustomer User IDをすべてのインテグレーションに送信します。 Customer User IDを使用する場合のプロファイルの動作は、いつ設定するかによって異なります: - **SDKの初期化時**:そのCustomer User IDを持つ既存のプロファイルを使用します(再訪ユーザーの場合)、または新しいプロファイルを作成します(初回ユーザーの場合)。 - **SDK初期化後**:初期化時に匿名プロファイルが作成されます。その後ユーザーを識別すると、AdaptyはCustomer User IDを匿名プロファイルに紐付けます(初回ユーザーの場合)、または既存のプロファイルに切り替えます(再訪ユーザーの場合)。 **どちらのアプローチを使うか:** - **アプリ起動時にCustomer User IDが利用可能な場合**(例:前回のセッションから保存されている)— SDKの初期化時に`activate()`へ渡します。 - **ユーザーがアプリ起動後にサインインする場合**— 認証後に`identify()`を呼び出します。AdaptyはそのIDを現在のプロファイルに紐付けます(IDが新規の場合)、または既存のプロファイルに切り替えます(IDが既に存在する場合)。 - **ログイン前に購入できる場合**— ログイン後に`identify()`を呼び出します。Customer User IDがAdaptyに既に存在する場合は、その後プロファイルを取得して現在のアクセスレベルを同期してください。 実装の詳細については、[ユーザーの識別](identifying-users)SDKガイドを参照してください。 :::note 以前にCustomer User IDなしでアプリを使用したことがある再訪ユーザーの場合、SDK初期化時に識別を開始しても、それらの匿名プロファイルは自動的にマージされません。そのようなユーザーの完全な履歴を維持するには、ログイン後に`identify()`を使用してください。 ::: ## 親プロファイルと継承プロファイル \{#parent-and-inheritor-profiles\} 同じストア側のサブスクリプションが複数のAdaptyプロファイルに関連付けられている場合、Adaptyはそれらのプロファイルをチェーンとして扱います:1つの**親**プロファイルと、同じ購入からアクセスを共有する1つ以上の**継承**プロファイルです。 これは以下の場合に発生します: - [ユーザーアカウント間での有料アクセスの共有](sharing-paid-access-between-user-accounts)が有効で、別のプロファイルが購入したデバイスにユーザーがサインインしたとき。 - ユーザーが`customer_user_id`なしでアプリを再インストールし、新しいプロファイルが前のインストールの購入を引き継いだとき。 - 異なる識別済みユーザーが同じデバイスで購入を復元したとき。 - アプリがApple Team IDを変更し、新しいアプリが旧Team IDで行われた購入を引き継いだとき。 **親の決定方法。** 親は**最初に購入を記録したプロファイル**です — プロファイルの作成順ではなく、Adaptyでの購入レシートの順序によって決定されます。例:アプリをインストールして購入せず、再インストールしてサブスクリプションを購入した場合、2番目のプロファイルが親になります(購入を行ったため)。最初のプロファイルは継承プロファイルとなり、共有によってアクセスを得ます。 **イベントの分配方法:** - **トランザクションイベント**(購入、更新、キャンセル、請求の問題、グレース期間、返金):購入を行った**親プロファイル**にのみ表示されます。サブスクリプションの更新・変更はすべてこのプロファイルに表示され続けます。 - **`access_level_updated`イベント**:アクセスレベルの状態が変化するたびに、**親プロファイルと継承プロファイルの両方**に表示されます。これにより、紐付けられたすべてのプロファイルが現在のアクセス状態を把握できます。 親プロファイルには完全なトランザクション履歴が表示されます。継承プロファイルには、アクセスレベルの更新のみが表示され、**Access level**セクションに親プロファイルへのリンクが表示されます。 <img src="/assets/shared/img/98d0dad-non-original_profile.webp" style={{ border: '1px solid #727272', width: '700px', display: 'block', margin: '0 auto' }} /> **複数のプロファイルにまたがる同一サブスクリプションの追跡。** 各継承プロファイルは独自の`profile_id`を持つため、`profile_id`はチェーン全体で一定ではありません。複数のプロファイルにまたがって同じサブスクリプションを特定するには(例:Webhookイベントの照合や、ダッシュボードのプロファイルと1人のユーザーの対応付け)、ストア側の識別子を使用してください。 | フィールド | 用途 | | --- | --- | | `store_original_transaction_id` | プロファイルをまたいだサブスクリプションチェーンの識別。Appleのサブスクリプションごとに一意。 | | `profiles_sharing_access_level`(Webhookフィールド) | 共有が有効な場合に、そのサブスクリプションによって権限を付与されているすべてのプロファイル。 | | `profile_id` | クロスプロファイル追跡には**不適切** — 各継承プロファイルが独自のIDを持つため。 | ## プロファイルなしのトランザクション \{#transactions-without-profiles\} Adaptyの一部のトランザクションはプロファイルに紐付けられていません — アナリティクスとエクスポートには表示されますが、プロファイルリストには表示されません。これは、Adapty SDKを通じてアプリに接続したことがないユーザーへの**サーバー間(S2S)ストア通知**が届いた場合に発生します。既知の発生源は以下の通りです: - App Store S2S通知(返金イベントを含む) - Google Play S2S通知 - StripeおよびPaddleのWebhookイベント これらのトランザクションは: - **アナリティクスチャートに表示されます**(全体の指標にカウントされます) - **エクスポートに表示されます**(S3、GCS、BigQuery)— `profile_id`は`null`に設定されます - **プロファイルリストには表示されません** — 紐付けるプロファイルが存在しないため アナリティクスやエクスポートで、プロファイルUIで見つけられるより多くのイベントが表示される場合、その差はおそらくこれらのプロファイルなしトランザクションによるものです。エクスポートで見つけるには、`profile_id IS NULL`の行でフィルタリングしてください。 ## ユーザーアカウント間での有料アクセスの共有 \{#sharing-paid-access-between-user-accounts\} :::link メイン記事: [ユーザーアカウント間での有料アクセスの共有](sharing-paid-access-between-user-accounts) ::: アクセスレベルの共有ポリシーを設定するには、[**General**](general)設定ページで共有オプションを選択します。[サンドボックス環境](test-purchases-in-sandbox)に対して別のポリシーを設定することもできます。 --- no_index: true --- **有効(デフォルト)** 識別済みユーザー([Customer User ID](identifying-users#set-customer-user-id-on-configuration)が設定されているユーザー)は、同じApple/Google IDでサインインしているデバイスであれば、Adaptyが提供する同じ[アクセスレベル](access-level)を共有できます。これは、ユーザーがアプリを再インストールして別のメールアドレスでログインした場合でも、以前の購入へのアクセスを維持できるため便利です。このオプションでは、複数の識別済みユーザーが同じアクセスレベルを共有できます。 アクセスレベルは共有されますが、過去および将来のすべてのトランザクションは、一貫したアナリティクスを維持し完全なトランザクション履歴(トライアル期間、サブスクリプション購入、更新など)を同じプロファイルに紐付けるため、元のCustomer User IDのイベントとして記録されます。 **新しいユーザーへアクセスを移譲** 識別済みユーザーは、デバイスが同じApple/Google IDでサインインしている限り、別の[Customer User ID](identifying-users#set-customer-user-id-on-configuration)でログインしたりアプリを再インストールしたりしても、Adaptyが提供する[アクセスレベル](access-level)を引き続き利用できます。 前のオプションとは異なり、Adaptyは識別済みユーザー間で購入を移譲します。これにより購入済みコンテンツへのアクセスが保証されますが、一度にアクセスできるのは1人のユーザーのみです。たとえば、UserAがサブスクリプションを購入し、同じデバイスでUserBがログインしてトランザクションをリストアした場合、UserBがサブスクリプションへのアクセスを取得し、UserAからはアクセスが取り消されます。 いずれかのユーザー(新しいユーザーまたは古いユーザー)が識別されていない場合でも、Adapty内でそれらのプロファイル間でアクセスレベルは共有されます。 アクセスレベルは移譲されますが、過去および将来のすべてのトランザクションは、一貫したアナリティクスを維持し完全なトランザクション履歴(トライアル期間、サブスクリプション購入、更新など)を同じプロファイルに紐付けるため、元のCustomer User IDのイベントとして記録されます。 **新しいユーザーへアクセスを移譲**に切り替えた後、アクセスレベルはすぐにはプロファイル間で移譲されません。特定のアクセスレベルの移譲プロセスは、サブスクリプションの更新、リストア、またはトランザクションの検証など、ストアからのイベントをAdaptyが受信したときにのみトリガーされます。 **無効** 最初にアクセスレベルを取得した識別済みユーザープロファイルが、それを永続的に保持します。これは、ビジネスロジック上、購入を単一のCustomer User IDに紐付ける必要がある場合に最適なオプションです。 なお、匿名ユーザー間ではアクセスレベルは引き続き共有されます。 [オーナーのユーザープロファイルを削除する](https://adapty.io/docs/ja/api-adapty/operations/deleteProfile)ことで、購入の紐付けを解除できます。削除後、アクセスレベルは最初にそれを要求したユーザープロファイル(匿名または識別済みを問わず)に付与されます。 共有の無効化は新しいユーザーにのみ影響します。すでにユーザー間で共有されているサブスクリプションは、このオプションを無効にした後も共有され続けます。 :::warning AppleとGoogleは、購入をApple/Google IDに紐付けているため、ユーザー間でアプリ内課金を共有または移譲することを求めています。共有がなければ、その後の再インストール時に購入のリストアが機能しない可能性があります。 共有を無効にすると、ログイン後にユーザーがアクセスを取り戻せなくなる場合があります。 共有の無効化は、ユーザーが購入前に**ログインを必須とする**場合にのみ推奨します。そうでない場合、識別済みユーザーがサブスクリプションを購入した後に別のアカウントにログインすると、アクセスを永続的に失う可能性があります。 ::: ### どの設定を選べばよいですか? \{#which-setting-should-i-choose\} | アプリの条件 | 選択するオプション | | ------------------------------------------------------------ | ------------------------------------------------------------ | | ログインシステムがなく、AdaptyのみMatch anonymous profile IDを使用している。 | デフォルトオプションを使用してください。3つのオプションすべてで、匿名プロファイルID間ではアクセスレベルが常に共有されます。 | | オプションのログインシステムがあり、アカウント作成前に購入できる。 | **新しいユーザーへアクセスを移譲**を選択してください。アカウントなしで購入したユーザーが後でトランザクションをリストアできるようになります。 | | 購入前にアカウント作成を必須とするが、購入を複数のCustomer User IDに紐付けることを許可している。 | **新しいユーザーへアクセスを移譲**を選択してください。一度にアクセスできるCustomer User IDは1つに限られますが、別のCustomer User IDでログインしても有料アクセスを失わずに済みます。 | | 購入前にアカウント作成を必須とし、購入を単一のCustomer User IDに厳密に紐付けるルールがある。 | **無効**を選択してください。アカウント間でトランザクションが移譲されないことが保証されます。 | ## 未来の日付のイベントタイムスタンプ(Apple/iOS) \{#event-timestamps-with-future-dates-appleios\} この動作はApple App Storeに特有のものです。Google Playの通知システムはイベントを事前に送信しません。 プロファイルやインテグレーションのイベントタイムスタンプが未来の日付を示すことがあります。これはAppleが更新イベントを事前に送信するためです。 - **発生理由**:Appleはサブスクリプションが期限切れになる前に自動更新されるようにしており、ユーザーのサービス中断を防ぐためです。詳細はAppleのデベロッパーフォーラムをご覧ください:[Server Notifications for Subscriptions](https://developer.apple.com/forums/tags/app-store-server-notifications)。 - **影響するイベントの種類**:通常、サブスクリプションの更新とトライアルから有料への転換に適用されます。これらのイベントはAppleが事前に通知するため、未来のタイムスタンプを持つ場合があります。 - **その他のイベントの種類**:追加のアプリ内課金とサブスクリプションプランの変更は、事前に予測できないため、実際のタイムスタンプで記録されます。 - **アナリティクスとイベントフィードへの影響**:これらのイベントは、タイムスタンプが過ぎた後にのみ**Analytics**と**Event Feed**に表示されます。未来のタイムスタンプを持つイベントはどちらのセクションにも表示されません。 - **インテグレーションへの影響**:Adaptyはイベントを受信したらすぐにインテグレーションへ送信します。イベントが未来のタイムスタンプを持つ場合、Adaptyはその未来のタイムスタンプをそのままインテグレーションに送信します。 ## 次のステップ \{#next-steps\} - プロファイルダッシュボードを使用してユーザーを検索・管理するには、[プロファイル](profiles-crm)を参照してください。 - アプリでのユーザー識別を設定するには、[ユーザーの識別](identifying-users)SDKガイドを参照してください。 - アクセス共有ポリシーを設定するには、[ユーザーアカウント間での有料アクセスの共有](sharing-paid-access-between-user-accounts)を参照してください。 --- # File: sharing-paid-access-between-user-accounts --- --- title: "ユーザーアカウント間での有料アクセスの共有" description: "複数のデバイスや複数のアプリプロファイルを持つユーザーに対応するため、異なるユーザーアカウント間で有料アクセスを共有する方法" --- ユーザーが購入を行うと、Adapty はアクティブな[プロファイル](identifying-users)に新しい[アクセスレベル](access-level)を割り当てます。このアクセスレベルにより、購入者は有料コンテンツにアクセスできるようになります。 購入者のプロファイルは、アプリの再インストールや新しいアプリ内アカウントへのログインによって意図せず変わることがあります。アクセスが途切れないよう、Adapty は元のプロファイルとその後のプロファイルの間でユーザーのアクセスレベルを自動的に共有します。 このアプローチはほとんどのアプリケーションに最適です。ただし、ビジネスロジックの要件によっては、より制限的な有料アクセス共有ポリシーを選択することもできます。 [General Settings](https://app.adapty.io/settings/general) ページを開いて、アクセスレベルの共有ポリシーを設定してください。テストを容易にするため、[サンドボックス環境のみ](#sharing-paid-access-on-sandbox)でこの設定を変更することもできます。 <Details> :::important アプリケーションがユーザー認証を行っていない場合、この設定は無視してかまいません。同じストアアカウントに関連付けられた匿名プロファイルは、*常に*アクセスレベルを共有します。 ::: <summary>どのアクセス共有ポリシーを選べばよいですか?(クリックして展開)</summary> | 私のアプリは… | おすすめの設定 | | ------------------------------------------------------------ | ------------------------------------------------------------ | | 認証機能を持たず、Adapty の匿名プロファイル ID のみを使用している。 | **Enabled (default)** 設定を使用してください。 | | ユーザー認証が可能だが、アカウントなしで購入できる。 | **Transfer access to new user** 設定を有効にしてください。ユーザーがサインアップして匿名購入を引き継げるようになります。 | | 購入前にアカウント作成が必須だが、1 つのプロダクトを複数の Customer User ID にリンクできる。 | **Transfer access to new user** 設定を有効にしてください。複数のアカウントがプロダクトにアクセスできますが、順番にのみアクセス可能です。 | | 購入前にアカウント作成が必須で、購入を単一の Customer User ID に紐付ける厳格なルールがある。 | アクセスレベルの共有を**無効**にしてください。 | </Details> <img src="/assets/shared/img/sharing-paid-access.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Enabled(デフォルト) \{#enabled-default\} この設定は、**組み込み認証を持たない**アプリケーションに最適です。購入後、同じストアアカウントに関連付けられたすべてのプロファイルがアクセスレベルを自動的に*継承*します。 * ユーザーが新しい認証情報でアプリにログインしても、有料コンテンツへのアクセスは維持されます。 * ユーザーが工場出荷時リセット後にアプリを再インストールしても、有料コンテンツへのアクセスは維持されます。 * ユーザーが同じストアアカウントで他のデバイスにアプリをインストールしても、購入はすべてのデバイスで利用可能になります。アプリの各インスタンスが独自のカスタマープロファイルを持っている場合でも同様です。 ## Transfer access to new user \{#transfer-access-to-new-user\} この設定は、**認証の有無にかかわらず購入を許可する**アプリケーション、または**1 デバイスにつき 1 ユーザー**のポリシーを適用したいアプリケーションに最適です。 Adapty は購入へのアクセスを一度に 1 つの Customer ID に制限します。デバイス所有者はアプリを再インストールしたり、ログインとログアウトを繰り返すことができますが、複数の Customer ID から同時に同じプロダクトにアクセスすることはできません。 この設定を有効にすると、匿名プロファイル(たとえばユーザーがログアウトした後にアクティブになるプロファイル)は常に最後にアクティブだった Customer ID のアクセスレベルを継承します。これは後でアクセスを失わないようにするために必要です。 :::warning デフォルト設定を無効にして **Transfer access to new user** を有効にしても、Adapty は既存のカスタマープロファイルのアクセスレベルをすぐには更新しません。 切り替えは、ユーザーが新しいストアイベント(サブスクリプションの更新や購入の復元など)をトリガーしたときに行われます。 ::: :::important Adapty が古いプロファイルを失効させるのは、SDK がトランザクションを伝播する時点で新しいプロファイルに [Customer User ID](identifying-users#set-customer-user-id-on-configuration) が設定されている場合のみです。`restorePurchases` が匿名プロファイルで実行された場合、古い Customer User ID と新しい匿名プロファイルの両方がアクセスレベルを持つことになります。古いプロファイルは、匿名プロファイルを識別した後に失効します。 これを避けるには、SDK メソッドをこの順番で呼び出してください:`activate` → `identify` → `restorePurchases`。 ::: ## 有料アクセス共有の無効化 \{#disable-paid-access-sharing\} この設定は、**必須認証**を持つアプリケーション、または独自のアクセス管理を実装しているアプリケーションに**のみ適切**です。それ以外の場合、ユーザーが購入にアクセスできなくなり、アプリが**必須のストアレビューに失敗するリスク**があります。 有料アクセス共有を無効にすると、Adapty は購入時にアクティブな [Customer ID](identifying-users#set-customer-user-id-on-configuration) にプロダクトを紐付け、他のカスタマープロファイルとアクセスレベルを共有しません。このポリシーにより、厳格な 1 対 1 のプロダクト配布が可能になります。 :::warning 有料アクセス共有を無効にすると、Customer ID が有料アクセスを継承できなくなります。過去に有料アクセスを継承した Customer ID がある場合、自動的に取り消すことはできません。 ::: :::important 緊急時には、次に利用可能なプロファイル(識別済みまたは匿名)がアクセスレベルを引き継げるよう、[ユーザープロファイルを削除する](api-adapty/operations/deleteProfile)必要がある場合があります。 ::: ## 実践的なリファレンス \{#practical-reference\} モードを選択したら、以下の一覧で期待される動作を確認してください:どのプロファイルがアクセスを受け取るか、古いプロファイルがいつアクセスを失うか、どのウェブフックイベントが発火するか。 | モード | 複数のプロファイルが 1 つの購入を共有するか | 転送時に古いプロファイルが失効するか | 古いプロファイルが失効するタイミング | 2 番目のプロファイルがサブスクリプションを引き継ぐ際のウェブフックイベント | | --- | --- | --- | --- | --- | | **Enabled (default)** | はい — 復元またはサインインしたすべてのプロファイルがアクセスを継承 | しない | N/A | 継承する各新規プロファイルに `access_level_updated`(`is_active=true`) | | **Transfer access to new user** | いいえ — 排他的だが、プロファイル間で移動可能 | はい | 新しい識別済みデバイスがトランザクションを伝播したとき(`restorePurchases`、identify、または次のストア側イベント)に即時 | 新しいプロファイル:`access_level_updated`(`is_active=true`)。古いプロファイル:`access_level_updated`(`is_active=false`) | | **Disabled** | いいえ — 購入ごとに 1 つの Customer User ID、永続的 | N/A — アクセスは転送されない | N/A | 2 番目のプロファイルには何もなし。SDK はそのプロファイルのアクセスを表示しない | ## サンドボックスでの有料アクセス共有 \{#sharing-paid-access-on-sandbox\} サンドボックス環境専用の有料アクセス共有ポリシーを設定できます。サンドボックス環境で購入をテストする際は、以下の動作が予想されます: * Apple はアカウントの購入履歴に過去の購入情報を保存します。Adapty SDK もこれにアクセスできます。 * アプリを再インストールした際、Adapty がプロダクトがすでに購入済みであることを検出した場合、アクティブなプロファイルがアクセスレベルを継承します。 * Apple がプロダクトの既存の購入を検出した場合、アクティブなプロファイルに必要なアクセスレベルがなくても、同じ購入を 2 回行うことはできません。 この動作は**有料アクセス共有の設定に関係なく**発生します。アプリにペイウォールが表示されず、プロダクトを購入できません。唯一の解決策は、**アカウントの購入履歴をクリアすること**です。詳細な手順は[サンドボックステストガイド](test-purchases-in-sandbox)を参照してください。 :::warning Apple のサンドボックスサブスクリプションは数分ごとに自動更新されます。この急速な更新により、Adapty が[親プロファイル](how-profiles-work#parent-and-inheritor-profiles)として扱うプロファイルが入れ替わることがあります。これは本番環境ではほとんど再現されないパターンです。本番環境で使用するモードをテストし、サンドボックスでの結論を出す前に実際の Apple ID で動作を確認してください。 ::: ## アナリティクスにおける有料アクセス共有 \{#paid-access-sharing-in-analytics\} * Adapty はトランザクションが発生した時点でそれを記録します。1 つのトランザクションが複数のプロファイルに関連付けられることがありますが、複数回カウントされることはありません。 * 2 つ以上のプロファイルが同じアクセスレベルを共有している場合、購入は[親プロファイル](how-profiles-work#parent-and-inheritor-profiles)に帰属されます。 * アクセスレベルの継承はインストール統計には影響しません。Adapty がインストールをカウントする方法を決定するには、設定ページで利用可能な 2 つの[インストール定義](installs#counting-modes)のいずれかを選択できます。 --- # File: segments --- --- title: "セグメント" description: "Adapty でユーザーセグメントを作成・管理して、より精度の高いターゲティングを実現しましょう。" --- **セグメント**は、共通の属性を持つユーザーをグループ化するフィルターの集合です。セグメントを使うと、ペイウォールや A/B テストのターゲティングをより効果的に行えます。 --- no_index: true --- import Callout from '../../../components/Callout.astro'; :::note イベントフィードのイベントはダッシュボードに届くまでに遅延が発生します。新しいプロファイルや属性の変更はすぐに反映されない場合があります。 ::: セグメントを作成したら、[プレースメントや A/B テストで**オーディエンス**として使用](audience)し、ユーザーに表示するペイウォール(単数または複数)を制御できます。使用例: - 非サブスクリプションユーザーには標準のペイウォールを表示し、以前サブスクリプションやトライアルをキャンセルしたユーザーには割引を提示する。 - 国ごとに異なるペイウォールを表示する。 - Apple Search Ads のアトリビューションデータに基づいてユーザーをターゲティングする。 - 古いバージョンのアプリを使用しているユーザーには既存のペイウォールを表示し続け、新しいバージョンのユーザーには更新されたペイウォールを表示する。 - [アナリティクス](controls-filters-grouping-compare-proceeds#filter-and-group-data)では、セグメントでフィルタリングして特定のユーザーグループのパフォーマンスを確認する。セグメントでグループ化すると、**全ユーザー**内でのパフォーマンスや貢献度を比較できる。 <img src="/assets/shared/img/3244407-Segments.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## 作成 \{#creation\} セグメントを作成するには、名前を入力し、フィルターを定義する属性を選択します。複数の属性を選択した場合、ユーザーはすべての条件を満たす必要があります。Adapty は属性間に AND 論理を適用します。 <img src="/assets/shared/img/1af9744-new_cohort.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## 利用可能な属性 \{#available-attributes\} :::note **Country**(国)や **Calculated total revenue USD**(計算済み合計収益 USD)など多くのユーザー属性は自動的に設定されますが、**Age**(年齢)、**App user ID**(アプリユーザー ID)、**Attribution**(アトリビューション)データ、**Gender**(性別)、**Custom attributes**(カスタム属性)は自動的には設定されません。セグメント化に利用する場合は、[ユーザー属性を設定](setting-user-attributes)するか、[アトリビューションデータを渡す](attribution-integration)必要があります。 ::: :::tip 日付ベースの属性には、以下の方法でフィルタリングできます: - **固定日付**: カレンダーから特定の日付を選択(例:ブラックフライデーからサイバーマンデーの間にインストールしたユーザーに特別オファーを表示) - **相対範囲**: 「過去 7 日間」や「過去 3 ヶ月」などの動的な期間を設定(例:30 日以上前に最後に見られたユーザーを再エンゲージしたり、最近のインストールをターゲティングしたりする) 相対範囲は自動的に更新されるため、継続的なキャンペーンに最適です。固定日付は期間限定のプロモーションに最も適しています。 ::: | 属性 | フィルター対象 | |---------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Age** | ユーザーの年齢。年齢は Adapty が最初に受け取った時点で計算され、その後は更新されません。 | | **App User ID** | アプリ内のユーザー識別子([customer_user_id](profiles-crm#user-attributes))。存在するかどうかでフィルタリングできます。例えば、ログインしていないユーザーにのみペイウォールを表示する場合などに使います。 | | **App version (current)** | Adapty が最後にイベントデータを受け取ったユーザーデバイスにインストールされているアプリの現在のバージョン。ユーザーがアップグレードすると**更新され**、常に現在実行中のバージョンを反映します。特定のバージョンを実行しているすべてのユーザー(以前のバージョンからアップグレードしたユーザーを含む)にロールアウトする場合に使用します。セグメント作成時に、**App version** の横にある鉛筆アイコンを選択して新しいバージョンを追加すると、すぐに使用できます。<br/> **version > X.X** 条件を使うと、各バージョンを個別にリストアップすることなく、特定のバージョンより古いまたは新しいすべてのアプリバージョンのコンバージョンへの影響を計測できます。<br/><br/> **フォーマット:** バージョン文字列は [SemVer](https://semver.org/) 形式に従う必要があります。各部分の先頭ゼロは無効です。`26.03.4` はマッチしませんが、`26.3.4` はマッチします。無効なバージョンはセグメントから黙って除外されます。 | | **App version (on install)** | Adapty が初めてイベントデータを受け取ったときにユーザーデバイスにインストールされていたアプリのバージョン。インストール時の値に**固定され、ユーザーがアップグレードしても更新されません**。現在のバージョンではなく、最初にインストールしたバージョンでユーザーをターゲティングする場合に使用します。`App version (on install) = 1.5.7` は、初回インストールが 1.5.7 だったユーザーのみにマッチし、以前のバージョンから 1.5.7 にアップグレードしたユーザーは黙って除外されます。アップグレードユーザーも対象にするには、**App version (current)** を使用してください。<br/><br/> **フォーマット:** バージョン文字列は [SemVer](https://semver.org/) 形式に従う必要があります。各部分の先頭ゼロは無効です。`26.3.04` はマッチしませんが、`26.3.4` はマッチします。無効なバージョンはセグメントから黙って除外されます。 | | **Attribution: Ad Group** | アトリビューションの広告グループ。 | | **Attribution: Ad Set** | アトリビューションの広告セット。 | | **Attribution: Campaign** | マーケティングキャンペーン名。 | | **Attribution: Creative** | アトリビューションのクリエイティブキーワード。 | | **Attribution: Channel** | マーケティングチャネル名。 | | **Attribution: Source** | アトリビューションの発生元。 | | **Attribution: Status** | アトリビューションのステータス。設定可能な値:<ul><li>**Organic** – 有料マーケティングの影響を受けずにアプリをインストールしたユーザー(App Store/Google Play での直接検索、口コミ、オーガニックソーシャルメディアなど)。</li><li>**Non-organic** – 有料マーケティングチャネル経由で獲得したユーザー(広告、インフルエンサーキャンペーン、リファラルプログラムなど)。</li><li>**Unknown** – このユーザーのアトリビューションデータが利用できない。</li></ul> | | **Calculated subscription state** | ユーザーの[現在のサブスクリプション状態](profiles-crm#subscription-state)。サブスクリプションがアクティブか、キャンセル済みか、または未解決の請求問題があるかを示します。 | | **Calculated total revenue USD** | このユーザーが生み出した合計収益。 | | **Country** | 直近の IP アドレスから判定された顧客の国。Adapty は IP シグナルを最大週 1 回更新するため、ユーザーが場所を変えたり VPN を使用したりすると値がずれる場合があります。ユーザーの App Store / Play Store アカウントの国でターゲティングする場合は、**Country from store account** を使用してください。 | | **Country from store account** | ユーザーの iOS または Android ストアアカウントに関連付けられた国。Adapty がストアの国を収集するのは、バージョン 13 以降の iOS デバイスのみです。 | | **Creation date** | プロファイルが作成された日付(ユーザーのデバイスにアプリが初めてインストールされた日時)。 | | **Device** | メタデータに基づくデバイスタイプ。例:「Samsung Galaxy」や「iPhone 13」 | | **Gender** | ユーザーの性別。この値は自分で設定します。 | | **Installation date** | ユーザーがアプリをインストールした日付。 | | **Language** | ユーザーのデバイスの言語。<Callout type="warning">Adapty は言語を 2 文字の `ISO 639-1` コードで保存します。`zh-Hant-TW` や `pt-BR` のような拡張ロケールは使用しないでください。ドロップダウンに表示される場合がありますが、どのユーザーにもマッチしません。</Callout> <Callout type="tip">言語ターゲティングをさらに絞り込むには、**Language** と **Country** を組み合わせてください。例えば、**簡体字中国語(`zh`)** + **Country = TW, HK, MO** とすると、繁体字スクリプトのユーザーをターゲットにできます。</Callout> | | **Last seen** | ユーザーが最後にアプリを開いた日付。 | | **OS** | ユーザーデバイスのオペレーティングシステムのバージョン。 | | **Paid access level** | ユーザーに付与されているアクセスレベル。 | | **Platform** | ユーザーのデバイスプラットフォーム。設定可能な値:`iOS`、`macOS`、`iPadOS`、`visionOS`、`Android`。<br/> ユーザーが複数のプラットフォーム(iOS と Android など)からアプリにアクセスする場合、セグメントへの所属はそれぞれのデバイスの最新データを使って各プラットフォームで個別に評価されます。これにより、同じユーザープロファイルでもプラットフォームごとにターゲティングが可能です。 | | **Subscription expiration date** | サブスクリプションの有効期限、またはその有無。永続アクセス購入の場合は `none` と表示され、ユーザーがプロファイルを持っているがトライアル、サブスクリプション、永続アクセス購入のいずれも行っていない場合は空のままです。 | | **Subscription product** | 顧客のアクティブなサブスクリプションの最新プロダクト ID。 | | **[Custom attributes](profiles-crm#custom-attributes)** | アプリやビジネスに固有のプロパティに基づいて、高度にターゲティングされたセグメントを作成するための独自属性を定義します。 | ## カスタム属性 \{#custom-attributes\} カスタム属性を定義して、アプリやビジネスに固有のプロパティに基づいたより精度の高いセグメントを構築できます。 :::note - カスタム属性は SDK または Adapty ダッシュボードで設定できます。SDK での設定手順は[こちら](setting-user-attributes#custom-user-attributes)をご覧ください。 - セグメントで使用後にカスタム属性を変更すると、[アナリティクス](controls-filters-grouping-compare-proceeds#filter-and-group-data)でそのセグメントとユーザーの同期が外れる場合があります。データは以前の値を反映します。 ::: ### カスタム属性の設定方法 \{#how-to-configure-a-custom-attribute\} Adapty ダッシュボードで、属性のドロップダウンメニューから **Create custom attributes** を選択します。 <img src="/assets/shared/img/883d3b2-CleanShot_2023-03-16_at_17.20.452x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> | フィールド | 説明 | | ------ |--------------------------------------------------------------------------------------------------------------------------------------| | **Name** | カスタム属性のラベル。Adapty ダッシュボード内でのみ使用されます。 | | **Key** | 属性の一意の識別子。SDK で使用されるキーと一致している必要があります。 | | **Type** | 以下から選択します:<ul><li>String:あらかじめ定義した値のリストが必要です。</li><li>Number:数値のみ受け付けます。</li></ul> | | **Values** | `String` を選択した場合は、使用可能な値のリストを入力します。`Number` を選択した場合、属性は数値入力のみ受け付けます。数値属性は小数値をサポートし、比較演算子と組み合わせて使用できます。 | 必須フィールドを入力したら、セグメント、[A/B テスト](ab-tests)などでカスタム属性を使用できます。 各プロファイルには最大 30 個のカスタム属性を設定できます。 ## 総数とランダムサンプル \{#total-number-and-random-sample\} セグメントを作成すると、Adapty はセグメント条件に一致するユーザーの総数を表示します。 また、条件に合致する 40 人のランダムサンプルも表示されます。これを使ってセグメントをテストし、正しく設定されているか確認できます。 <img src="/assets/shared/img/segment-random-set.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## セグメントの複製 \{#duplicate-segments\} 既存のセグメントに似たものが必要な場合は、最初から作り直す代わりに複製しましょう。ユーザーグループが重複する複数のキャンペーンや A/B テストを運用しているチームの作業時間を節約できます。 セグメントを複製すると、すべてのフィルターと説明を含むコピーが作成されます。新しいセグメントの名前には「(copy)」が追加されるので、元のものと区別できます。新しいセグメントは元のセグメントから独立しており、一方への変更は他方に影響しません。 Adapty ダッシュボードでセグメントを複製するには: 1. Adapty メインメニューの **Profiles & Segments** セクションを開き、[**Segments**](https://app.adapty.io/segments) タブに切り替えます。 2. セグメントの横にある **3-dot** ボタンをクリックし、**Duplicate** を選択します。 <img src="/assets/shared/img/duplicate-segment.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. 新しいセグメントを開き、必要に応じてフィルターを調整します。 ## セグメントの削除 \{#delete-segments\} セグメントが不要になったら、完全に削除できます。 以下のいずれかでセグメントが現在オーディエンスとして使用されている場合、Adapty は削除をブロックします: - **プレースメント**:削除されていないプレースメントの少なくとも 1 つがそのセグメントをオーディエンスとして使用している。 - **A/B テスト(ライブまたは完了済み)**:削除されていない A/B テストの少なくとも 1 つがそのセグメントをオーディエンスとして使用している。 セグメントの削除において、Adapty は**ライブ**と**完了済み**の A/B テストをどちらもアクティブとして扱います。完了済みのテストは、テスト後のペイウォールまたはオンボーディングを一致するユーザーに表示するために引き続きオーディエンスを使用しており、テストの過去の指標はそのセグメントにスコープされています。セグメントは A/B テスト自体が削除されて初めて解放されます。 :::warning セグメントの削除は永続的です。削除されたセグメントは復元できません。 ::: Adapty ダッシュボードでセグメントを削除するには: 1. Adapty メインメニューの **Profiles & Segments** に移動し、[**Segments**](https://app.adapty.io/segments) タブに切り替えます。 2. セグメントの横にある **3-dot** ボタンをクリックし、**Delete** を選択します。 3. 確認フィールドにセグメント名を入力し、**Delete forever** をクリックします。 :::info セグメントが使用中の場合、ダイアログにはそれを参照しているプレースメントと A/B テストの一覧が表示されます。 削除のブロックを解除するには、リストの各プレースメントまたは A/B テストを開き、オーディエンスからセグメントを削除するか、プレースメントまたは A/B テスト自体を削除してください。何もセグメントを参照していない状態になれば、削除できます。 ::: --- # File: event-feed --- --- title: "イベントフィード" description: "Adaptyのイベントフィードでユーザーアクティビティを監視・分析します。" --- イベントフィードを使うと、Adaptyが生成した[イベント](events)を視覚的に追跡し、Webhookを含むサードパーティ連携へのエクスポート状況を確認できます。 :::warning イベントフィードには以下は表示されません: - **サーバーサイドAPI v1のトランザクション**:[サーバーサイドAPI(バージョン1)](server-side-api-specs-legacy#requests)を使って作成されたもの。表示させるには[サーバーサイドAPI(バージョン2)](api-adapty/operations/setTransaction)を使用してください。 - **プロファイルのないイベント**:SDKがユーザーを識別する前に届いたトランザクション(例:ストアのサーバー通知)。これらをエクスポートに含めるには、[S3](s3-exports)または[Google Cloud Storage](google-cloud-storage)連携で **Include events without profile** を有効にしてください。 ::: <img src="/assets/shared/img/event-status.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> <p> </p> :::note AppsFlyer、Facebook Ads、Branchの送信ステータスは、エラーが発生しても常に返されるとは限らないため、正確でない場合があります。 ::: トランザクションを開始したユーザーのプロファイルを確認するには、イベント詳細の **View Profile** ボタンをクリックしてください。 --- # File: ab-tests --- --- title: "A/B テスト" description: "Adapty の A/B テストでサブスクリプション価格を最適化し、コンバージョン率を向上させましょう。" --- :::tip 調査なしで実行可能な A/B テスト計画を取得できます。[Growth Autopilot](autopilot) はペイウォールを監査し、競合他社のベンチマークを行い、Adapty が追跡する 20,000 のサブスクリプションアプリの匿名化データからサジェストを生成します。 ::: Adapty で A/B テストを実施して、アプリの収益を向上させましょう。フロー、ペイウォール、オンボーディングを比較して、最もコンバージョンが高いものを見つけてください — コード変更は不要です。たとえば、次の項目をテストできます: - サブスクリプション価格 - ペイウォールのデザイン、コピー、レイアウト - トライアル期間とサブスクリプション期間 - オンボーディングのデザイン ## 前提条件 \{#prerequisites\} A/B テストを設定する前に、以下が必要です: - **プレースメント**:フロー、ペイウォール、またはオンボーディングが表示される 1 つ以上の[プレースメント](placements)。 - **フローの場合**:少なくとも 2 つの[フロー](adapty-flow-builder)。 - **ペイウォールの場合**:少なくとも 2 つの[ペイウォール](paywalls)。 - **オンボーディングの場合**:少なくとも 2 つの[オンボーディング](onboardings)。 :::warning [Adapty Flow builder](adapty-flow-builder) または [Adapty Paywall builder](adapty-paywall-builder) を使用していない場合は、`.logShowFlow()` (iOS SDK v4+) / `.logShowPaywall()` を使って[ペイウォールのビューを Adapty に送信](present-remote-config-paywalls#track-paywall-view-events)してください。このメソッドがないと、Adapty はテスト内のペイウォールビューを計算できず、コンバージョン統計が不正確になります。 ::: ## A/B テストの種類 \{#ab-test-types\} Adapty は 2 つの主要な A/B テストタイプをサポートしています: - **通常**:単一のフロー/ペイウォール/オンボーディングのプレースメントで実行されます。 - **クロスプレースメント**:複数のペイウォールプレースメントにまたがって実行され、同じバリアントをユーザーに一貫して表示します。現在はペイウォールのみで利用可能です。 タイプの詳細な比較、ユースケース、優先順位のルールについては、[A/B テストの種類](ab-test-types)を参照してください。 ## 次のステップ \{#next-steps\} - [Growth Autopilot](autopilot) — ペイウォールを分析し、市場インサイトを取得して、A/B テスト計画を生成する - [A/B テストの種類](ab-test-types) — テストの種類とそれぞれの使いどころを学ぶ - [A/B テストの作成・実行・停止](run_stop_ab_tests) — はじめてのテストをセットアップして実行する - [A/B テストの結果と指標](results-and-metrics) — A/B テストのデータを理解して勝者を選ぶ --- # File: ab-test-types --- --- title: "A/B テストタイプ" description: "Adapty の A/B テストタイプについて説明します。" --- Adapty では、テストシナリオに応じた 2 種類の A/B テストタイプを用意しています。 - **通常の A/B テスト:** 単一の[フロー](adapty-flow-builder)/[ペイウォール](paywalls)/[オンボーディング](onboardings)プレースメントに対して作成する A/B テストです。 - **クロスプレースメント A/B テスト:** アプリ内の複数のペイウォールプレースメントに対して作成する A/B テストです。A/B テストが<InlineTooltip tooltip="バリアント">A/B テストのバリアントとは、テスト対象のフロー、ペイウォール、またはオンボーディングの代替バージョンです。</InlineTooltip>を割り当てると、選択したアプリのすべてのセクションにわたって同じバリアントを一貫して表示します。 :::warning クロスプレースメント A/B テストは、Adapty SDK v3.5.0 以降でのみ利用可能です。クロスプレースメント A/B テストはペイウォールのみで動作します。 フロー A/B テストには Adapty SDK v4.0.0 以降が必要です。 オンボーディング A/B テストには、Adapty SDK v3.8.0 以降(iOS、Android、React Native、Flutter)、v3.14.0 以降(Unity)、または v3.15.0 以降(Kotlin Multiplatform、Capacitor)が必要です。 旧バージョンのユーザーはスキップされます。 ::: 各フロー/ペイウォール/オンボーディングにはウェイトが設定され、テスト中のトラフィックを分割します。 たとえば、ウェイトが 70% と 30% の場合、1,000 人のユーザーのうち最初のペイウォールは約 700 人に、2 番目のペイウォールは約 300 人に表示されます。クロスプレースメントテストでは、ウェイトはペイウォールごとではなくバリアントごとに設定されます。 この設定により、異なるフローやペイウォールを比較し、アプリのマネタイズ戦略についてデータに基づいた意思決定ができます。 ## どちらのタイプを使うべきか \{#when-to-use-each-type\} 各 A/B テストタイプが有効な場面は以下のとおりです。 - **通常の A/B テスト**: - アプリにプレースメントが 1 つしかない場合。 - アプリに複数のプレースメントがある場合でも、1 つのプレースメントのみで A/B テストを実行し、そのプレースメントの経済効果の変化だけを追跡したい場合。 - 過去のユーザー(少なくとも 1 つの Adapty ペイウォールを見たことがあるユーザー)に対して A/B テストを実行したい場合。 - **クロスプレースメント A/B テスト**: - 複数のプレースメントにわたってバリアントを同期させたい場合。たとえば、オンボーディングフローとアプリ設定の両方で同時に価格を変更したい場合。 - アプリ全体の経済効果を評価したい場合。すべてのプレースメントにわたってテストを実行することで、個別のプレースメントをテストするよりも A/B テストの統計が分析しやすくなります。 - 新規ユーザーのみ(Adapty のペイウォールを一度も見たことがないユーザー)に対して A/B テストを実行したい場合。 - 1 つのバリアント内で複数のペイウォールを使用したい場合: <img src="/assets/shared/img/ab-test-variants.png" alt="1 つのクロスプレースメント A/B テストバリアント内に複数のペイウォールがある例" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## 主な違い \{#key-differences\} | 機能 | 通常の A/B テスト | クロスプレースメント A/B テスト | | ------------------------------- |--------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------| | **テスト対象** | 1 つのフロー/ペイウォール/オンボーディング | 1 つのバリアントに属するペイウォールのセット | | **バリアントの一貫性** | バリアントはプレースメントごとに個別に決定される | すべてのペイウォールプレースメントで同じバリアントが使用される | | **オーディエンスのターゲティング** | フロー/ペイウォール/オンボーディングのプレースメントごとに定義される | すべてのペイウォールプレースメントで共有される | | **アナリティクス** | 1 つのフロー/ペイウォール/オンボーディングのプレースメントを分析する | テストの一部であるプレースメントに対してアプリ全体を分析する | | **バリアントのウェイト分布** | フロー/ペイウォール/オンボーディングごと | ペイウォールのセットごと | | **ユーザー** | すべてのユーザー | 新規ユーザーのみ(Adapty ペイウォールを見たことがないユーザー) | | **Adapty SDK バージョン** | フローの場合: v4.0.0 以降。ペイウォールの場合: 任意。オンボーディングの場合: v3.8.0 以降(iOS、Android、React Native、Flutter)、v3.14.0 以降(Unity)、v3.15.0 以降(KMP、Capacitor) | 3.5.0 以降 | | **最適な用途** | アプリ全体の経済効果を考慮せずに、単一のフロー/ペイウォール/オンボーディングプレースメントの独立した変更をテストする場合 | アプリ全体のマネタイズ戦略を評価する場合 | ## A/B テストの選択ロジック \{#ab-test-selection-logic\} **クロスプレースメント A/B テストは通常の A/B テストよりも優先されます。** ただし、クロスプレースメントテストは**新規ユーザー**(まだ Adapty のペイウォールを一度も見ていないユーザー、つまり `getPaywall` SDK メソッドが一度も呼び出されていないユーザー)にのみ表示されます。これにより、プレースメント間での結果の一貫性が確保されます。 以下のダイアグラムは、Adapty がプレースメントに対して A/B テストを選択するためのロジックを示しています。 <img src="/assets/shared/img/ab-tests-scheme.webp" alt="ペイウォールプレースメントの A/B テスト選択ロジックを示すダイアグラム" style={{ border: '1px solid #727272', /* border width and color */ width: '350px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> **A/B Tests** ページでは、ペイウォール、オンボーディング、フロー、クロスプレースメントのテストが別々のタブに表示されます。 <img src="ab-tests-tabs.webp" alt="通常、オンボーディング、クロスプレースメントのテストタイプごとにタブが設けられた A/B テスト一覧ページ" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## クロスプレースメント A/B テストの制限事項 \{#crossplacement-ab-test-limitations\} :::warning クロスプレースメント A/B テストには、フローまたはオンボーディングのプレースメントを含めることができません。 ::: クロスプレースメント A/B テストは、テスト内のすべてのプレースメントで各ユーザーが同じバリアントを見ることを保証します。これにより、以下の制限が生じます。 * 参加できるのは新規ユーザーのみです。新規ユーザーとは、Adapty のペイウォールを見たことがなく、アプリが `getPaywall` を一度も呼び出していないユーザーです。それ以外のユーザーに対して一貫したペイウォールのチェーンを保証することはできません。 * ユーザーが最初に訪れたプレースメントで、Adapty が表示するペイウォールが決まります。ユーザーの割り当てを変更したり、同じユーザーを複数のクロスプレースメント A/B テストに登録したりすることはできません。 :::warning ユーザーがクロスプレースメントのペイウォールを受け取ると、テストを停止した後も 90 日間はそれが表示され続けます。この期間を変更するには、**General** 設定の **[Cross-placement variation stickiness](general#9-cross-placement-variation-stickiness)** を調整してください。 ::: ## クロスプレースメント A/B テストの優先順位 \{#crossplacement-ab-test-priority\} * クロスプレースメント A/B テストは、常に通常の A/B テストおよびオンボーディング A/B テストよりも優先されます。新規ユーザーが同じプレースメントでクロスプレースメントテストと通常のテストの両方の対象となる場合は、クロスプレースメントテストが表示されます。 * 同じオーディエンスを持つ複数のクロスプレースメント A/B テストが同じプレースメントを共有している場合、Adapty は追加された順序に基づいてテストの優先順位を自動的に割り当てます。最初のテストが最高優先度を持ちます。手動で変更することはできません。 * オーディエンスの小さいセグメントをターゲットとするテストは、「すべてのユーザー」セグメントをターゲットとするテストよりも自動的に優先されます。 :::note アナリティクスでは、クロスプレースメント A/B テストはプレースメントごとに 1 つずつ、複数の子テストとして表示されます。子テストの命名パターンは `<test-name> child-0`、`<test-name> child-1` のようになります。番号は A/B テスト詳細ページのプレースメントの順序と対応しています。特定のプレースメントの結果を確認するには、**Placement** でフィルタリングしてください。 ::: ## 次のステップ \{#next-steps\} - [A/B テストの作成・実行・停止](run_stop_ab_tests) — 最初のテストをセットアップして開始する - [A/B テストの結果と指標](results-and-metrics) — パフォーマンスを分析して勝者を選ぶ --- # File: run_stop_ab_tests --- --- title: "A/B テストの作成・実行・停止" description: "Adapty で A/B テストを作成・実行・停止するためのステップバイステップガイド。" --- この記事では、Adapty における A/B テストのライフサイクル全体(テストの作成・実行・停止)について説明します。 ## 前提条件 \{#prerequisites\} A/B テストを設定する前に、以下が必要です。 - [フロー](adapty-flow-builder)/[ペイウォール](paywalls)/[オンボーディング](onboardings)が少なくとも 2 つ作成されていること - アプリに[プレースメント](placements)が設定されていること :::warning [Adapty フロービルダー](adapty-flow-builder)や [Adapty ペイウォールビルダー](adapty-paywall-builder)を使用していない場合は、`.logShowPaywall()` を使って[ペイウォールのビュー情報を Adapty に送信](present-remote-config-paywalls#track-paywall-view-events)してください。このメソッドを使用しないと、Adapty はテスト内のペイウォールビュー数を計算できず、コンバージョン統計が不正確になります。 ::: :::info Adapty の A/B テストは 2 ステップで進みます。まずテストを作成して下書きとして保存します。この時点ではすぐには公開されません。準備ができたら、別途実行します。これにより、ユーザーに表示される前に設定内容を確認できます。 ::: ## A/B テストを作成する \{#create-an-ab-test\} 新しい A/B テストを作成する際は、[フロー](adapty-flow-builder)/[ペイウォール](paywalls)/[オンボーディング](onboardings)を少なくとも 2 つ含める必要があります。 新しい A/B テストを作成するには: 1. Adapty のメインメニューから [**A/B tests**](ab-tests) に移動します。 <img src="/assets/shared/img/go-to-abtests.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. 右上の **Create A/B test** をクリックします。 <img src="/assets/shared/img/create-abtest.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. **Create the A/B test** ウィンドウで **Test name** を入力します。これは必須項目です。結果を確認する際に識別しやすいよう、テストの内容を明確に表す名前を選んでください。 4. **Test goal** に達成したい目標(例:サブスクリプションの増加やチャーンの削減)を記入します。 5. **Select placement** をクリックして、フロー・ペイウォール・オンボーディングのプレースメントを選択します。 6. **Variants** テーブルでテストの内容を設定します。各行がバリアント、各列がプレースメントになります。各交点にペイウォールを追加します。 デフォルトでは、テーブルに 2 つのバリアントと 1 つのプレースメントがあります。バリアントは最大 20 個まで追加できます。2 つ目のプレースメントを追加すると、テストはクロスプレースメント A/B テストになります。なお、クロスプレースメント A/B テストはペイウォールのみ対応しています。 <img src="/assets/shared/img/abtest-variants.webp" style={{ border: '1px solid #727272', width: '700px', display: 'block', margin: '0 auto' }} /> 7. テストを保存します。2 つの選択肢があります: 1. **Save as draft**:テストはすぐに公開されません。後でプレースメントまたは A/B テストリストから起動できます。公開前に設定を確認したい場合に使用してください。 2. **Run A/B test**:テストをすぐに起動します。このボタンをクリックした瞬間にテストが公開されます。 下書きとして保存した後は、[A/B テストを実行する](#run-an-ab-test)に進んでください。 ## A/B テストを編集する \{#edit-an-ab-test\} A/B テストは下書きとして保存されている場合にのみ編集できます。テストが公開された後は変更できません。公開中のテストを更新するには、**Modify** オプションを使用します。これにより同じ名前の複製が作成され、そこで変更を加えることができます。Adapty は元のテストを停止し、元のバージョンと修正バージョンがどちらも分析画面に別々に表示されます。 ## A/B テストを実行する \{#run-an-ab-test\} Adapty で A/B テストを実行するとは、プレースメントに割り当ててユーザーへのペイウォールやオンボーディングの表示を開始することを意味します。 1. Adapty のメインメニューから [**A/B tests**](ab-tests) セクションに移動します。 2. 正しいリストを表示していることを確認してください。**Paywall**・**Flow**・**Onboardings**・**Crossplacement** の A/B テストは、切り替え可能な別々のタブに表示されます。 <img src="/assets/shared/img/ab-tests-tabs.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. **Drafts** タブに切り替えます。起動できるのは下書きのテストのみです。 4. 起動したいテストの横にある **Run A/B test** をクリックします。 <img src="/assets/shared/img/run-ab-test-2.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. **Edit A/B test** ウィンドウが開きます。設定を確認し、必要な最終変更を行います。プレースメントやオーディエンスが未設定の場合は、ここで追加してください。 6. 設定を確認したら、**Run A/B test** をクリックして開始します。 テストを起動した後は、[A/B テストの結果と指標](results-and-metrics)ページで進捗を追跡し、パフォーマンスデータを確認できます。 ## A/B テストを停止する \{#stop-an-ab-test\} A/B テストを停止すると、テストが終了し結果を確認できます。また、テスト終了後に対象プレースメントでユーザーに何を表示するかを決定します。 <img src="/assets/shared/img/stop-ab-test.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 1. [**A/B tests**](https://app.adapty.io/ab-tests) セクションを開き、**Live** タブに移動します。 2. 停止したいテストの横にある 3 点メニューをクリックし、**Stop A/B test** を選択します。 3. **Stop the A/B test** ウィンドウで、テスト終了後の動作を決定します。3 つの選択肢があります: | オプション | 説明 | |----------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | テスト済みのペイウォール/オンボーディングのいずれかを表示する | 収益・最良確率(**P2BB**)・1,000 ユーザーあたりの収益などのテスト結果をもとに、勝者のペイウォールまたはオンボーディングを選択します。選択したプレースメントとオーディエンスに対して、そのペイウォールまたはオンボーディングが表示されます。 | | A/B テストに参加していないペイウォール/オンボーディングを選択する | 現在の A/B テストに含まれていないペイウォールまたはオンボーディングを選択します。テストしたバリアントがどれも目標を達成しなかった場合に使用します。 | | 特定のペイウォール/オンボーディングを表示しない | 選択したプレースメントとオーディエンスに対して、A/B テスト終了後に特定のペイウォールまたはオンボーディングは選択されません。代わりに、オーディエンスの優先度に基づいて次に利用可能なペイウォールまたはオンボーディングが表示されます。手動で選択せずに既存の設定でペイウォールまたはオンボーディングを決定したい場合に適しています。 | :::note A/B テストの停止は取り消しできません。テストを再起動することはできないため、停止を決定する前に十分なデータが集まっていることを確認してください。 ::: 4. **Stop and complete this A/B test** ボタンをクリックします。 A/B テストが終了すると、テストはアクティブでなくなり、テスト内のペイウォールまたはオンボーディングは新しいユーザーに表示されなくなります。 テスト実行中に参加したユーザーのパフォーマンスを確認するために、[A/B テストの指標ページ](results-and-metrics#metrics-controls)で引き続き A/B テストの結果と指標にアクセスできます。それらのユーザーに新たな購入や収益イベントが紐付けられると、指標は引き続き更新される場合があります。 --- # File: ab-test-no-paywall-variants --- --- title: "フローまたはペイウォールなしでA/Bテストのバリアントを追加する" description: "リモートコンフィグのフラグを使って表示を制御し、フローまたはペイウォールをスキップするバリアントでA/Bテストを実行する方法。" --- フローまたはペイウォールの効果を、空のバリアントとのA/Bテストで測定できます。一方のバリアントはフロー/ペイウォールを表示し、もう一方は何も表示しません。アプリはリモートコンフィグのフラグを読み取って、レンダリングするかどうかを判断します。 ## 仕組み \{#how-it-works\} 同じプレースメントに2つのフロー/ペイウォールを設定します。 - **フロー/ペイウォール A**: テストしたいフローまたはペイウォール。リモートコンフィグで `show_paywall` を `true` に設定します。 - **フロー/ペイウォール B**: 空のフローまたはペイウォール。リモートコンフィグで `show_paywall` を `false` に設定します。 SDKがフローまたはペイウォールを返すと、アプリは `show_paywall` フラグを読み取ります。フラグが `true` の場合はレンダリングし、`false` の場合はレンダリングをスキップして、ユーザーは何も見ずに続行します。 ## 1. リモートコンフィグにshow_paywallフラグを追加する \{#1-add-the-show_paywall-flag-in-remote-config\} 同じプレースメントに2つのフローまたはペイウォールが必要です。フロー/ペイウォール A(テストしたいもの)とフロー/ペイウォール B(空のもの)です。両方のバリアントで同じキーを使って分岐できるよう、それぞれに `show_paywall` フィールドを追加します。 フロー/ペイウォール A にフラグを追加するには: 1. Adapty のメインメニューで [**Flows**](https://app.adapty.io/flows)/[**Paywalls**](https://app.adapty.io/paywalls) セクションを開き、フロー/ペイウォール A を選択します。 2. **Remote config** セクションを開きます。 3. 名前 `show_paywall`、値 `true` のフィールドを作成します。**JSON** ビューでは次のようになります: ```json showLineNumbers { "show_paywall": true } ``` 4. 変更を保存します。 フロー/ペイウォール B にも同じ手順を繰り返しますが、`show_paywall` を `false` に設定します。 リモートコンフィグの詳細については、[リモートコンフィグでフローをカスタマイズする](customize-flow-with-remote-config)または[リモートコンフィグでペイウォールをデザインする](customize-paywall-with-remote-config)を参照してください。 :::tip 両方のバリアントに `show_paywall` を設定することで、両グループのコードパスが同一になり、後からバリアントを追加するときも簡単に拡張できます。 ::: ## 2. A/Bテストを設定する \{#2-set-up-the-ab-test\} 1. プレースメントに[A/Bテストを作成](run_stop_ab_tests)し、両方のフロー/ペイウォールをバリアントとして追加します。 2. バリアントのウェイトを設定して、フロー/ペイウォールを見るユーザーと見ないユーザーにトラフィックを分配します。 ## 3. アプリでフラグを確認する \{#3-check-the-flag-in-your-app\} SDKから返されるリモートコンフィグの `show_paywall` を読み取ります。フラグが `false` の場合、レンダリングをスキップしてユーザーを続行させます。 <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS" default> ```swift showLineNumbers do { let flow = try await Adapty.getFlow(placementId: "YOUR_PLACEMENT_ID") let config = flow.remoteConfigs.first(where: { $0.locale == "en" }) ?? flow.remoteConfigs.first let showPaywall = config?.dictionary?["show_paywall"] as? Bool ?? true if showPaywall { // render the flow or paywall } } catch { // handle the error } ``` </TabItem> <TabItem value="kotlin" label="Android"> ```kotlin showLineNumbers Adapty.getPaywall("YOUR_PLACEMENT_ID") { result -> when (result) { is AdaptyResult.Success -> { val paywall = result.value val showPaywall = paywall.remoteConfig?.dataMap?.get("show_paywall") as? Boolean ?: true if (showPaywall) { // Render the paywall } } is AdaptyResult.Error -> { // handle the error } } } ``` </TabItem> <TabItem value="react-native" label="React Native"> ```typescript showLineNumbers try { const paywall = await adapty.getPaywall({ placementId: "YOUR_PLACEMENT_ID" }); const showPaywall = paywall.remoteConfig?.data?.["show_paywall"] ?? true; if (showPaywall) { // Render the paywall } } catch (error) { // handle the error } ``` </TabItem> <TabItem value="flutter" label="Flutter"> ```dart showLineNumbers try { final paywall = await Adapty().getPaywall(id: "YOUR_PLACEMENT_ID"); final bool showPaywall = paywall.remoteConfig?.dictionary?['show_paywall'] as bool? ?? true; if (showPaywall) { // Render the paywall } } on AdaptyError catch (adaptyError) { // handle the error } ``` </TabItem> <TabItem value="unity" label="Unity"> ```csharp showLineNumbers Adapty.GetPaywall("YOUR_PLACEMENT_ID", (paywall, error) => { if (error != null) { // handle the error return; } var showPaywall = paywall.RemoteConfig?.Dictionary?["show_paywall"] as bool? ?? true; if (showPaywall) { // Render the paywall } }); ``` </TabItem> <TabItem value="kmp" label="Kotlin Multiplatform"> ```kotlin showLineNumbers Adapty.getPaywall( placementId = "YOUR_PLACEMENT_ID" ).onSuccess { paywall -> val showPaywall = paywall.remoteConfig?.dataMap?.get("show_paywall") as? Boolean ?: true if (showPaywall) { // Render the paywall } }.onError { error -> // handle the error } ``` </TabItem> <TabItem value="capacitor" label="Capacitor"> ```typescript showLineNumbers try { const paywall = await adapty.getPaywall({ placementId: 'YOUR_PLACEMENT_ID' }); const showPaywall = paywall.remoteConfig?.data?.['show_paywall'] ?? true; if (showPaywall) { // Render the paywall } } catch (error) { // handle the error } ``` </TabItem> </Tabs> フォールバック値を `true` にしておくことで、フラグがない場合もフロー/ペイウォールは表示されたままになり、フラグを持たない既存のフロー/ペイウォールに影響しません。 :::important ペイウォールを自分でレンダリングする場合([フロービルダー](adapty-flow-builder)や[ペイウォールビルダー](adapty-paywall-builder)を使わない場合)、フロー/ペイウォール A を表示する際に [`logShowFlow`(iOS SDK v4+)/ `logShowPaywall`](present-remote-config-paywalls#track-paywall-view-events) を呼び出してください。これをしないと、Adapty はテストのビュー数を計測できません。フロー/ペイウォール B は表示されないため、ビューをログに記録しないでください。 ::: ## 次のステップ \{#next-steps\} - [A/Bテストの作成・実行・停止](run_stop_ab_tests) — 両方のバリアントを含むテストを設定する - [A/Bテストの結果と指標](results-and-metrics) — 空のバリアントとフロー/ペイウォールを比較する --- # File: results-and-metrics --- --- title: "A/B テストの結果と指標" description: "Adapty の結果と主要指標を分析して、アプリのサブスクリプションパフォーマンスとユーザーエンゲージメントを改善しましょう。" --- [A/B テスト](ab-tests)では、さまざまなペイウォールやオンボーディングを比較し、ユーザーの行動・エンゲージメント・コンバージョン率にどう影響するかを確認できます。ここで紹介する指標や結果を活用すれば、より賢い判断を下してアプリのパフォーマンスを向上させることができます。データを深掘りして、実践的なインサイトを見つけましょう。 ## A/B テストの結果 \{#ab-test-results\} Adapty が A/B テストの結果として提供する主な指標は以下の 3 つです。 <img src="/assets/shared/img/ab-test-results.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> **Revenue(収益)**: この指標は、購入とリニューアルから発生した USD 総収益から、ユーザーへの返金を差し引いた金額を示します。初回購入だけでなく、その後のサブスクリプション更新も含まれます。収益を見ることで、各 A/B テストバリアントの財務パフォーマンスを把握し、どのバリアントが最も多くの収益をもたらしているかを判断できます。 [ペイウォール](paywall-metrics)の指標についてはこちらをご覧ください。 **Probability to be best(最良の確率)**: Adapty は強固な数学的分析フレームワークを用いて A/B テストの結果を分析し、「最良の確率(Probability to be best)」という指標を提供します。この指標は、特定のバリアントがテストされたすべてのバリアントの中で最も優れたパフォーマンス(長期的な収益の観点から)である可能性を評価します。1% ~ 100% のパーセンテージで表されます。Adapty がこの指標を計算する方法については、[ドキュメント](maths-behind-it)をご参照ください。1K ユーザーあたりの収益で最も優れたオプションは緑色でハイライトされ、デフォルトとして自動的に選択されます。 **Revenue per 1K users(1K ユーザーあたりの収益)**: この指標は、各 A/B テストバリアントにおける 1,000 ユーザーあたりの平均収益を計算します。ユーザー総数に関わらず、バリアントの収益効率を把握するのに役立ちます。標準化されたスケールで異なるバリアントのパフォーマンスを比較し、収益創出効率に基づいて情報に基づいた意思決定を行えます。 **Prediction intervals for revenue 1K users(1K ユーザー収益の予測区間)**: 1K ユーザーあたりの収益指標には予測区間も含まれています。この予測区間は、利用可能なデータと統計分析に基づいて、特定のバリアントの 1,000 ユーザーあたりの真の収益が収まると予測される範囲を表します。 A/B テストにおいて、異なるバリアントが生み出す収益を分析する際、各バリアントの 1,000 ユーザーあたりの平均収益を計算します。収益はユーザーごとに異なるため、予測区間は予測プロセスに伴う変動性と不確実性を考慮しつつ、1,000 ユーザーあたりの収益の妥当な値の範囲を明確に示します。 1K ユーザーあたりの収益指標に予測区間を組み込むことで、Adapty は A/B テストバリアントの収益効率を評価しながら、潜在的な収益結果の幅も考慮できるようにしています。この情報は、予測プロセスの不確実性と 1,000 ユーザーあたりの収益の妥当な値を踏まえた、データに基づく意思決定とサブスクリプション戦略の最適化に役立ちます。 これらの指標を分析することで、A/B テストバリアントの財務パフォーマンス・統計的有意性・収益効率についてのインサイトを得られ、データに基づいた意思決定とサブスクリプション戦略の効果的な最適化が可能になります。 ## A/B テストの指標 \{#ab-test-metrics\} Adapty は、ペイウォールやオンボーディングのバリエーションに対して実施された A/B テストのパフォーマンスを効果的に測定するための包括的な指標セットを提供します。これらの指標はリアルタイムで継続的に更新されますが、ビュー数は定期的に更新されます。これらの指標を理解することで、さまざまなバリエーションの効果を評価し、ペイウォールやオンボーディング戦略を最適化するためのデータドリブンな意思決定が可能になります。 A/B テストの指標は A/B テストリストで確認でき、すべての A/B テストのパフォーマンス概要を把握できます。この包括的なビューでは各テストバリエーションの集計指標が表示され、パフォーマンスの比較や有意な差異の特定が可能です。各 A/B テストのより詳細な分析には、A/B テスト詳細指標にアクセスできます。このセクションでは選択した A/B テストに固有の詳細な指標が提供され、個々のバリエーションのパフォーマンスを深く掘り下げることができます。 ビュー数を除くすべての指標は、ペイウォールやオンボーディング内のプロダクトに紐付けられます。 ## インストール日で指標をフィルタリング \{#filter-metrics-by-install-date\} --- no_index: true --- ペイウォール、トライアル、購入の指標は、2つの異なる日付でグループ化できます: - **イベント日** — ペイウォールが表示された日、トライアルが開始された日、または購入が行われた日。 - **インストール日** — ユーザーが初めてアプリを開いた日。 同じ日付範囲でも、この2つのビューは大きく異なる数値を示すことがあります。**Filter metrics by install date** チェックボックスで、ダッシュボードがどちらを使用するかを制御します: - **チェックなし(デフォルト)**:指標はイベント日でグループ化されます。 - **チェックあり**:指標はインストール日でグループ化されます。 **例。** 日付範囲を4月1日〜30日に設定し、トライアルを確認します。 - **チェックなし**:それらのユーザーがいつインストールしたかに関わらず、4月に*開始*されたトライアルを表示します。 - **チェックあり**:トライアルがいつ開始されたかに関わらず、4月に*インストール*したユーザーのトライアルを表示します。 特定のコホートのユーザー獲得パフォーマンスを測定するにはインストール日ビューを使用し、特定の期間のペイウォールやオンボーディングのアクティビティを測定するにはイベント日ビューを使用してください。 ## 指標のコントロール \{#metrics-controls\} システムは選択した期間に基づいて指標を表示し、3 段階のインデントを持つ左側カラムのパラメータに従って整理します。 ### 期間の選択 \{#time-ranges\} 分析する期間を日・週・月やカスタム日付範囲など、さまざまな時間軸から選択できます。 <img src="/assets/shared/img/ab-test-time-ranges.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### 利用可能なフィルターとグループ化 \{#available-filters-and-grouping\} :::link メイン記事:[アナリティクスのコントロール](controls-filters-grouping-compare-proceeds) ::: Adapty は、ニーズに合わせた指標分析のフィルタリングとカスタマイズのための強力なツールを提供しています。Adapty の指標ページでは、さまざまな期間・グループ化オプション・フィルタリング機能を利用できます。 - ✅ フィルター対象:オーディエンス、アトリビューション、国、ペイウォール、ペイウォールの状態、ペイウォールグループ、オンボーディング、プレースメント、国、ストア、プロダクト、プロダクトストア - ✅ グループ化対象:プロダクトおよびストア :::note A/B テストでフィルタリングすると、クロスプレースメント A/B テストはプレースメントごとに個別の子テスト(例:`My test child-0`、`My test child-1`)として表示されます。詳細は [クロスプレースメント A/B テストの制限事項](ab-test-types#crossplacement-ab-test-limitations)をご覧ください。 ::: ## 単一指標チャート \{#single-metrics-chart\} ペイウォールやオンボーディングの指標ページの主要コンポーネントの一つが、選択した指標を視覚的に表示して分析を容易にするチャートセクションです。 <img src="/assets/shared/img/e6b0674-Area.gif" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> A/B テスト指標ページのチャートセクションには、選択した指標の値を視覚的に表す横棒グラフが含まれています。グラフの各バーは指標値に対応し、サイズが比例しているためデータをひと目で把握できます。横軸は分析対象の期間を示し、縦軸には指標の数値が表示されます。すべての指標値の合計はグラフの横に表示されます。 また、チャートセクション右上の矢印アイコンをクリックすると、ビューが拡大され、選択した指標がチャートの全体ラインに表示されます。 ## A/B テストのサマリー \{#ab-test-summary\} 単一指標チャートの隣には A/B テスト詳細サマリーセクションが表示されており、A/B テストの状態・期間・プレースメント・その他の関連詳細情報が含まれています。 <img src="/assets/shared/img/90fa3f5-Area.gif" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## 指標の定義 \{#metrics-definitions\} A/B テストで利用可能な主要指標は以下のとおりです。 <img src="/assets/shared/img/30c7b68-Area.gif" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### Revenue(収益) \{#revenue\} Revenue は、A/B テストによる購入とリニューアルから発生した USD 総収益を表します。初回購入とその後のサブスクリプション更新が含まれます。収益指標は App Store または Play Store の手数料を差し引く前の金額で計算されます。 [ペイウォール](paywall-metrics#revenue)の収益指標についてはこちらをご覧ください。 ### CR to purchases(購入へのコンバージョン率) \{#cr-to-purchases\} 購入へのコンバージョン率は、A/B テストがビューを実際の購入に転換する効果を測定します。購入数をビュー数で割ることで計算されます。例えば、購入数が 10、ビュー数が 100 の場合、購入へのコンバージョン率は 10% になります。 ### CR trials(トライアルへのコンバージョン率) \{#cr-trials\} トライアルへのコンバージョン率(CR)は、A/B テストから開始されたトライアル数をビュー数で割った値です。A/B テストがビューをトライアル有効化に転換する効果を測定します。開始されたトライアル数をビュー数で割ることで計算されます。 ### Purchases(購入数) \{#purchases\} 購入数指標は、A/B テストによってペイウォールやオンボーディング内で行われたトランザクションの総数を表します。以下の種類の購入が含まれます。 - 新規購入 - 有効化されたトライアルのトライアル転換 - サブスクリプションのダウングレード、アップグレード、クロスグレード - サブスクリプションの復元(自動更新なしで期限切れになったサブスクリプションが後に復元された場合など) なお、更新(リニューアル)は購入数指標には含まれません。 ### Trials(トライアル数) \{#trials\} トライアル数指標は、A/B テストによって有効化されたトライアルの総数を示します。 ### Trials cancelled(キャンセルされたトライアル) \{#trials-cancelled\} キャンセルされたトライアル指標は、自動更新がオフになったトライアルの数を表します。これはユーザーがトライアルを手動で解除した場合に発生します。 ### Refunds(返金) \{#refunds\} A/B テストの返金は、テストされたバリエーションに関連する返金された購入とサブスクリプションの件数を表します。 ### Views(ビュー数) \{#views\} ビュー数は、A/B テストを構成するペイウォールやオンボーディングが閲覧された回数です。同じユーザーが 2 回訪問した場合、2 回としてカウントされます。 ### Unique views(ユニークビュー数) \{#unique-views\} ユニークビュー数は、ペイウォールやオンボーディングのユニーク閲覧数です。同じユーザーが 2 回訪問した場合、1 回としてカウントされます。 ### Probability to be the best(最良の確率) \{#probability-to-be-the-best\} 「最良の確率」指標は、A/B テスト内の特定のバリアントが、テストされたすべてのペイウォールやオンボーディングの中で最もパフォーマンスの高いオプションである可能性を数値化したものです。各ペイウォールやオンボーディングの相対的なパフォーマンスを示す数値確率を提供します。1% ~ 100% のパーセンテージで表されます。 ### ARPU(ユーザーあたりの平均収益) \{#arpu-average-revenue-per-user\} オンボーディング A/B テストのみ対象。特定期間における各ユーザーから生み出された平均収益を測定します。総収益をユニークユーザー数で割ることで計算されます。 ### ARPPU(有料ユーザーあたりの平均収益) \{#arppu-average-revenue-per-paying-user\} ARPPU は A/B テストによる有料ユーザーあたりの平均収益(Average Revenue Per Paying User)です。総収益をユニーク有料ユーザー数で割ることで計算されます。例えば、1,000 人の有料ユーザーから $15,000 の収益が発生した場合、ARPPU は $15 となります。 ### ARPAS(アクティブサブスクライバーあたりの平均収益) \{#arpas-average-revenue-per-active-subscriber\} ARPAS は、A/B テストの実施によるアクティブサブスクライバーあたりの平均収益を測定する指標です。総収益をトライアルまたはサブスクリプションを有効化したサブスクライバー数で割ることで計算されます。例えば、総収益が $5,000 でサブスクライバーが 1,000 人の場合、ARPAS は $5 となります。この指標はサブスクライバーあたりの平均収益化ポテンシャルを評価するのに役立ちます。 ### Proceeds(手取り収益) \{#proceeds\} A/B テストの手取り収益指標は、App Store / Play Store の手数料を差し引いた後にアプリオーナーが受け取る実際の USD 金額を、購入とリニューアルから表したものです。A/B テストでテストされたバリエーションに関連する純収益を反映し、アプリの収益に直接貢献します。手取り収益の計算方法については、Adapty の[ドキュメント](analytics-cohorts#revenue-vs-proceeds)をご参照ください。 ### Unique subscribers(ユニークサブスクライバー数) \{#unique-subscribers\} ユニークサブスクライバー数指標は、A/B テストのバリエーションを通じてサブスクリプションを登録またはトライアルを有効化した個別ユーザーの数を表します。サブスクリプションやトライアルの開始回数に関わらず、各サブスクライバーを 1 回のみカウントします。 ### Unique paid subscribers(ユニーク有料サブスクライバー数) \{#unique-paid-subscribers\} ユニーク有料サブスクライバー数指標は、A/B テストのバリエーションを通じて購入を完了し、有料サブスクライバーになったユニークユーザーの数を表します。 ### Refund rate(返金率) \{#refund-rate\} A/B テストの返金率は、テストのバリエーションに関連する返金数を初回購入数(更新は除く)で割ることで計算されます。例えば、返金が 5 件、初回購入が 1,000 件の場合、返金率は 0.5% となります。 ### Unique CR purchases(ユニーク購入コンバージョン率) \{#unique-cr-purchases\} A/B テストのユニーク購入コンバージョン率は、テストのバリエーションに関連する購入数をユニークビュー数で割ることで計算されます。例えば、購入数が 10、ユニークビュー数が 100 の場合、ユニーク購入コンバージョン率は 10% となります。 ### Unique CR trials(ユニークトライアルコンバージョン率) \{#unique-cr-trials\} A/B テストのユニークトライアルコンバージョン率は、テストのバリエーションに関連する開始されたトライアル数をユニークビュー数で割ることで計算されます。例えば、開始されたトライアルが 30、ユニークビュー数が 100 の場合、ユニークトライアルコンバージョン率は 30% となります。 ### Completions & unique completions(完了数とユニーク完了数) \{#completions--unique-completions\} オンボーディング A/B テストのみ対象。完了数は、A/B テストのバリエーションを通じてユーザーがオンボーディングを完了した(最初から最後のスクリーンまで進んだ)回数をカウントします。2 回完了した場合は、**completions(完了数)** が 2 カウントされますが、**unique completion(ユニーク完了数)** は 1 になります。 ### Unique completions rate(ユニーク完了率) \{#unique-completions-rate\} オンボーディング A/B テストのみ対象。ユニーク完了数をユニークビュー数で割った値です。この指標は、A/B テストのバリエーションを通じてユーザーがオンボーディングにどう関わっているかを把握し、無視されていると気づいた場合に改善を行うのに役立ちます。 --- # File: maths-behind-it --- --- title: "A/B テストの背後にある数学" description: "サブスクリプション分析の背後にある数学を理解して、収益インサイトを向上させましょう。" --- A/B テストは、フロー、ペイウォール、またはオンボーディングの2つの異なるバージョンのパフォーマンスを比較するための強力な手法です。最終的な目標は、12か月間のユーザーあたりの平均収益に基づいて、どちらのバージョンがより効果的かを判断することです。しかし、データを収集して意思決定を行うために丸1年待つのは現実的ではありません。そのため、目標指標の代替として2週間のユーザーあたりの収益が使用されており、これは過去のデータ分析に基づいて選択されています。正確で信頼性の高い結果を得るためには、多様なデータタイプを扱える堅牢な統計手法を使用することが重要です。現代のデータ分析で人気のアプローチであるベイズ統計は、A/B テストに柔軟で直感的なフレームワークを提供します。事前知識を取り込み、新しいデータで更新することで、ベイズ手法は不確実性の下でより良い意思決定を可能にします。このドキュメントでは、A/B テスト結果の評価とデータ駆動型の意思決定に向けた貴重なインサイトの提供において、Adapty が採用している数学的分析の包括的なガイドを提供します。 ## 統計分析に対する Adapty のアプローチ \{#adaptys-approach-to-statistical-analysis\} Adapty は、A/B テストのパフォーマンスを評価し、正確で信頼性の高いインサイトを提供するために、包括的な統計分析アプローチを採用しています。私たちの方法論は以下の主要なステップで構成されています: 1. **指標の定義:** A/B テストを成功させるには、分析の具体的な目標や目的に合致する主要指標を特定・定義する必要があります。Adapty は大量のサブスクリプションアプリの過去データを活用し、1年後の平均収益という長期目標に対するプロキシ指標として最適なものを特定しました。それは14日後の ARPU です。 2. **仮説の設定:** A/B テストのために2つの仮説を作成します。帰無仮説(H0)は、コントロールグループ(A)とテストグループ(B)の間に有意な差がないと仮定します。対立仮説(H1)は、2つ以上のグループの間に有意な差があることを示唆します。 3. **分布の選択:** データの特性と観察している指標に基づいて、最適な分布ファミリーを選択します。ここで最も頻繁に選択されるのは対数正規分布(ゼロ値を考慮したもの)です。 4. **ベストである確率の計算:** A/B テストへのベイズアプローチを活用して、テストに参加しているすべてのペイウォールまたはオンボーディングのバリアントに対して、ベストである確率を計算します。この値は以前使用していた p 値と確かに関連していますが、本質的には異なるアプローチであり、より堅牢で理解しやすいものです。 5. **結果の解釈:** 「ベストである確率」は文字通りその意味です。確率が高いほど、特定のオプションがタスクに対して最良の選択である可能性が高くなります。意思決定のしきい値は自分自身で決定する必要があり、具体的な状況の多くの要因に依存すべきですが、一般的な確率の基準は 95% です。 6. **予測区間:** Adapty は各グループのパフォーマンス指標に対する予測区間を計算し、真の母集団パラメータが収まる可能性のある値の範囲を提供します。これにより、推定されたパフォーマンス指標に関連する不確実性を定量化できます。 ## サンプルサイズの決定 \{#sample-size-determination\} 適切なサンプルサイズを決定することは、信頼性が高く決定的な A/B テスト結果を得るために重要です。Adapty は、現在採用しているベイズアプローチにおいても依然として重要となる統計的検出力や期待効果量などの要因を考慮し、適切なサンプルサイズを確保します。現在採用しているベイズアプローチに特有の、必要なサンプルサイズを推定するための手法が、分析の信頼性を担保します。 A/B テストの機能について詳しくは、[A/B テストの作成](ab-tests)と[A/B テストの実行](run_stop_ab_tests)に関するドキュメント、および[A/B テストの指標と結果](results-and-metrics)の理解をご参照ください。 Adapty の A/B テスト向け分析フレームワークはベイズアプローチを採用するようになりましたが、指標の定義、仮説の設定、分布の選択に焦点を当てるという点は変わりません。ただし、p 値を決定する代わりに、事後分布を計算し、各バリアントがベストである確率を算出するようになりました。また、予測区間も算出しています。この改訂されたアプローチは、依然として包括的でさらに堅牢でありながら、より直感的で解釈しやすいインサイトを提供するように設計されています。目標は、A/B テストの堅牢な統計分析に基づいて、企業が戦略を最適化し、パフォーマンスを向上させ、成長を促進できるよう支援することです。 --- # File: autopilot-how-it-works --- --- title: "Growth Autopilot:仕組み" description: "Growth Autopilotの仕組みを理解し、収益向上をお任せください。" --- [Growth Autopilot](autopilot)は、実際のパフォーマンスデータと同じ市場の類似アプリの動向をもとに、どんな実験を行うべきかを提案します。何が効果的かを手探りで探す必要はなく、成果を改善する可能性が高いテストの具体的なレコメンデーションを受け取れます。 この記事では、Autopilotの考え方——どのデータを使うか、どのように機会を評価するか、なぜ特定のレコメンデーションが表示されるか——を透明性を持ってご説明します。Autopilotを成長ワークフローの一部として自信を持って活用していただくことを目的としています。 ## Autopilotが実際に行うこと \{#what-autopilot-actually-does\} Autopilotはアプリとペイウォールの指標を分析し、収益を最も効果的に増加させる実験を見つけます。分析対象は以下のとおりです: - **現在の設定**:価格、トライアル、プロダクト、コンバージョン率 - **市場パターン**:類似アプリのオファー構成と価格帯 - **テスト履歴**:実施済みの実験とその結果 - **成長ポテンシャル**:最も効果が見込まれる変更点 AutopilotはAIを使ってこれらの要素を総合的に評価し、すぐに開始できるA/B テストに変換します。競合他社をリサーチしたり次に何をテストすべきか推測したりする必要なく、すぐに使える計画が手に入ります。 ## Autopilotのデータソース \{#the-data-behind-autopilot\} 各レコメンデーションは、連携して機能する3つの主要データソースをもとに構築されています。 #### アプリ自体のデータ Autopilotは現在のアプリのパフォーマンスを確認します: - ペイウォール全体のコンバージョン指標 - 価格とプロダクト構成 これにより、変更を提案する前のベースラインが確立されます。 :::note あなたのアプリのパフォーマンスデータは、他のアプリへのレコメンデーション生成に使用しません。データのプライバシーは守られます。 ::: #### ペイウォール分析 Autopilotはペイウォールのスクリーンショットを分析し、そのデザインをカテゴリ内のトップパフォーマーが採用している確立されたパターンと比較します。レイアウトの選択、コピー、サブスクリプションの内訳、節約バッジやレビューセクションなどのコンバージョン重視の要素を評価します。 この分析から2種類のレコメンデーションが生成されます: - **ベンチマークに基づくレコメンデーション**:トップパフォーマーとの違いをもとにした提案で、それぞれ具体的な統計データに裏付けられています(例:「教育カテゴリのトップパフォーマーの72%が採用」)。 - **ビジュアル分析レコメンデーション**:スクリーンショットからAIが生成した提案で、コピーの改善、レイアウト変更、その他のデザイン調整が含まれます。 これらのレコメンデーションは、A/B テストとして[実施可能な](autopilot-execute-plan)仮説として[成長計画](autopilot-growth-plan#view-the-growth-plan)に直接反映されます。 #### 競合データ Autopilotは、価格、サブスクリプション構造、カテゴリ内の一般的なパターンといった公開情報を使って、同じ市場の類似アプリと現在の設定を比較します。競合の価格や構造は市場によって異なるため、この比較は国ごとに行われます。競合の価格データは、指標分析で使用される匿名化されたAdaptyネットワークデータとは異なり、App Storeなどのサードパーティおよび公開ソースから取得しています。 これにより、ランダムなアイデアではなく、自分のアプリに近い類似アプリがすでに実績を上げている戦略をテストできます。分析結果では、ベンチマークと競合価格を並べて比較できます。類似アプリが異なる価格や構成でより良い成果を上げているなら、同じアプローチが自分のアプリでも有効なシグナルとなります。 :::tip Autopilotは、現実的に競合できるアプリに基づいて関連する競合他社を自動的に選択します。一般的に、あまりにも先を行くアプリや遅れているアプリを追加するよりも、この提案に従うことをお勧めします。アプリが複数のカテゴリに当てはまる場合は、最も関連性の高い市場セグメントに焦点を当てるようリストを調整することを検討してください。 ::: #### 業界ベンチマーク AutopilotはAdaptyが追跡する20,000のサブスクリプションアプリの匿名化データを活用し、特定の国内のカテゴリ平均との比較を提供します。データはネットワーク全体で集計されており、特定のアプリに紐付けられることはありません。 たとえば、コンバージョンファネルやインストールあたりの収益が、同じカテゴリ・国のアプリの平均と比較されます。これにより、パフォーマンスが平均以下か、平均的か、あるいはすでに平均を上回っているかを把握できます。 #### 地域別市場データ Autopilotは個々の地理的市場を分析し——20,000アプリのAdaptyネットワーク全体のパターンを活用して——地域別の価格調整によってさらなる収益を引き出せる機会を特定します。各国について以下を評価します: - **コンバージョン率**:インストールから有料への転換率がグローバル平均と比較してどうか。高い場合は値上げの余地があることを示す場合があり、低い場合は価格感受性の高さを示す場合があります。 - **価格指数**:その国の[Adapty Pricing Index](https://uploads.adapty.io/adapty_pricing_index.pdf)における位置づけ(住民の購買力を示します)。 これらのレコメンデーションは、成長計画内の[地域別価格の仮説](autopilot-growth-plan#geo-pricing-hypotheses)からA/B テストを作成することで実行できます。 ## Autopilotがレコメンデーションを決定する方法 \{#how-autopilot-decides-what-to-recommend\} Autopilotはペイウォールのコンバージョン改善に向けた提案のプールを生成します。これらの提案は、各変更の影響を確実に測定できるよう、1つずつ順番にテストすることを前提に設計されています。 Autopilotが提案を生成する流れは以下のとおりです: 1. **最大の機会を見つける** Autopilotは価格、プロダクト、ファネルのパフォーマンスを確認し、業界パターンや類似アプリと比較します。分析はUSDだけでなく、主要市場の通貨で行われるため、価格のレコメンデーションはサブスクライバーが実際に支払う金額に合致します。価格の調整、トライアルの追加、オファー構造の変更など、改善の余地が最も大きい部分を探します。 2. **次の実験を選択する** 各仮説は、既存のテスト履歴をもとに生成されます。Autopilotは実施済みの実験、勝者となった実験、まだ探索する価値のある方向性を把握しています。次の提案は、前の実験から得られた知見の上に構築されます(固定されたシーケンスには従いません)。 3. **勝者 vs. チャレンジャーのテストを実施する** 各実験後、勝者が新しいベースラインになります。その結果が成長計画の次のレコメンデーションを形成します——Autopilotは効果があったものを継続し、効果がなかったものを除外し、次のテストを選択します。 4. **実用性を保つ** Autopilotは、既存のプロダクトと設定で実施できるテスト、または新しいプロダクトの作成や価格の調整といった小さな変更で対応できるテストのみを提案します。テストを迅速かつ管理しやすい状態に保つことが目的です。 5. **根拠を明示する** 各レコメンデーションについて、Autopilotはこのテストを実施する価値がある理由を明確に説明する仮説を提供します。現在の指標が競合他社や業界平均とどう比較されるか、機会は何か、改善が期待される主要指標は何かを確認できます。 これにより、実験が繰り返し可能なプロセスとなり、各テストから学びを得ながら、より効果的なペイウォールへと近づいていきます。 ## 各実験後に起こること \{#what-happens-after-each-experiment\} レコメンデーションが尽きることはありません。完了した各テストが、さらなる実験の基盤となります。テストを続ける限り、Autopilotは次に試すべきことを提案し続けます。 基盤となる市場データを最新の状態に保つには、同じプレースメントで分析を再実行してください。再実行のたびに、最新の競合価格、コンバージョンベンチマーク、カテゴリトレンドが取り込まれ、新たに特定された仮説が既存の内容を乱すことなく成長計画に追加されます。既存のAI生成仮説、カスタム仮説、進行中のA/B テストは再実行をまたいで保持されます。 ベースラインを最適化したら、より高度な競合他社との競争を選択することもできます。このような反復的なアプローチにより、アプリが成長し市場が進化するにつれて収益を最大化し続けることができます。 :::tip 試してみる準備はできていますか?[Growth Autopilot](autopilot-analysis)を起動してペイウォールを分析し、A/B テスト付きの成長計画を生成しましょう。複雑なテストをシームレスに開始するには[内蔵ウィザード](autopilot-execute-plan)を使用してください:プロダクトの作成、ペイウォールの複製、セグメントの設定まで順を追ってガイドします。 ::: --- # File: autopilot-analysis --- --- title: "ペイウォールとマーケット分析" description: "アプリに合わせたデータドリブンな成長プランを生成します。" --- この記事の手順に従って、Growth Autopilot 分析を実行し、成長プランを生成してください。 対象プレースメントの成長プランをすでに生成している場合、この分析では新しい仮説を追加して選択できるようになります。 :::tip 開始前に[分析の要件](autopilot#prerequisites)を満たしているか確認してください。 ::: ## ペイウォール分析 \{#paywall-analysis\} ### 分析するペイウォールを選択する \{#select-a-paywall-for-analysis\} 1. **Growth Autopilot** ページを開き、[Get Growth plan](https://app.adapty.io/ab-tests/analysis/start) ボタンをクリックします。 2. **Paywall Diagnostic** ページで、ドロップダウンから **Placement** と **Paywall** を選択します。Adapty は収益が最も高いプレースメントとそのトップペイウォールを自動的に選択します。別のペイウォールを分析するには、先にプレースメントを変更してください。 3. スクリーンショットをアップロードします。Growth Autopilot はペイウォールのデザインとコンテンツを分析するためにスクリーンショットが必要です。 4. ペイウォールのアクティブなプロダクトを確認します。右側のプロダクトカードには、各プロダクトのサブスクリプション期間、価格、トライアル期間が表示されます。 5. **Confirm & Analyze** をクリックして続行します。Adapty がペイウォールを分析し、診断レポートを表示します。 ### ペイウォール分析レポート \{#paywall-analysis-report\} ペイウォールを選択してスクリーンショットをアップロードすると、Adapty はペイウォールを確立されたデザインパターンと照らし合わせて分析し、優れている点と改善できる点を明示します。 #### うまくいっている点 \{#whats-working-well\} このセクションでは、コンバージョンを最大化する確立されたパターンの活用状況をハイライトします。例えば、目立つ節約バッジ、目立つユーザーレビューセクション、わかりやすいサブスクリプションの内訳などです。 #### ペイウォールで修正すべき点 \{#what-to-fix-on-your-paywall\} Adapty の推奨事項は次の 2 つのカテゴリーに分類されます。 - **ベンチマーク推奨事項**: 同カテゴリーのトップアプリに基づくデータドリブンな提案。各推奨事項にはベンチマーク統計(例:「教育系トップアプリの 72% が使用」)と変更内容の説明が含まれます。 - **ビジュアル分析推奨事項**: ペイウォールのスクリーンショットに基づく AI 生成の提案。コピーの改善、レイアウトの変更などが含まれます。 :::tip [成長プラン](autopilot-growth-plan#view-the-growth-plan)には、ベンチマーク推奨事項に基づく仮説が含まれます。ビジュアル分析の提案は手動でプランに追加できます。 ::: **Get Market Insights** をクリックして続行します。 ## マーケットと競合分析 \{#market-and-competitor-analysis\} :::note マーケットと競合分析を行うには、先に[ペイウォール分析](#paywall-analysis)を完了する必要があります。 ::: Market Insights 分析では、アプリの価格設定とコンバージョン指標を競合他社や業界平均と比較します。比較は国ごとに行われます。ベンチマークとして、Adapty は同サブカテゴリー・同国の App Store アプリのデータを集計・分析します。このデータは他では公開されていません。 ### 競合他社を選択する \{#select-competitors\} 比較対象として最大 5 社の競合他社を選択します。 Adapty が自動的に 5 社を選び、さらに 5 社を提案します。App Store のリンクを使って手動でアプリを追加することもできます。より精度の高い結果を得るには、自社より MRR が高いアプリを選択してください。 **Generate report** をクリックしてリストを確定し、分析が完了するまで待ちます。 ### 国を選択する \{#select-a-country\} Country ドロップダウンを使って、詳細分析の対象となるトップ国を 1 つ選択します。 ### 収益の地域分布 \{#revenue-distribution\} この収益分布チャートは、パーセンテージの内訳とともに、収益がどの国から得られているかを示します。上位 5 か国がハイライトされ、以降の分析はそれらを中心に行われます。 ### 競合他社の価格設定 \{#competitor-pricing\} 競合他社の価格比較テーブルでは、[選択した国](#select-a-country)における競合他社のサブスクリプション価格とペイウォールの価格を比較します。サブスクリプション期間ごとに列が分かれています。 ### コンバージョンファネル \{#conversion-funnel\} このチャートは、Views-to-Trial、Trial-to-Paid、Views-to-Paid のコンバージョン率を、類似アプリの平均値と並べて表示します。 ### 期間別収益分布 \{#revenue-distribution-by-duration\} このチャートは、業界平均と比較して、どのサブスクリプション期間が収益に最も貢献しているかを示します。特定の期間に収益が偏っている場合、価格戦略の最適化の機会がある可能性があります。 ### アクティベーション ARPU \{#activation-arpu\} **Activation ARPU: your app vs. category** チャートは、アプリの新規インストールあたりの平均収益をカテゴリー平均と比較します。 [コンバージョンファネル](#conversion-funnel)と組み合わせて活用してください: - コンバージョンは何人のユーザーが支払いをしているかを示します。 - Activation ARPU はユーザーあたりの平均収益を示します。 コンバージョン率が高いのに Activation ARPU が低い場合は、オファーの価格設定が低すぎる可能性があります。 この指標は**コホートベース**です。Adapty は過去 90 日間にアプリをインストールしたユーザーを対象に、彼らが生み出した収益をユーザー数で割って算出します。 #### 他の指標との比較 \{#comparison-to-other-metrics\} Activation ARPU は、ダッシュボードの他の場所で表示される ARPU とは一致しません。各指標は異なる内容を測定しています。 - **[ARPU 分析チャート](arpu)**: 古いコホートからの更新も含まれるため、Activation ARPU より数倍高い値になります。 - **[収益チャート](revenue)(Period フィルターを「Activation」に設定)**: 各ユーザーの初回支払いのみをカウントします。90 日間のウィンドウ内でコホートが行った更新はカウントされません。 - **[コホート収益](analytics-cohorts)(90 日間)**: 最も近い指標であり、参考値として使用してください。 ## 次のステップ \{#next-steps\} [成長プランの実行](autopilot-execute-plan)を読んで、分析結果に基づいた A/B テストの実施方法を確認してください。 分析レポートはいつでも成長プランから確認できます。**Analysis Results** タブに切り替えてください。 --- # File: autopilot-growth-plan --- --- title: "グロースプランの管理" description: "カスタム仮説の追加、アーカイブ、グロースプランの更新方法を説明します。" --- [分析](autopilot-analysis)が完了すると、Adapty はグロースプランを表示します。グロースプランとは、**実行可能な改善仮説**のリストです。各アイテムは、新しい価格設定またはデザイン改善を提案します。 仮説を開いて [A/B テストで試す](autopilot-execute-plan)ことができます。 各プレースメントには独自のグロースプランがあります。市場状況が変化した場合は、分析を再実行して提案を更新できます。過去の実行結果はバージョン履歴に保存されます。 ## 仮説 \{#hypotheses\} グロースプランの上部にあるタブを切り替えて、タイプ別に仮説をフィルタリングできます。 - **Top priority** には、注目すべき最も影響力の高い仮説が含まれます。該当する仮説がない場合、このタブは非表示になります。 - **All** にはアクティブなプランのすべての仮説が表示されます。 - **Pricing** 仮説は、新しい価格設定やトライアル設定を探ります。それぞれはペイウォール診断または市場インサイトレポートからの具体的な推奨事項に基づいています。 - **Visual** 仮説はデザイン改善の提案です。コピー、レイアウト、その他のビジュアル要素の変更が含まれる場合があります。 - [**Geo-pricing**](#geo-pricing-hypotheses) 仮説は、国ごとの価格調整をテストします。 - [**Archived**](#archive-a-hypothesis) 仮説は、アクティブなプランから削除した提案です。いつでも復元できます。 [独自の仮説を追加](#add-your-own-hypothesis)したり、テストしたくない仮説を[アーカイブ](#archive-a-hypothesis)したりすることもできます。 これらの仮説は、任意の順序で1つずつテストします。ジオプライシングテストは例外で、オーディエンスが重複しないため、並行して実行できます。 ### ジオプライシング仮説 \{#geo-pricing-hypotheses\} :::important 買い切り購入は、地域別価格最適化の対象外です。 ::: **Geo-pricing** タブを開くと、ジオプライシングの推奨事項の一覧が表示されます。各推奨事項は1つの国を対象とし、1つの価格変更を行い、個別の A/B テストとして実行されます。 Adapty は価格調整が必要な国を検出し、[Adapty Pricing Index](https://uploads.adapty.io/adapty_pricing_index.pdf) で検証されたデータドリブンな推奨事項を提供します。 <br /> #### Adapty がジオプライシングの提案を行う仕組み \{#how-adapty-makes-geo-pricing-suggestions\} - 価格推奨事項は App Store のデータに基づいています。生成された A/B テストは App Store と Google Play の両方で実行できます。 - 価格変更の割合は、すべてのサブスクリプション期間で同じです。 - すべての価格は最も近い App Store 価格ティアに丸められます。 - Adapty がその国のトランザクションデータを持っている場合、価格は現地通貨(EUR や GBP など)で表示されます。現地データがない場合は、USD で表示されます。 ### 仮説のステータスバッジ \{#hypothesis-status-badges\} 1. **Lightning bolt** — 最優先の提案を示します。 2. **Product sync status** — A/B テストの起動に製品アクションが必要な場合に表示されます。 - **Draft** — プロダクトの設定が未完了(Adapty 側) - **Action required** — プロダクトの設定が未完了(ストア側) - **Pending...** — Adapty がストアによるレビューまたは初期同期の完了を待っています。 - **Approved** — プロダクトはストアによって承認され、テスト準備が完了しています。 - **Rejected** — ストアがプロダクトを却下しました。 - **Not connected** — プロダクトがまだストアに連携されていません。 3. **A/B test status** — A/B テストを起動した際に表示されます。 - **Draft test** — テストは下書き状態で、まだ実行されていません。 - **Running** — テストは稼働中です。 - **Completed** — テストが終了しました。 - **Archived test** — テストは結論が出ないままアーカイブされました。 ## AI が生成する新しい仮説を取得する \{#get-new-ai-generated-hypotheses\} 各テスト後、Adapty は結果に基づいて仮説を自動的に更新します。 最新の競合他社の価格情報、コンバージョンベンチマーク、カテゴリトレンドを取り込むには、グロースプランのヘッダーにある **Update** Refresh をクリックするか、Autopilot ホームページの **Update Analysis** をクリックします。プロンプトが表示されたら **Get New Ideas** をクリックします。 Adapty は分析ウィザードを開き、プレースメントが事前に選択されています。ペイウォール分析と競合他社リサーチを繰り返すと、Adapty が結果から新しい仮説を特定します。 追加したいものを選択するか、**Add All To Plan** Plus をクリックしてすべてを受け入れます。新しく追加された仮説はリストの先頭に表示されます。既存の AI 生成仮説、カスタム仮説、進行中の A/B テストには影響しません。 更新を完了する前に終了した場合は、**resume it** で続きから再開するか、**discard it** で最初からやり直すことができます。 ## 独自の仮説を追加する \{#add-your-own-hypothesis\} **Add Hypothesis** Plus をクリックして、独自の価格設定またはビジュアルの提案を作成します。 フォームに入力します:タイトル、説明、仮説タイプ(**Monetization** または **Visual**)。 - ドロップダウンメニューから改善したい指標を選択します。 - Monetization 仮説は、テスト用プロダクトの選択も必要です。 ## 仮説をアーカイブする \{#archive-a-hypothesis\} 仮説をアーカイブするには、Close ボタンをクリックし、**Skip** をクリックして確認します。理由を入力することもできます — Adapty が将来の提案を改善するのに役立ちます。 仮説は **Archived** タブに移動します。 アーカイブされた仮説をアクティブなプランに戻すには、カード上の **Restore** をクリックします。 ## 過去の仮説を見直して再利用する \{#revisit-and-reuse-old-hypotheses\} 過去の分析で生成された提案を参照するには、グロースプランのヘッダーの **Clock** Clock をクリックします。**Version history** モーダルには、プレースメントの過去の実行履歴(日付、ペイウォール、その時点で承認した仮説の数)がすべて表示されます。 過去の実行をクリックすると、生成された仮説を確認できます。**Add to Plan** Plus を使えば、任意の仮説をアクティブなプランに追加できます — 最初に選ばなかった提案を見直すのに便利です。 --- # File: autopilot-execute-plan --- --- title: "グロースプランを実行する" description: "グロースプランの仮説からA/Bテストを起動します。" --- テストはどの順番で実行してもかまいませんが、**同時に実行できるのは1つだけ**です。ただし、ジオプライシングテストのオーディエンスは重複しないため、それらは並行して実行できます。テストが終わったら、勝利した戦略を次のラウンドに進めてください。ラウンドを重ねるごとに、アプリにとってより効率的な設定に絞り込まれていきます。 Adaptyの試算では、Autopilotのテストを一通り実施することで、収益が**最大80%向上する**可能性があります。 :::important 各提案には、A/Bテストの最短実施期間が含まれています。次のステージに進む前に、最も正確なデータを得るためにこの推奨事項に従ってください。A/Bテストは手動で停止する必要があります。 ::: 仮説を開いて **Set Up & Run Test** をクリックすると、A/Bテスト作成ウィザードが起動します。 ## ステップ1:仮説を確認する \{#step-1-view-the-hypothesis\} 最初のステップでは、仮説の概要が表示されます。提案された変更内容とその根拠が説明されています。「Set up & Run Test」をクリックして次のステップに進んでください。 {/* TODO: REPLACE SCREENSHOT */} ## ステップ2:新しいプロダクトを作成する \{#step-2-create-new-products\} テストに価格変更が含まれる場合、2番目のステップでテストバリアント用の新しいプロダクトを作成できます。ビジュアル仮説の場合、このステップはスキップされます。 * **Create a new product and push to stores** をクリックすると、新しいプロダクトをゼロから作成できます。 * **Connect an existing product** をクリックすると、アプリストアに既に存在するプロダクトを接続できます。 ## ステップ3:セグメントとペイウォールを設定する \{#step-3-set-up-segment-and-paywall\} 3番目のステップでは、ペイウォールのテストバリアントを設定できます。Adaptyはペイウォールを複製して、提案された変更を適用するよう促します。 **ジオプライシング仮説**の場合、ウィザードは既存のジオフェンスセグメントを選択するか、新しいセグメントを作成するよう促します。 新しいペイウォールの準備が整い、セグメントの設定が完了したら **Next** をクリックしてください。 ## ステップ4:確認して起動する \{#step-4-review--launch\} 最後のステップでは、これから実施するテストのサマリーが表示されます。以下の内容が含まれます: - **バリアントA vs バリアントB** の主要指標 — ペイウォール名、プロダクトの選択、トライアル期間、価格。 - テストの **Duration**(期間)、**Traffic**(分割)、**Subscribers**(最小サンプルサイズ)。 - テストの成否を示すシグナルを説明する **How to interpret results** セクション。 設定内容を確認し、**Launch Test** をクリックしてA/Bテストを開始します。 --- # File: how-adapty-analytics-works --- --- title: "Adapty アナリティクスの仕組み" description: "Adapty アナリティクスがサブスクリプションのパフォーマンスを効率的に追跡する仕組みについて説明します。" --- この記事では、Adapty アナリティクスの仕組みについて説明します。表示されるデータの種類、データの取得元、およびデータの処理方法を紹介します。また、Adapty アナリティクスを他と差別化する設計上の判断と、それがどのようにあなたのメリットになるかについても解説します。 ## Adapty アナリティクスとストアのアナリティクス \{#adapty-analytics-vs-store-analytics\} - **データの多様性**: ストアは自社のデータしか表示できず、アプリ内のユーザー行動にはアクセスできません。 Adapty は複数のストアのデータを統合でき、マーケティングプラットフォームや広告ネットワークなどの追加ソースも利用できます。Adapty SDK はペイウォールやオンボーディングとのユーザーのやり取りを追跡します。 - **更新頻度**: アプリストアは通常、1 日 1 回データを更新するため、リアルタイムの意思決定が難しい場合があります。 Adapty は[ほぼリアルタイム](#data-processing)のアナリティクスを提供します。 - **高度な指標**: アプリストアはダウンロード数、収益、リテンション率などの基本的な指標を表示します。 Adapty はさらに、定期収益やユーザーあたりの平均収益などの高度な指標も算出します。専用のセクションでは、ユーザーのチャーン、課金失敗などのサブスクリプションの問題を分析します。完全なリストは[指標比較表](metric-comparison-table)の記事をご覧ください。 - **予測**: Adapty は高度な機械学習アルゴリズムを使用して[将来の LTV と収益を予測](predicted-ltv-and-revenue)します。 ## データとその取得元 \{#data-and-its-sources\} Adapty アナリティクスは以下のデータを[チャートやグラフ](analytics)に処理します: - [サブスクリプションイベント](events)(ユーザーのライフサイクル全体で発生するもの)— トライアル開始、購入、更新、キャンセル、課金失敗、返金。Adapty はこれらを[アナリティクスチャート](analytics)に集約し、リアルタイムで[Webhook](webhook)、[イベントフィード](event-feed)、[イベントベースの連携](analytics-integration)に転送します。 - [トランザクションデータ](revenue) — 収益、返金、購入者の国など。 - インストール数や[ペイウォールとのインタラクション](paywalls)などの**アプリケーションデータ**。 - [トランザクションのアトリビューションデータ](attribution-integration):トラフィックソースや広告キャンペーン。 このデータは以下のソースから取得されます: - <InlineTooltip tooltip="Adapty SDK">[iOS](ios-sdk-overview)、[Android](android-sdk-overview)、[React Native](react-native-sdk-overview)、[Flutter](flutter-sdk-overview)、[Unity](unity-sdk-overview)、[Kotlin Multiplatform](kmp-sdk-overview)、[Capacitor](capacitor-sdk-overview) </InlineTooltip> はアプリ内からユーザー行動データを報告します。Adapty が購入フローの管理を担っている場合、SDK は購入イベントに関する直接情報を共有します。[オブザーバーモード](observer-vs-full-mode)を使用している場合、SDK は手動で設定した[イベントレポート](report-transactions-observer-mode)を受信します。 - ストアはサーバー間通信を使用して、トランザクション(トライアル、サブスクリプションの更新、キャンセルなど)を Adapty に通知します。 - サードパーティの[アトリビューションサービス](attribution-integration)(Appsflyer、Adjust、Branch など)がトラフィックソースや広告キャンペーンのデータを共有します。[Adapty User Acquisition](adapty-user-acquisition) を設定すると、Adapty がこのステップを省略して独自に広告キャンペーンデータを処理できます。 - ユーザーは Adapty が分析・表示するために[過去のトランザクションデータを手動でインポート](importing-historical-data-to-adapty)できます。 いずれかのソースに問題が発生すると、アナリティクスデータ全体の品質に影響する可能性があります。詳細については[トラブルシューティング](#troubleshooting)セクションをご覧ください。 ## サードパーティ連携 \{#third-party-integrations\} [Adapty User Acquisition](adapty-user-acquisition) を有効にすると、広告キャンペーンデータで Adapty のアナリティクス機能を拡張できます。広告キャンペーンの費用とユーザー行動の相関関係を発見するのに役立ちます。 同様に、アナリティクスデータをサードパーティプラットフォームや[プライベートサーバー](webhook)に[エクスポート](analytics-integration)して、別のプラットフォームで Adapty のデータを分析することもできます。 ## データ処理 \{#data-processing\} Adapty はほぼリアルタイムのアナリティクスを提供しており、主要な指標の変化に素早く対応できます。 - **アナリティクスチャート**: トランザクション発生から **15〜30 分の遅延**でデータが表示されます。この時間は、トランザクションの検証、手数料と税金の適用、データの集計に必要です。 - **[イベントフィード](event-feed)**: ストアがイベントを配信するとリアルタイムで更新されます。 - **[Webhook](webhook) とイベントベースの連携**(AppsFlyer、Branch など): Adapty はイベントが発生すると同時に転送します — 15〜30 分のアナリティクス遅延は適用されません。受信サービス側で独自の処理時間が発生する場合があります。 各サーフェスにはそれぞれのタイミングがあります。同じイベントがチャート、イベントフィード、連携先で若干異なるタイミングで表示されることがあります。これらの間に小さなズレが生じるのは想定内の動作です。 ## 手数料と税金 \{#commissions-and-taxes\} 収益関連のチャートを表示する際、**Gross revenue(総収益)**、**Revenue after commissions(手数料控除後の収益)**、**Revenue after commissions and taxes(手数料・税金控除後の収益)**から選択できます。 ### 手数料 \{#commissions\} ストアは各トランザクションから手数料を差し引きます。組織が手数料減額プログラムに登録している場合は、Adapty の設定を変更して手数料率の計算を修正してください: * [App Store Small Business Program](app-store-small-business-program) * Google の[手数料減額プログラム](google-reduced-service-fee) ストアは、以下の要因によってトランザクション手数料が減額されるかどうかを自動的に報告します: * [1 年以上継続した App Store サブスクリプションの更新](https://developer.apple.com/app-store/subscriptions/) — 15% の手数料 * 国別レート(例:[日本で配信される App Store アプリの 21%](https://developer.apple.com/support/app-distribution-in-japan/#business-terms)) ### 税金 \{#taxes\} **Adapty は税金を計算しません。** Apple と Google が各トランザクションに適用される税率を決定し、Adapty に報告します。Adapty はその値をそのまま表示します。 特定のトランザクションに表示される税率は以下の要素によって決まります: - **購入者の請求先国**と現地の税率。 - **ストアの税金処理ルール**。一部の国・地域ではストアが開発者に代わって税金を徴収・納付します。その他の国・地域では開発者が責任を負います。 - App Store トランザクションの場合、アプリやアプリ内課金に割り当てられた**税カテゴリ**(書籍、ニュース、動画など)— カテゴリによって現地ルールに基づく税率が異なります。 税率は購入者の国の組み合わせ、ストアの処理ルール、(App Store の場合)割り当てられた税カテゴリによって、アプリ間だけでなく同一アプリ内のトランザクション間でも大きく異なる場合があります。 公式ルールについては、ストアの公式ドキュメントを参照してください: - [App Store: 税金について](https://developer.apple.com/help/app-store-connect/making-payments-to-apple/understanding-taxes/) - [Google Play: 税率と VAT](https://support.google.com/googleplay/android-developer/answer/138000) ## トラブルシューティング \{#troubleshooting\} :::link メイン記事:[データの不一致とトラブルシューティング](discrepancies-and-troubleshooting) ::: * 設定が誤っているデータソースや欠落しているデータソースは、アナリティクスシステム全体に悪影響を与える可能性があります。データに問題が発生した場合は、ストアおよびサードパーティプラットフォームとの連携が設定されており、有効になっていることを確認してください。 * Adapty のチャートを他のアナリティクスプラットフォームと比較すると、差異に気づく場合があります。これはデータ処理の違いから生じる想定内の動作です。データの不一致の一般的な原因については、[データ不一致ガイド](discrepancies-and-troubleshooting)の記事をお読みください。 --- # File: metric-comparison-table --- --- title: "指標の比較" description: "Adapty アナリティクス指標のリファレンステーブル(カテゴリ別)。" --- これは Adapty アナリティクスで利用できる指標の概要です。各指標が何を測定しているか、また関連する指標との違いを把握するためにご活用ください。 Adapty がアナリティクスデータをどのように処理するかについての詳細な説明は、[Adapty アナリティクスの仕組み](how-adapty-analytics-works)を参照してください。 :::note この記事では [Adapty ユーザー獲得](adapty-user-acquisition)の指標は扱いません。広告キャンペーンの指標(Spend、CPI、ROAS、CTR など)については、[UA アナリティクス](ua-analytics)を参照してください。 ::: ## グローバル指標 \{#global-metrics\} グローバル指標は、すべてのプレースメントとペイウォールにわたるアプリ全体のパフォーマンスを追跡します。 ### 収益 \{#revenue\} これらの指標は、アプリがどれだけの収益を生み出しているか、またその収益源を測定します。 | 指標 | 説明 | 主な違い | |--------|-------------|----------------| | [Revenue](revenue) | サブスクリプションおよび買い切り購入からの総収益(返金控除後) | 実際に発生した収益。[チャートのコントロール](controls-filters-grouping-compare-proceeds)に応じて、グロス収益、手数料控除後収益、または税金・手数料控除後収益で表示可能 | | [MRR](mrr) | アクティブなサブスクリプションからの月次経常収益 | アプリの予測可能な月次収益。買い切り購入や非継続サブスクリプションは除外 | | [ARR](arr) | アクティブなサブスクリプションからの年次経常収益 | MRR と同様の計算方法だが年単位。年間収益の予測に有用 | | [ARPU](arpu) | ユーザーあたりの平均収益 | 収益を全ユーザー数(有料・無料含む)で割った値。ユーザー1人あたりの平均収益を示す | | [ARPPU](arppu) | 有料ユーザーあたりの平均収益 | 選択した期間中に購入を行ったユーザー(返金済みトランザクションを含む)のみを対象。常に ARPU より高くなる | | [LTV(ライフタイムバリュー)](ltv) | コホート内の有料顧客からの収益を有料顧客数で割った値 | 時間経過に伴う有料顧客1人あたりの実現価値。ARPPU(単一期間)と異なり、顧客関係全体にわたる総収益を示す。更新回数または経過日数で表示可能 | | [予測 LTV](predicted-ltv-and-revenue) | コホート内のユーザーあたりの推定ライフタイムバリュー | 将来予測。実現済み LTV と異なり、過去のコホートリテンションパターンから将来価値を予測。3・6・9・12・18・24 ヶ月で確認可能 | | [予測収益](predicted-ltv-and-revenue) | コホートが生み出すと推定される総収益 | 将来予測。実現済み Revenue と異なり、選択した期間にコホートが生み出す総額を予測。毎日更新 | | [Non-subscriptions](non-subscriptions) | アプリ内課金の件数:消耗型アイテム、非消耗型アイテム、非自動更新サブスクリプション | 自動更新サブスクリプションを除外 | | [Refund events](refund-events) | 返金された購入またはサブスクリプションの件数 | 元の購入日ではなく返金日に帰属 | | [Refund money](refund-money) | 選択した期間中の返金総額 | 返金の財務的影響。ストア手数料控除前に計算。Refund events(件数)と異なり、金額を示す | ### サブスクライバーとコンバージョン \{#subscribers-and-conversion\} これらの指標は、ユーザーがアプリに流入し、ファネルを通過する様子を追跡します。 | 指標 | 説明 | 主な違い | |--------|-------------|----------------| | [Installs](installs) | 期間中のアプリインストール数 | [インストールの定義](general#4-installs-definition-for-analytics)に応じて以下のいずれかをカウント:<br /> • デバイスインストール数(アプリを再インストールしたユーザーは再カウント)<br /> • ユニークユーザー数(`customer_user_id` を設定したユーザーのみカウント。匿名ユーザーは完全に除外 — 識別済みユーザーがいない場合はカウント 0) | | [New trials](new-trials) | 期間中に開始されたトライアル数 | チャートを確認した時点でトライアルが期限切れや有料転換済みであっても、すべてのトライアル開始をカウント | | [Active trials](active-trials) | まだ期限切れになっていないトライアルの数 | 期間終了時点でアクティブなトライアルのみカウント | | [New subscriptions](reactivated-subscriptions) | 期間中に初めて有効化されたサブスクリプション(トライアルなしの初回購入とトライアルから有料への転換の両方を含む) | 更新や再アクティベーションは除外。トライアル転換が `trial_converted` を発火するのに対し、トライアルなしの初回購入のみをカウントするインテグレーションイベント `subscription_started` とは異なる | | [Active subscriptions](active-subscriptions) | まだ期限切れになっていない有料サブスクリプションの数 | トライアルと更新キャンセル済みのサブスクリプションを除外 | | [Install to trial](analytics-conversion#install---trial) | トライアルを開始したインストーラーの割合 | 分母にはペイウォール閲覧者だけでなくすべてのインストーラーが含まれるため、Paywall view to trial より低くなる場合がある。アプリがペイウォールの表示を記録しない場合、2つの指標が乖離することもある。これは `logShowFlow`(iOS SDK v4+)/ `logShowPaywall` を呼び出さないカスタムペイウォールや、[プロモートされたアプリ内課金](https://developer.apple.com/documentation/storekit/supporting-promoted-in-app-purchases-in-your-app)からトライアルを開始した場合に発生する | | [Paywall view to trial](analytics-conversion#paywall-view---trial) | ペイウォールを閲覧してトライアルを開始したユーザーの割合 | ペイウォールを閲覧したユーザーのみをカウントするため、Install to trial より高い場合がある | | [Trial to paid](analytics-conversion#trial---paid) | サブスクリプションを購入したトライアルユーザーの割合 | トライアルの質とコンバージョン効率を測定。Install to paid と異なり、トライアルを完了したユーザーのみに焦点を当てる | | [Install to paid](analytics-conversion#install---paid) | 初回サブスクリプションを購入したインストーラーの割合 | ペイウォール閲覧者だけでなくすべてのインストーラーをカウント。Paywall view to paid より低くなる場合がある。直接購入とトライアルから有料への転換の両方を含む | | [Paywall view to paid](analytics-conversion#paywall-view---paid) | 最終的にサブスクリプションを購入したペイウォール閲覧者の割合 | ペイウォールを閲覧したユーザーのみをカウントするため、Install to paid より高くなる場合がある。先にトライアルを完了したユーザーも含む | ### リテンションとサブスクリプションの更新 \{#retention-and-subscription-renewal\} これらの指標は、アプリが有料サブスクライバーをどれだけ長く維持できているかを追跡します。 | 指標 | 説明 | 主な違い | |--------|-------------|----------------| | [Retention](analytics-retention) | 各請求期間(1回目の更新、2回目の更新など)後に残っているオリジナルサブスクライバーの割合 | 初回支払いからサブスクライバーを追跡。以下の期間対期間の指標と異なり、常にオリジナルグループと比較するため、全体像を一目で把握できる | | [Paid to 2nd period](analytics-conversion#paid---2nd-period) | 2回目の期間に更新した初回サブスクライバーの割合 | 2つの特定の隣接期間間の遷移を測定。Retention と異なり、最も重要な更新である最初の更新に焦点を当てる | | [2nd to 3rd period](analytics-conversion#2nd-period---3rd-period) | 2回目から3回目の期間に更新した割合 | 初回更新後の初期リテンション安定性を示す | | [3rd to 4th period](analytics-conversion#3rd-period---4th-period) | 3回目から4回目の期間に更新した割合 | 中期リテンション指標 | | [4th to 5th period](analytics-conversion#4th-period---5th-period) | 4回目から5回目の期間に更新した割合 | 長期ロイヤルティ指標 | | [6 Months+](analytics-conversion#6-months-) | 6ヶ月以上サブスクリプションを継続している初回サブスクライバーの割合 | 更新回数ではなくカレンダー時間で測定。年間サブスクライバーは更新なしでも6ヶ月時点でリテンション済みとカウント | | [1 Year+](analytics-conversion#1-year-) | 12ヶ月以上サブスクリプションを継続している初回サブスクライバーの割合 | 年次リテンションのマイルストーン | | [2 Years+](analytics-conversion#2-years-) | 24ヶ月以上サブスクリプションを継続している初回サブスクライバーの割合 | 長期リテンションのマイルストーン | ### チャーン \{#churn\} これらの指標は、アプリが失ったサブスクライバーとトライアルユーザーの数を測定します。 | 指標 | 説明 | 主な違い | |--------|-------------|----------------| | [Trials renewal cancelled](trials-renewal-cancelled) | ユーザーが自動更新を無効化したトライアル数 | ユーザーはトライアルが終了するまでアクセスを維持するが、自動的に有料に転換されない。Subscriptions renewal cancelled と異なり、まだ支払いをしていないトライアルユーザーに適用される | | [Expired (churned) trials](expired-churned-trials) | 期限切れになったトライアル(ユーザーがプレミアム機能へのアクセスを失った) | ユーザーはすでにアクセスを失っている。ユーザーが前の期間に更新をキャンセルした場合でも、失効日に帰属。理由(任意 vs. 請求)でグループ化可能 | | [Subscriptions renewal cancelled](cancelled-subscriptions) | ユーザーが自動更新を無効化したサブスクリプション数 | ユーザーは期間終了までアクセスを維持。実際のチャーンではなくチャーンリスクを示す — 期間終了前にユーザーが自動更新を再有効化する場合がある | | [Churned (expired) subscriptions](churned-expired-subscriptions) | 期限切れになったサブスクリプション(ユーザーがプレミアム機能へのアクセスを失った) | 実際のチャーン。ユーザーはすでにアクセスを失っている。ユーザーが前の期間に更新をキャンセルした場合でも、失効日に帰属。理由(任意 vs. 請求)でグループ化可能 | ### 請求の問題と収益の回復 \{#billing-issues-and-revenue-recovery\} これらの指標は、請求の問題によって失われた収益をどれだけ効果的に回復できているかを追跡します。 | 指標 | 説明 | 主な違い | |--------|-------------|----------------| | [Grace period](grace-period) | 請求失敗によりグレース期間に入ったサブスクリプション数 | グレース期間を超えてアクセスを失ったユーザーも含む | | [Grace period to paid](analytics-conversion#grace-period---paid) | グレース期間終了前に更新したグレース期間ユーザーの割合 | 割合(%)。「グレース期間ユーザーのうち何割が回復したか?」に答える | | [Grace period converted](grace-period-converted) | 正常に更新されたグレース期間サブスクリプションの絶対数 | Grace period to paid と同じイベントだが、割合ではなく件数で表示 | | [Grace period converted revenue](grace-period-converted-revenue) | グレース期間での回復による収益 | グレース期間機能の財務的影響 | | [Billing issue](billing-issue) | 請求の問題状態に入ったサブスクリプション数 | グレース期間終了後に開始。Grace period と異なり、すでにプレミアムアクセスを失ったユーザーのみをカウント | | [Billing issue to paid](analytics-conversion#billing-issue---paid) | 請求サイクル終了前に更新した請求の問題ユーザーの割合 | 割合(%)。「請求の問題ユーザーのうち何割が回復したか?」に答える | | [Billing issue converted](billing-issue-converted) | 正常に更新された請求の問題サブスクリプションの絶対数 | 正常に更新された請求の問題サブスクリプションの件数。Billing issue to paid と同じイベントだが、割合ではなく件数で表示 | | [Billing issue converted revenue](billing-issue-converted-revenue) | 請求の問題からの回復による収益 | 請求の問題回復の財務的影響 | ## ペイウォール・プレースメント・オンボーディング指標 \{#paywall-placement-and-onboarding-metrics\} これらの指標は、個々の[ペイウォール](paywall-metrics)、[プレースメント](placement-metrics)、およびオンボーディングに対して計算されます。アプリ全体ではなく、特定のペイウォールやプレースメントのパフォーマンスを測定します。**関連するグローバル指標**列には、グローバルアナリティクスセクションの対応する指標を示しています。 | 指標 | 説明 | 主な違い | 関連するグローバル指標 | |--------|-------------|----------------|---------------| | [Proceeds](paywall-metrics#proceeds) | 個々のプレースメントの税金・手数料控除後収益 | 税金・手数料控除後の [Revenue](revenue) に相当 | [Revenue](revenue) | | [ARPPU](paywall-metrics#arppu) | このペイウォールまたはプレースメントの有料ユーザーあたりの平均収益 | グローバル ARPPU と同じ計算方法だが、単一のペイウォールまたはプレースメントにスコープされる | [ARPPU](arppu) | | [ARPAS](paywall-metrics#arpas) | アクティブサブスクライバー数(トライアルおよび有料)で割った収益 | トライアルユーザーをカウント。ARPPU と異なり、サブスクライバーベース全体の収益ポテンシャルを反映 | — | | [Views](paywall-metrics#views) | ペイウォールまたはプレースメントが表示された合計回数 | すべての表示をカウント。同じユーザーが同じペイウォールを2回閲覧した場合は2ビューとカウント | — | | [Unique views](paywall-metrics#unique-views) | ペイウォールまたはプレースメントを閲覧したユニークユーザー数 | 閲覧回数に関わらず各ユーザーを1回カウント。Views と異なり、エンゲージメント頻度ではなくリーチを測定 | — | | [CR to purchases](paywall-metrics#cr-to-purchases) | 購入数を総ビュー数で割った値 | 分母に総ビュー数(同一ユーザーの繰り返し閲覧を含む)を使用 | [Paywall view to paid](analytics-conversion#paywall-view---paid) | | [Unique CR to purchases](paywall-metrics#unique-conversion-rate-cr-to-purchases) | 購入数をユニークビュー数で割った値 | 分母にユニークビュー数を使用。繰り返し閲覧者が1回カウントされるため、非ユニーク CR より高い割合になる | [Paywall view to paid](analytics-conversion#paywall-view---paid) | | [CR to trials](paywall-metrics#unique-cr-to-trials) | 開始されたトライアル数を総ビュー数で割った値 | ペイウォールがビューをトライアルにどれだけ効果的に転換しているかを測定 | [Paywall view to trial](analytics-conversion#paywall-view---trial) | | [Unique CR to trials](paywall-metrics#unique-cr-to-trials) | 開始されたトライアル数をユニークビュー数で割った値 | CR to trials と同様の計算だが、分母にユニーク閲覧者を使用 | [Paywall view to trial](analytics-conversion#paywall-view---trial) | | [Purchases](paywall-metrics#purchases) | このペイウォールのトランザクション総数:新規購入、トライアル転換、アップグレード、ダウングレード、復帰サブスクリプション | 更新を除外 | [Revenue](revenue) | | [Trials](paywall-metrics#trials) | このペイウォールを通じて有効化された総トライアル数 | このペイウォールのみにスコープ | [New trials](new-trials) | | [Trials canceled](paywall-metrics#trials-canceled) | ユーザーが自動更新を無効化したトライアル数 | このペイウォールのトライアルのみにスコープ | [Trials renewal cancelled](trials-renewal-cancelled) | | [Refund rate](paywall-metrics#refund-rate) | 返金数を初回購入数で割った値(更新を除外) | 割合(%)であり件数ではない。返金を購入数で正規化 | [Refund events](refund-events)(件数、割合ではない) | | Completions | ユーザーがオンボーディングフローを最初から最後の画面まで完了した回数 | プレースメントとオンボーディングのみ。同一ユーザーによる繰り返し完了を含む、すべての完了をカウント | — | | Unique completions | オンボーディングフローを完了したユニークユーザー数 | プレースメントとオンボーディングのみ。各ユーザーを1回カウント。Completions と異なり、フローを終了した個人の数を測定 | — | | Unique completions rate | ユニーク完了数をユニークビュー数で割った値 | プレースメントとオンボーディングのみ。オンボーディングの効果を測定:開始したユーザーのうち何割が実際に完了したか | — | --- # File: overview --- --- title: "アナリティクス概要ページ" description: "複数の Adapty アナリティクスチャートを同じページで確認し、アプリのパフォーマンスを俯瞰できます" --- [概要ページ](https://app.adapty.io/overview)では、すべてのアプリの統合指標を一か所で確認できます。ダッシュボードのホームページとして機能し、左側のメニューからもアクセスできます。特定のアプリのデータを見たい場合は、個別の[チャート](charts)を開いてください。 ## チャート \{#charts\} 概要ページでは、Adapty の[アナリティクスチャート](charts)の中からカスタマイズして表示できます。利用可能なすべてのチャートの説明と比較については、[指標比較表](metric-comparison-table)を参照してください。 表示するチャートとその順序をカスタマイズするには、右上の **Edit** をクリックします。そこからチャートの削除、追加、並べ替えが行えます。 以下のチャートが利用できます: - [Revenue](revenue) - [MRR](mrr) - [ARR](arr) - [ARPU](arpu) - [ARPPU](arppu) - [ARPAS](placement-metrics#arpas) - [Installs](installs) - [New trials](new-trials) - [New subscriptions](reactivated-subscriptions) - [Active trials](active-trials) - [Active subscriptions](active-subscriptions) - [New non-subscriptions](non-subscriptions) - [Refund events](refund-events) - [Refund money](refund-money) - [Subscriptions renewal canceled](cancelled-subscriptions) - [インストールからトライアル、インストールから有料、トライアルから有料へのコンバージョン率](analytics-conversion) ## コントロール \{#controls\} 概要ページは、フィルタリング、グルーピング、期間比較など、[アナリティクスコントロール](controls-filters-grouping-compare-proceeds)のほとんどに対応しています。 概要ページ独自の機能として、アプリ別のグルーピングとフィルタリングがあります。このページはすべてのアプリのデータを統合しているため、アプリごとのビューでビジネス指標への各アプリの貢献度を確認できます。 ## インストール数とタイムゾーン \{#install-count-and-timezone\} 概要ページは**独自のタイムゾーンとインストール集計設定**を使用してすべてのアプリのデータを統合します。アプリごとの設定はここでは適用されません。 - **Installs**:インストールの集計方法を選択します。**By device installations** は、再インストールを含めデバイスへのインストールをそれぞれ個別にカウントします。**By unique users** は識別されたユーザーごとに初回インストールのみをカウントします。設定を変更するには、**Edit Metrics** をクリックし、ドロップダウンから[別のオプション](general#4-installs-definition-for-analytics)を選択してください。 - **Timezone**:概要ページのタイムゾーンを変更するには、**Edit Metrics** をクリックし、ドロップダウンからタイムゾーンを選択します。アカウント内の異なるアプリが異なるタイムゾーンを使用している場合に特に便利です。 --- # File: controls-filters-grouping-compare-proceeds --- --- title: "アナリティクスコントロール" description: "Adapty アナリティクスデータをフィルタリング、グループ化、比較する方法。" --- Adapty では、各アナリティクスタブのデータを絞り込むためのコントロールとして、時間範囲、期間比較、フィルタリング、グループ化、チャート表示を利用できます。利用可能なコントロールはタブによって異なります。 **アナリティクスタブ別の利用可能なコントロール:** | コントロール | チャート | コホート | ファネル | リテンション | コンバージョン | LTV | | :--- | :---: | :---: | :---: | :---: | :---: | :---: | | 日付範囲 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | 期間比較 | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | | フィルター | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | グループ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | | チャート表示 | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | | テーブル表示 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | CSV エクスポート | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | 手数料と税金 | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ### 日付範囲を設定する \{#set-the-date-range\} 各チャート上部の **Date range** カレンダーで期間を指定します。Adapty アナリティクスは **UTC タイムゾーン** を使用します。[概要ページ](overview) には独自の設定可能なタイムゾーンがあります。 #### プリセット範囲 \{#preset-ranges\} 任意の開始日・終了日を指定するには **Custom** オプションを使用します。プリセットの一覧は以下のとおりです: | プリセット | 開始 | 終了 | | --- | --- | --- | | Last 7 days | 6日前 | 今日 | | Last 28 days | 27日前 | 今日 | | Last month | 前月の同日 | 今日 | | Last 3 months | 3ヶ月前 | 今日 | | Last 6 months | 6ヶ月前 | 今日 | | Last year | 1年前 | 今日 | | Previous month | 前月の初日 | 前月の末日 | | This month | 当月1日 | 今日 | | This quarter | 当四半期の初日 | 今日 | | This year | 当年1月1日 | 今日 | :::tip 週次サブスクリプションプロダクトを追跡するには **Last 28 days** を使用してください。この範囲は4週間分をカバーするため、週の途中で期間が切れてしまうことがありません。 ::: #### タイムスケール \{#time-scale\} チャート上の各データポイントは一定の時間単位を表します。ドロップダウンから日、週、月、四半期、年を選択できます。日・週は短期的な増減を、月・四半期・年は長期的なトレンドを把握するのに適しています。 [コホート](analytics-cohorts)分析や [LTV](ltv) 分析では、同じ設定を **cohort length** と呼びます。詳細は各記事を参照してください。 ### 2つの期間を比較する \{#compare-two-time-periods\} カレンダーの隣にある比較オプションをクリックすると、現在の期間と直前の同じ長さの期間を重ねて表示できます。比較範囲を変更するには、オプションを再度クリックしてカスタム範囲を選択してください。 比較結果は以下の形式で表示されます: - **チャート上** — グループが0または1つの場合、折れ線・エリア・カラムが重ねて表示されます。 - **数値** — 2つの期間の差分が、上昇時は緑、下降時は赤で表示されます。 - **ツールチップ** — データポイントにカーソルを合わせると、そのポイントの数値差分が表示されます。 ### データをフィルタリング・グループ化する \{#filter-and-group-data\} **フィルター** を使うと、1つ以上の属性(例: 特定の国やプロダクト)に一致するデータのみをチャートに表示できます。**グループ化** を使うと、チャートの合計を属性値ごとに別々の系列に分割できます。たとえば、収益を国別にグループ化すると、合算した総計の代わりに国ごとの収益ラインが表示されます。 **利用可能なフィルター・グループ化属性:** | 属性 | フィルター | グループ | 説明 | | --- | :---: | :---: | --- | | アトリビューション | ✅ | ✅ | レポート元、ステータス、チャネル、キャンペーン、広告グループ、広告セット、クリエイティブ(キーワード)。[アトリビューション統合](attribution-integration)が必要です。 | | オーディエンス | ✅ | ✅ | ユーザーが属する[オーディエンス](audience)。 | | 更新ステータス | ❌ | ✅ | サブスクリプションが次の期間に更新されるかどうか。 | | 期間 | ✅ | ✅ | サブスクリプションのライフサイクルステージ: **Trial**、**Activation**(初回支払い)、**Renewal 1**〜**Renewal 5**、**Renewals 6+**(以降の更新)。 | | 国 | ✅ | ✅ | ユーザーのストア国。取得できない場合、Adapty は通貨コードまたはデバイスの IP から推定します。 | | オファータイプ | ✅ | ✅ | トランザクションに適用されたオファー: <ul><li>**Introductory** — サブスクリプション初回期間の初回オファー。有料の初回オファーと無料トライアルを区別するには **Offer Discount Type** を使用してください。</li><li>**Promotional** — App Store プロモーションオファーおよびそれに相当するもの。</li><li>**Offer Code** — ユーザーがストアで入力するプロモコード。</li><li>**No offer** — オファーなし。</li></ul> | | オファー ID | ✅ | ✅ | 特定のオファー ID。 | | オファー割引タイプ | ✅ | ✅ | 初回オファーまたはプロモーションオファーの価格モデル: **Free Trial**、**Pay As You Go**、または **Pay Up Front**。たとえば無料トライアルの初回オファーと有料の初回オファーを区別するには **Offer Type** と組み合わせて使用します。 | | ペイウォール | ✅ | ✅ | 購入に使用された[ペイウォール](paywalls)。 | | A/B テスト | ✅ | ❌ | 購入時に有効だった [A/B テスト](ab-tests)。 | | プレースメント | ✅ | ✅ | 購入が発生した[プレースメント](placements)。 | | ストア | ✅ | ✅ | トランザクションを処理したストア: App Store、Google Play、Stripe など。 | | プロダクト | ✅ | ✅ | [プロダクト](product) — サブスクリプションと買い切り購入。 | | 期間 | ✅ | ✅ | プロダクトの期間。 | | セグメント | ✅ | ✅ | ユーザー[セグメント](segments)。セグメントでグループ化すると、**All users** に対するセグメントのパフォーマンスを比較できます。<ul><li>ファネルはセグメントによるグループ化をサポートしていません。</li><li>セグメントが使用しているカスタム属性を後から変更した場合、Adapty はアナリティクスからそのユーザーをセグメントから除外することがあります。データには引き続き以前の値が表示されます。</li></ul> | | 払い戻し理由 | ✅ | ✅ | トランザクションが払い戻された理由(例: **Refund** または **Upgraded**)。払い戻しおよび請求問題解決チャートで利用可能。 | | 失効理由 | ❌ | ✅ | サブスクリプションまたはトライアルが失効した理由: **Cancelled by customer**、**Billing issue**、**Customer hasn't agreed to price increase**、**Unknown**、または **Refund**。失効(チャーン)したサブスクリプションおよびトライアルで利用可能。 | | コホート(LTV のみ) | ❌ | ✅ | LTV チャートでコホート期間(**Day**、**Week**、**Month**、**Year**)でグループ化します。このチャートではアトリビューションによるグループ化に代わります。 | 上記のすべてのフィルター・グループ化属性がすべてのアナリティクスビューで使用できるわけではありません。チャートタブの ARPU とインストール数は、アトリビューション、国、セグメント、ストア、および(フィルターのみ)A/B テストに限定されています。LTV、コホート、ファネル、リテンション、コンバージョンの各タブはそれぞれ異なるサブセットをサポートしています。詳細については、各チャートまたはタブの記事を参照してください。 ### 国の判定方法 \{#how-country-is-determined\} 各トランザクションには作成時に国が付与されます。国のソースは以下の優先順位で適用されます: 1. トランザクション時のユーザーの**デバイス IP の国**。 2. ユーザーの**ストア国** — App Store または Google Play のアカウント国。 3. 最後に確認されたユーザーの **IP の国**。 ウェブ決済(Stripe、Paddle)、手動で付与されたアクセス、またはストアが提供しなかったトランザクションではストア国を取得できません。その場合、Adapty は IP ベースの国にフォールバックします。 国はトランザクションごとに記録されるため、インストール後に App Store の国を変更したユーザーは、変更前後のトランザクションで異なる国の値を持ちます。過去のトランザクションは元の国を保持します。 **GB と United Kingdom について。** 国データは ISO 3166-1 alpha-2 コードで保存されます(「United Kingdom」ではなく「GB」)。ダッシュボードの表示レイヤーはコードをルックアップテーブルで正式名称にマッピングしており、レガシーの `'UK' → 'United Kingdom'` エイリアスが含まれています。そのため、セグメント作成時に両方が選択肢として表示されることがあります。 ### チャートの表示形式を変更する \{#change-the-chart-visualization\} 表示形式ドロップダウンからチャートの表示方法を選択します: - **Stacked column** — 各カラムに合計値をグループごとの色付きセグメントで表示します。 - **Stacked area** — 積み上げカラムと同様ですが、データポイントを結ぶ塗りつぶしエリアで表示します。 - **Line** — グループごとに1本の折れ線を表示し、塗りつぶしなし。 - **100% stacked column** — 各カラムがチャートの最大高さに達し、実際の値の代わりにグループごとの相対的な割合(パーセンテージ)を表示します。時系列での比率確認に便利です。 - **100% stacked area** — 100% 積み上げカラムと同様ですが、カラムの代わりに塗りつぶしエリアで表示します。 ### テーブルでデータを確認する \{#view-data-as-a-table\} 各チャートの下には同じデータが日付を列としたテーブルで表示されます。Total 行と列にはチャート上では確認できない集計値が表示されます。 ### データを CSV にエクスポートする \{#export-data-to-csv\} **Export** ボタンをクリックすると、チャートの基礎データを CSV ファイルとしてダウンロードできます。 :::tip プログラムによるアクセスや定期的なアクセスには、代わりに [Export API](export-analytics-api) を使用してください。CSV ダウンロードと同じデータを返します。 ::: ### 収益の表示形式(総収益 / 純収益) \{#display-gross-or-net-revenue\} 収益関連のチャート([Revenue](revenue)、[MRR](mrr)、[ARR](arr)、[ARPU](arpu)、[ARPPU](arppu))には、3つの表示モードを切り替えるドロップダウンがあります: - **Gross revenue** — 控除前の総収益。 - **Proceeds after store commission** — ストアの手数料を差し引いた収益(税金は含む)。 - **Proceeds after store commission and taxes** — 手数料と税金の両方を差し引いた収益。 手数料と税金の計算方法の詳細については、「*Adapty アナリティクスの仕組み*」の[手数料と税金](how-adapty-analytics-works#commissions-and-taxes)を参照してください。 --- # File: revenue --- --- title: "収益" description: "Adaptyのサブスクリプションインサイトを使用して、アプリの収益を追跡・分析します。" --- 収益チャートは、サブスクリプションと買い切り購入の両方から得た総収益から、後日返金された金額を差し引いた値を表示します。アプリの財務パフォーマンスを監視するための主要な指標です。 月次の解像度に切り替えると、過去12か月の全体的なトレンドを把握できます。プロダクト、ユーザーセグメント、またはアトリビューションソース別にチャートをグループ化して収益の発生源を確認し、新規対更新の比率を見てビジネスのどちらの側が成長を牽引しているかを把握しましょう。 ## 計算方法 \{#calculation\} :::warning 以下の計算機は[ストア手数料と税金](how-adapty-analytics-works#commissions-and-taxes)を**考慮していません**。結果をあなたの**グロス収益**の計算と比較してください。 ::: 収益は、期間内のすべての有料トランザクション(新規サブスクリプション、更新、トライアルからの転換、買い切り購入)の合計から、期間内に処理された返金を差し引いた値です:**収益 = 総トランザクション − 返金**。 各トランザクションの全額は、サブスクリプションの期間にわたって分散されるのではなく、購入日に計上されます。 チャートはデフォルトでグロス収益を表示します。[チャートコントロール](controls-filters-grouping-compare-proceeds#display-gross-or-net-revenue)を使用して、グロス、手数料差引後、または手数料・税金差引後の表示に切り替えられます。 <CompoundCalculator client:load heading="Revenue" formuLatex="\sum P_i \times Q_i - D" variables={[ { nameInTheFormula: "P", variableName: "price", variableDescription: "Price per unit", variableValue: 10 }, { nameInTheFormula: "Q", variableName: "qty", variableDescription: "Quantity", variableValue: 1, isInteger: true }, { nameInTheFormula: "D", variableName: "refunds", variableDescription: "Amount refunded", variableValue: 35, global: true } ]} rowFormula="price * qty" resultFormula="_sum - refunds" defaultRows={[ { price: 10, qty: 5 }, { price: 50, qty: 10 }, { price: 100, qty: 1 } ]} /> ## 返金の処理 \{#refund-handling\} 収益は、各返金を元の購入日ではなく、返金が処理された日付に差し引きます。特定のグループや日にバケット内の返金が新規収益を上回った場合、チャートに負の値が表示されることがあります。 指標全体での比較については、[指標における返金の処理方法](refund-events#how-metrics-handle-refunds)をご覧ください。 ## 通貨 \{#currency\} --- no_index: true --- Adaptyはすべての金額チャートを**米ドル(USD)**で表示します。元の取引通貨に関わらず、収益、MRR、ARR、ARPU、ARPPU、LTV、予測収益、返金額、コホートおよびA/Bテストレポート内の収益数値が対象です。他の通貨で表示する設定はありません。 Adaptyは各取引を[currencylayer.com](https://currencylayer.com/)のレートを使用してUSDに換算します。このレートは8時間ごとに更新され、**取引時点のレートに固定**されます。為替が変動しても、過去のUSD換算値は再計算されません。 現地通貨の値は、取引ごとに以下で確認できます。 - Webhookの`price`および`currency_code`フィールド - S3、GCS、BigQueryエクスポートの`price`および`currency_code`カラム - プロファイルページ(取引ごとの表示) 現地通貨で財務レポートを作成する場合は、エクスポートから取引ごとの現地通貨の値を取得し、自分で集計してください。 ## 更新時の価格設定 \{#renewal-pricing\} --- no_index: true --- Adaptyは、ユーザーが最初に購読したときの価格に関わらず、プロダクトの現在の価格で更新収益を計算します。App Store ConnectまたはGoogle Playで価格を変更した後、既存のサブスクリプションユーザーに対するダッシュボードのRevenue、MRR、ARRの数値は、実際に収集された収益と乖離する場合があります。ストアがそれらのユーザーを旧価格のまま維持していても、Adaptyは新しい価格を適用します。 確認するには、S3、GCS、またはBigQueryエクスポートのトランザクションごとの`price`フィールドと、同じトランザクションのダッシュボードの値を比較してください。エクスポートフィールドはストアが報告した値(顧客が実際に支払った価格)を反映し、ダッシュボードは現在のプロダクト価格を反映します。 ## 利用可能なフィルターとグループ化 \{#available-filters-and-grouping\} :::link メイン記事:[アナリティクスコントロール](controls-filters-grouping-compare-proceeds) ::: - ✅ フィルター対象:アトリビューション、オーディエンス、国、オファータイプ、オファーID、オファー割引タイプ、ペイウォール、A/B テスト、プレースメント、期間、セグメント、ストア、プロダクト、期間(デュレーション)。 - ✅ グループ化:期間、更新ステータス、プロダクト、国、ストア、ペイウォール、オーディエンス、プレースメント、期間(デュレーション)、オファータイプ、オファー割引タイプ、オファーID、セグメント、アトリビューション。 ## 類似指標 \{#similar-metrics\} これらの指標を並べて比較するには、[指標比較表](metric-comparison-table#revenue)をご覧ください。 - [MRR](mrr) - [ARR](arr) - [ARPU](arpu) - [ARPPU](arppu) --- # File: mrr --- --- title: "MRR" description: "Adapty で月次経常収益(MRR)を理解し最適化する。" --- 月次経常収益(MRR)チャートは、アクティブな有料サブスクリプションからの収益を月次換算した値で表示します。サブスクリプションの期間に関わらず、サブスクリプションビジネスが生み出す安定した収益を示します。 各サブスクライバーのコホートが経常収益にどのように貢献しているかを時系列で確認するには、チャートを初回購入月でグループ化し、月次解像度に切り替えてください。積み上げエリア表示で、各コホートの月ごとの貢献を確認できます。 ## 計算方法 \{#calculation\} :::warning 以下の計算機は、[ストア手数料と税金](how-adapty-analytics-works#commissions-and-taxes)を**考慮していません**。結果は**グロス収益**の計算と比較してください。 ::: MRR は各サブスクリプションの収益を月次換算に正規化します。たとえば、年間 $240 のサブスクリプションは毎月 $20 として計上され、$240 が一括計上されるわけではありません。これにより、サブスクリプションの請求期間の分布に関わらず MRR が安定します。 MRR は、すべてのサブスクリプション種別に対して(価格 × アクティブなサブスクライバー数 ÷ 請求期間(月数))の合計です。週次サブスクリプションの請求期間は ≈0.23 ヶ月として計算されます。 <SimpleCalculator client:load heading="MRR" formuLatex="\sum_{subscriptions}^{}\frac{P_s\times N_s}{D_m}" variables={[ { nameInTheFormula: "P_s", variableName: "subscriptionPrice", variableDescription: "Price", variableValue: 10 }, { nameInTheFormula: "N_s", variableName: "activeSubs", variableDescription: "Subscribers", variableValue: 1, isInteger: true }, { nameInTheFormula: "D_m", variableName: "duration", variableDescription: "Subscription period", variableValue: 1, options: [ { label: "Weekly", value: 0.23 }, { label: "Monthly", value: 1 }, { label: "2 months", value: 2 }, { label: "3 months", value: 3 }, { label: "6 months", value: 6 }, { label: "Annual", value: 12 } ] } ]} formulaCalculation="(subscriptionPrice * activeSubs) / duration" isSum={true} defaultRows={[ { subscriptionPrice: 240, activeSubs: 2, duration: 12}, { subscriptionPrice: 30, activeSubs: 10, duration: 1}, { subscriptionPrice: 10, activeSubs: 20, duration: 0.23}, ]} /> MRR には、経常収益を生み出さないプロダクトは含まれません。 - 買い切り購入 - 消耗型アイテム - 非更新型サブスクリプション ユーザーベースが買い切り型プロダクトを通じて安定した収益を生み出している場合でも、購入自体が継続的なものではないため、その収益は MRR に計上されません。 ## 返金処理 \{#refund-handling\} サブスクリプションが返金されると、MRR はそれまでカウントされていたすべての日付からその貢献分を差し引きます。返金が発生すると、過去の MRR 値が下がる場合があります。 指標間の全体的な比較については、[指標の返金処理方法](refund-events#how-metrics-handle-refunds)を参照してください。 ## 通貨 \{#currency\} --- no_index: true --- Adaptyはすべての金額チャートを**米ドル(USD)**で表示します。元の取引通貨に関わらず、収益、MRR、ARR、ARPU、ARPPU、LTV、予測収益、返金額、コホートおよびA/Bテストレポート内の収益数値が対象です。他の通貨で表示する設定はありません。 Adaptyは各取引を[currencylayer.com](https://currencylayer.com/)のレートを使用してUSDに換算します。このレートは8時間ごとに更新され、**取引時点のレートに固定**されます。為替が変動しても、過去のUSD換算値は再計算されません。 現地通貨の値は、取引ごとに以下で確認できます。 - Webhookの`price`および`currency_code`フィールド - S3、GCS、BigQueryエクスポートの`price`および`currency_code`カラム - プロファイルページ(取引ごとの表示) 現地通貨で財務レポートを作成する場合は、エクスポートから取引ごとの現地通貨の値を取得し、自分で集計してください。 ## 更新時の価格設定 \{#renewal-pricing\} --- no_index: true --- Adaptyは、ユーザーが最初に購読したときの価格に関わらず、プロダクトの現在の価格で更新収益を計算します。App Store ConnectまたはGoogle Playで価格を変更した後、既存のサブスクリプションユーザーに対するダッシュボードのRevenue、MRR、ARRの数値は、実際に収集された収益と乖離する場合があります。ストアがそれらのユーザーを旧価格のまま維持していても、Adaptyは新しい価格を適用します。 確認するには、S3、GCS、またはBigQueryエクスポートのトランザクションごとの`price`フィールドと、同じトランザクションのダッシュボードの値を比較してください。エクスポートフィールドはストアが報告した値(顧客が実際に支払った価格)を反映し、ダッシュボードは現在のプロダクト価格を反映します。 ## 利用可能なフィルターとグループ化 \{#available-filters-and-grouping\} :::link メイン記事:[アナリティクスコントロール](controls-filters-grouping-compare-proceeds) ::: - ✅ フィルター対象:アトリビューション、オーディエンス、国、オファータイプ、オファー ID、オファー割引タイプ、ペイウォール、A/B テスト、プレースメント、期間、セグメント、ストア、プロダクト、期間長。 - ✅ グループ化対象:期間、更新ステータス、プロダクト、国、ストア、ペイウォール、オーディエンス、プレースメント、期間長、オファータイプ、オファー割引タイプ、オファー ID、セグメント、アトリビューション。 ## 関連指標 \{#similar-metrics\} これらの指標を並べて比較するには、[指標比較表](metric-comparison-table#revenue)を参照してください。 - [Revenue(収益)](revenue) - [ARR](arr) - [ARPU](arpu) - [ARPPU](arppu) --- # File: arr --- --- title: "ARR" description: "年間定期収益(ARR)を追跡し、サブスクリプション戦略を最適化しましょう。" --- 年間定期収益チャートは、有効なすべての自動更新サブスクリプションの収益を1年間に換算して表示します。有料かつ未失効のサブスクリプションはすべてアクティブとみなされます。ARRは、サブスクリプションビジネスの成長を追跡し、将来の収益を予測するための重要な指標です。 ## 計算方法 \{#calculation\} :::warning 以下の計算機は、[ストア手数料と税金](how-adapty-analytics-works#commissions-and-taxes)を**考慮していません**。結果は**売上総額**の計算と比較してください。 ::: ARRは、定期的なサブスクリプション収益を年換算したものです。年間サブスクリプションがメインのプロダクトである場合に最も役立ちます。月次または週次のサブスクリプションが中心のビジネスには、[MRR](mrr)の方が参考になります。 ARRは、すべてのサブスクリプションタイプにわたる「価格 × アクティブな加入者数 ÷ 請求期間(年単位)」の合計です。月次は1/12、週次は1/52を使用します。 <SimpleCalculator client:load heading="ARR" formuLatex="\sum \frac{P_s \times U_s}{D_y}" variables={[ { nameInTheFormula: "P_s", variableName: "price", variableDescription: "Subscription price", variableValue: 240 }, { nameInTheFormula: "U_s", variableName: "subs", variableDescription: "Active paid subs", variableValue: 2, isInteger: true }, { nameInTheFormula: "D_y", variableName: "periods", variableDescription: "Subscription period", variableValue: 1, options: [ { label: "Weekly", value: "1/52" }, { label: "Monthly", value: "1/12" }, { label: "2 months", value: "2/12" }, { label: "3 months", value: "3/12" }, { label: "6 months", value: "6/12" }, { label: "Annual", value: 1 } ] } ]} formulaCalculation="(price * subs ) / periods" isSum={true} defaultRows={[ { price: 240, subs: 2, periods: "1" }, { price: 30, subs: 10, periods: "1/12" }, { price: 10, subs: 20, periods: "1/52" } ]} /> ## 返金の処理 \{#refund-handling\} サブスクリプションが返金された場合、それ以前にカウントされていたすべての日付について、ARRからその寄与分が差し引かれます。返金が発生すると、過去のARR値が減少することがあります。 各指標での返金の扱いを比較するには、[指標における返金の処理方法](refund-events#how-metrics-handle-refunds)を参照してください。 ## 通貨 \{#currency\} --- no_index: true --- Adaptyはすべての金額チャートを**米ドル(USD)**で表示します。元の取引通貨に関わらず、収益、MRR、ARR、ARPU、ARPPU、LTV、予測収益、返金額、コホートおよびA/Bテストレポート内の収益数値が対象です。他の通貨で表示する設定はありません。 Adaptyは各取引を[currencylayer.com](https://currencylayer.com/)のレートを使用してUSDに換算します。このレートは8時間ごとに更新され、**取引時点のレートに固定**されます。為替が変動しても、過去のUSD換算値は再計算されません。 現地通貨の値は、取引ごとに以下で確認できます。 - Webhookの`price`および`currency_code`フィールド - S3、GCS、BigQueryエクスポートの`price`および`currency_code`カラム - プロファイルページ(取引ごとの表示) 現地通貨で財務レポートを作成する場合は、エクスポートから取引ごとの現地通貨の値を取得し、自分で集計してください。 ## 更新時の価格 \{#renewal-pricing\} --- no_index: true --- Adaptyは、ユーザーが最初に購読したときの価格に関わらず、プロダクトの現在の価格で更新収益を計算します。App Store ConnectまたはGoogle Playで価格を変更した後、既存のサブスクリプションユーザーに対するダッシュボードのRevenue、MRR、ARRの数値は、実際に収集された収益と乖離する場合があります。ストアがそれらのユーザーを旧価格のまま維持していても、Adaptyは新しい価格を適用します。 確認するには、S3、GCS、またはBigQueryエクスポートのトランザクションごとの`price`フィールドと、同じトランザクションのダッシュボードの値を比較してください。エクスポートフィールドはストアが報告した値(顧客が実際に支払った価格)を反映し、ダッシュボードは現在のプロダクト価格を反映します。 ## 利用可能なフィルターとグループ化 \{#available-filters-and-grouping\} :::link メイン記事:[アナリティクスコントロール](controls-filters-grouping-compare-proceeds) ::: - ✅ フィルター対象:アトリビューション、オーディエンス、国、オファータイプ、オファーID、オファー割引タイプ、ペイウォール、A/B テスト、プレースメント、期間、セグメント、ストア、プロダクト、期間長。 - ✅ グループ化対象:期間、更新ステータス、プロダクト、国、ストア、ペイウォール、オーディエンス、プレースメント、期間長、オファータイプ、オファー割引タイプ、オファーID、セグメント、アトリビューション。 ## 関連指標 \{#similar-metrics\} これらの指標を並べて比較するには、[指標比較表](metric-comparison-table#revenue)を参照してください。 - [収益](revenue) - [MRR](mrr) - [ARPU](arpu) - [ARPPU](arppu) --- # File: arpu --- --- title: "ARPU" description: "ユーザー一人当たりの平均収益(ARPU)を分析して、収益の最適化に役立てましょう。" --- ARPU(ユーザー一人当たりの平均収益)チャートは、特定の期間におけるユーザー一人当たりの平均収益を表示します。この指標は、コホートの総収益をそのコホートのユーザー数で割ることで算出されます。ARPUを使って、アトリビューションソース、国、プロダクトなどのユーザーセグメント間での収益パフォーマンスを比較できます。 ## 計算方法 \{#calculation\} :::warning 以下の計算機は[ストアの手数料と税金](how-adapty-analytics-works#commissions-and-taxes)を**考慮していません**。結果は**総収益**の計算と比較してください。 ::: ARPUは、アプリがユーザー一人当たりに生み出す平均収益を示す、マネタイズ効率の一般的な基準指標です。 ARPUは、その期間の収益(返金を差し引いた額)を同期間のアプリ総ユーザー数で割った値です。 <CompoundCalculator client:load heading="ARPU" formuLatex="\frac{\sum P_i \times Q_i - D}{U_p}" variables={[ { nameInTheFormula: "P", variableName: "price", variableDescription: "プロダクト価格", variableValue: 10 }, { nameInTheFormula: "Q", variableName: "qty", variableDescription: "購入されたプロダクト数", variableValue: 1, isInteger: true }, { nameInTheFormula: "D", variableName: "refunds", variableDescription: "返金額", variableValue: 35, global: true }, { nameInTheFormula: "Up", variableName: "users", variableDescription: "総ユーザー数", variableValue: 160, global: true, isInteger: true } ]} rowFormula="price * qty" resultFormula="(_sum - refunds) / users" defaultRows={[ { price: 10, qty: 5 }, { price: 50, qty: 10 }, { price: 100, qty: 1 } ]} /> ## 返金の処理 \{#refund-handling\} 返金は、処理された日付に収益の分子から差し引かれます。 各指標での返金の扱いの詳細な比較については、[各指標における返金の処理方法](refund-events#how-metrics-handle-refunds)を参照してください。 ## 通貨 \{#currency\} --- no_index: true --- Adaptyはすべての金額チャートを**米ドル(USD)**で表示します。元の取引通貨に関わらず、収益、MRR、ARR、ARPU、ARPPU、LTV、予測収益、返金額、コホートおよびA/Bテストレポート内の収益数値が対象です。他の通貨で表示する設定はありません。 Adaptyは各取引を[currencylayer.com](https://currencylayer.com/)のレートを使用してUSDに換算します。このレートは8時間ごとに更新され、**取引時点のレートに固定**されます。為替が変動しても、過去のUSD換算値は再計算されません。 現地通貨の値は、取引ごとに以下で確認できます。 - Webhookの`price`および`currency_code`フィールド - S3、GCS、BigQueryエクスポートの`price`および`currency_code`カラム - プロファイルページ(取引ごとの表示) 現地通貨で財務レポートを作成する場合は、エクスポートから取引ごとの現地通貨の値を取得し、自分で集計してください。 ## 利用可能なフィルターとグループ \{#available-filters-and-grouping\} :::link メイン記事:[分析のコントロール](controls-filters-grouping-compare-proceeds) ::: - ✅ フィルター対象:アトリビューション、国、A/B テスト、セグメント、ストア - ✅ グループ対象:国、ストア、セグメント、アトリビューション ## 関連指標 \{#similar-metrics\} これらの指標の比較については、[指標比較表](metric-comparison-table#revenue)を参照してください。 - [収益(Revenue)](revenue) - [MRR](mrr) - [ARPPU](arppu) - [ARR](arr) --- # File: arppu --- --- title: "ARPPU" description: "ARPPU(有料ユーザー一人当たりの平均収益)がアプリのマネタイズに与える影響を理解しましょう。" --- ARPPU(有料ユーザー一人当たりの平均収益)チャートは、有料ユーザー一人当たりの平均収益を表示します。有料ユーザーが実際に生み出した収益を顧客数で割り、返金額を差し引いた値です。アトリビューション別にARPPUをグループ化すると、より高い価値の有料ユーザーをもたらしている獲得チャネルを確認できます。 ## 計算方法 \{#calculation\} :::warning 以下の計算ツールは[ストア手数料と税金](how-adapty-analytics-works#commissions-and-taxes)を**考慮していません**。結果は**グロス収益**の計算と比較してください。 ::: ARPPUは有料ユーザー一人当たりの平均収益を示します。分母に非有料ユーザーが含まれないため、通常は[ARPU](arpu)よりも大幅に高くなります。 ARPPUは、該当期間の収益(返金額を差し引いた値)をその期間の有料ユーザー数で割った値です。 <CompoundCalculator client:load heading="ARPPU" formuLatex="\frac{\sum P_i \times Q_i - D}{U_p}" variables={[ { nameInTheFormula: "P", variableName: "price", variableDescription: "Product price", variableValue: 10 }, { nameInTheFormula: "Q", variableName: "qty", variableDescription: "Products purchased", variableValue: 1, isInteger: true }, { nameInTheFormula: "D", variableName: "refunds", variableDescription: "Amount refunded", variableValue: 35, global: true }, { nameInTheFormula: "Up", variableName: "users", variableDescription: "Paying users", variableValue: 16, global: true, isInteger: true } ]} rowFormula="price * qty" resultFormula="(_sum - refunds) / users" defaultRows={[ { price: 10, qty: 5 }, { price: 50, qty: 10 }, { price: 100, qty: 1 } ]} /> ## 返金の処理方法 \{#refund-handling\} 返金は処理された日付に収益の分子から差し引かれます。購入後に返金を受けたユーザーも有料ユーザーの分母にはカウントされたままになるため、返金が多いほどARPPUは予想以上に急激に低下します。 指標全体にわたる比較については、[指標における返金の扱い方](refund-events#how-metrics-handle-refunds)をご覧ください。 ## 通貨 \{#currency\} --- no_index: true --- Adaptyはすべての金額チャートを**米ドル(USD)**で表示します。元の取引通貨に関わらず、収益、MRR、ARR、ARPU、ARPPU、LTV、予測収益、返金額、コホートおよびA/Bテストレポート内の収益数値が対象です。他の通貨で表示する設定はありません。 Adaptyは各取引を[currencylayer.com](https://currencylayer.com/)のレートを使用してUSDに換算します。このレートは8時間ごとに更新され、**取引時点のレートに固定**されます。為替が変動しても、過去のUSD換算値は再計算されません。 現地通貨の値は、取引ごとに以下で確認できます。 - Webhookの`price`および`currency_code`フィールド - S3、GCS、BigQueryエクスポートの`price`および`currency_code`カラム - プロファイルページ(取引ごとの表示) 現地通貨で財務レポートを作成する場合は、エクスポートから取引ごとの現地通貨の値を取得し、自分で集計してください。 ## 利用可能なフィルターとグループ化 \{#available-filters-and-grouping\} :::link メイン記事:[Analytics controls](controls-filters-grouping-compare-proceeds) ::: - ✅ フィルター対象:アトリビューション、オーディエンス、国、ペイウォール、A/B テスト、プレースメント、期間、セグメント、ストア、プロダクト、期間。 - ✅ グループ化:期間、更新ステータス、プロダクト、国、ストア、ペイウォール、オーディエンス、プレースメント、期間、セグメント、アトリビューション。 ## 類似指標 \{#similar-metrics\} これらの指標の並べて比較については、[指標比較表](metric-comparison-table#revenue)をご覧ください。 - [Revenue](revenue) - [MRR](mrr) - [ARPU](arpu) - [ARR](arr) --- # File: installs --- --- title: "インストール" description: "Adaptyを使ってアプリのインストール数を追跡し、サブスクリプションへの影響を把握しましょう。" --- インストールチャートは、選択した期間にアプリをインストールしたユーザー数を表示します。何がインストールとしてカウントされるか、またどのようにグループ化されるかは、インストールのカウント設定によって異なります。 この記事では、適切なカウントモードの選択方法と、さまざまなアナリティクスソース間で[生じる可能性のある差異のトラブルシューティング](#troubleshooting)について説明します。 ## インストールとしてカウントされるもの \{#what-counts-as-an-install\} Adapty SDKは、ユーザーがアプリを初めて起動したときに「インストール」として登録し、Adaptyに送信します。 これには2つの影響があります。 - Adaptyへのインストール記録は、ユーザーが初めてアプリを開いたタイミングで行われるため、ダウンロードから数時間〜数日後になることがあります。 - ユーザーがダウンロードしてもアプリを一度も開かない場合、Adaptyにはカウントされません。 **App Settings**のレポートタイムゾーンによって、各インストールがどの日付に反映されるかが決まります。たとえば、UTC 6月1日の23:30のインストールは、タイムゾーンが+02:00の場合は6月2日として記録されますが、App Store ConnectやGoogle Playでは6月1日として表示される場合があります。 ### カウントモード \{#counting-modes\} **Installs definition for analytics** 設定により、新規インストールとしてカウントされる条件が決まります。変更するには、[App Settings → General → Installs definition for analytics](general#4-installs-definition-for-analytics)を開いてください。 | モード | カウント対象 | 例 | サードパーティの指標 | 差異が生じる可能性 | | --- | --- | --- | --- | --- | | **New device_ids**(推奨) | 再インストールを含む**すべてのアプリインストール**。認証、プロファイル作成、バージョンアップグレードはカウントに含まれません。 | 1ユーザーが5台のデバイスを使用 = 5インストール。<br /> <br /> 同じデバイスで再インストール = 2インストール。 | App Store: <br /> **Total Active Devices** <br /> <br /> Google Play: **Devices** | 再インストールが多い場合、**アプリダウンロード数より多くなる**可能性があります。<br /> <br /> アプリを開かずにダウンロードするユーザーが多い場合、**アプリダウンロード数より少なくなる**可能性があります。 | | **New customer_user_ids** | [識別済みユーザー](identifying-users)ごとの**初回インストールのみ**。追加デバイスや匿名ユーザーはカウントされません。 | 1ユーザーが5台のデバイスを使用 = 1インストール。<br /> <br /> 再インストール後にログインし直しても新規インストールとしてカウントされません。<br /> <br /> アカウントなしでアプリを使用した場合もカウントされません。 | アプリの認証システムのサインアップ統計 | ユーザーをまったく識別しない場合、**データが空のまま**になります。 | | **New profiles in Adapty**(レガシー) | すべてのインストールと再インストール、さらに**ログアウト時に作成された匿名プロファイル**もカウントします。 | 1ユーザー・1デバイスで3回ログアウト = 4インストール。 | なし | **すべての外部指標より高くなります**。ログアウト時に作成される匿名プロファイルもインストールとしてカウントされます。 | 特別な理由がない限り、**New device_ids** を使用してください。 ## トラブルシューティング \{#troubleshooting\} ### AdaptyのカウントがApp Store ConnectやGoogle Playより多い \{#adaptys-count-is-higher-than-app-store-connect-or-google-play\} 主な原因は2つあります。 - **再インストール。** [カウントモード](#counting-modes)が **New device_ids** に設定されている場合、Adaptyは初回起動と再インストールの両方をカウントします。App Store Connectの「Total Downloads」は初回ダウンロードのみをカウントします。 - **初回起動日 ≠ ダウンロード日。** ストアはダウンロード日をもとに集計します。アプリを遅れて開いたユーザーは別の日付に記録されます。 より正確に比較するには、**App Store Connect → Total Active Devices** または **Google Play → Devices** を確認してください。これらの指標はデバイス単位で集計されており、Adaptyの **New device_ids** モードに近い数値になります。 ### Adaptyのカウントがゼロになる \{#adaptys-count-is-zero\} カウントモードが **New customer_user_ids** に設定されているにもかかわらず、<InlineTooltip tooltip="ユーザーを認証する">[iOS](identifying-users)、[Android](android-identifying-users)、[React Native](react-native-identifying-users)、[Flutter](flutter-identifying-users)、[Unity](unity-identifying-users)、[Kotlin Multiplatform](kmp-quickstart-identify)、[Capacitor](capacitor-quickstart-identify)</InlineTooltip>を実装していない場合、Adaptyはインストールを記録しません。このモードでは、匿名インストールは除外されます。**New device_ids** に切り替えるか、ユーザー識別を実装してください。 ### AdaptyのカウントがAppsFlyerやAdjustと異なる \{#adaptys-count-differs-from-appsflyer-or-adjust\} MMP(モバイル計測パートナー)は、独自のSDK初期化またはファーストタッチイベントを基準にインストールを計測します。これらのタイミングはAdaptyのSDK初回起動とは異なるため、ある程度の差異が生じるのは正常です。 ## 利用可能なフィルターとグループ化 \{#available-filters-and-grouping\} :::link メイン記事:[アナリティクスの操作](controls-filters-grouping-compare-proceeds) ::: - ✅ フィルター:アトリビューション、国、A/B テスト、セグメント、ストア - ✅ グループ化:国、ストア、セグメント、アトリビューション ## 関連指標 \{#similar-metrics\} これらの指標の比較一覧については、[指標比較表](metric-comparison-table#subscribers-and-conversion)をご覧ください。 - [新規サブスクリプション](reactivated-subscriptions) - [アクティブサブスクリプション](active-subscriptions) - [新規トライアル](new-trials) --- # File: active-subscriptions --- --- title: "アクティブなサブスクリプション" description: "Adaptyの強力なアナリティクスでアクティブなサブスクリプションを監視・管理しましょう。" --- アクティブなサブスクリプションチャートは、選択した各期間の終了時点でまだ有効期限が切れていない一意の有料サブスクリプション数を表示します。開始済みで現在アクティブな通常の(有効期限内の)アプリ内サブスクリプションを含み、無料トライアルおよび更新がキャンセルされたサブスクリプションは除外されます。サブスクライバーベースの規模と成長を把握するための指標です。 ## 計算方法 \{#calculation\} アクティブなサブスクリプションの指標は、各期間終了時点における有料かつ有効期限内のサブスクリプション数をカウントします。グレース期間のないサブスクリプションの場合、次の更新日が到来しても正常に更新されなければ有効期限切れとなります。 例:先月末のアクティブなサブスクリプション500件+今月の新規50件-今月に有効期限が切れた25件=今月末のアクティブなサブスクリプション525件。 ## 返金の処理 \{#refund-handling\} サブスクリプションが返金された場合、Adaptyはそのサブスクリプションをアクティブ数から削除します。これは現在だけでなく、過去の日付に対しても遡って適用されます。 指標全体での返金の取り扱い比較については、[指標の返金処理方法](refund-events#how-metrics-handle-refunds)をご覧ください。 ## 利用可能なフィルターとグループ化 \{#available-filters-and-grouping\} :::link メイン記事:[アナリティクスのコントロール](controls-filters-grouping-compare-proceeds) ::: - ✅ フィルター:アトリビューション、オーディエンス、国、オファータイプ、オファーID、オファー割引タイプ、ペイウォール、A/B テスト、プレースメント、期間、セグメント、ストア、プロダクト、期間。 - ✅ グループ化:期間、更新ステータス、プロダクト、国、ストア、ペイウォール、オーディエンス、プレースメント、期間、オファータイプ、オファー割引タイプ、オファーID、セグメント、アトリビューション。 ## 関連指標 \{#similar-metrics\} これらの指標の横断比較については、[指標比較表](metric-comparison-table#subscribers-and-conversion)をご覧ください。 - [解約(期限切れ)サブスクリプション](churned-expired-subscriptions) - [キャンセルされたサブスクリプション](cancelled-subscriptions) - [買い切り購入](non-subscriptions) --- # File: reactivated-subscriptions --- --- title: "新規サブスクリプション" description: "Adaptyで新規サブスクリプションを追跡し、初回コンバージョンや無料トライアルから有料への転換を監視します。" --- 新規サブスクリプションチャートは、アプリ内で新たに(初めて)有効化されたサブスクリプションの数を表示します。この指標は、特定の期間に開始した新規サブスクリプションの数を示しており、ゼロから始まるサブスクリプションと、無料トライアルから有料サブスクリプションに転換したものの両方が含まれます。サブスクリプションの更新や再開されたサブスクリプションは含まれません。 ## 計算方法 \{#calculation\} 新規サブスクリプション指標は、期間中の初回サブスクリプション有効化数をカウントします。ゼロから始まるサブスクリプションと、無料トライアルから有料サブスクリプションに転換したものの両方が含まれます。 ## 返金の扱い \{#refund-handling\} 新規サブスクリプションは返金を**差し引きません**。後に返金されたサブスクリプションもカウントに含まれます。正味の影響を把握するには、[返金イベント](refund-events)と比較してください。 各指標における返金の扱いの全体比較については、[指標ごとの返金処理方法](refund-events#how-metrics-handle-refunds)をご覧ください。 ## 利用可能なフィルターとグループ化 \{#available-filters-and-grouping\} :::link メイン記事:[アナリティクスのコントロール](controls-filters-grouping-compare-proceeds) ::: - ✅ フィルター項目:アトリビューション、オーディエンス、国、オファータイプ、オファーID、オファー割引タイプ、ペイウォール、A/B テスト、プレースメント、期間、セグメント、ストア、プロダクト、期間長。 - ✅ グループ化項目:更新ステータス、プロダクト、国、ストア、ペイウォール、オーディエンス、プレースメント、期間長、オファータイプ、オファー割引タイプ、オファーID、セグメント、アトリビューション。 ## 関連指標 \{#similar-metrics\} これらの指標の比較表については、[指標比較テーブル](metric-comparison-table#subscribers-and-conversion)をご覧ください。 - [アクティブサブスクリプション](active-subscriptions) - [解約済み(期限切れ)サブスクリプション](churned-expired-subscriptions) - [キャンセル済みサブスクリプション](cancelled-subscriptions) - [買い切り購入](non-subscriptions) --- # File: non-subscriptions --- --- title: "非サブスクリプション" description: "Adaptyで非サブスクリプションプロダクトを管理し、ユーザーの購入を効率的に追跡する方法を学びましょう。" --- 非サブスクリプションチャートは、自動更新サブスクリプション以外のアプリ内課金(消耗型アイテム、非消耗型アイテム、非更新型サブスクリプション)の件数を集計します。更新は対象外です。 :::note 「非サブスクリプション」は「買い切り購入」より広い概念です。消耗型アイテムと非更新型サブスクリプションはそれぞれ複数回購入できます。 ::: ## 計算方法 \{#calculation\} 非サブスクリプションのアプリ内課金は、次の3種類に分類されます。 - **消耗型アイテム**: 複数回購入できるアイテム。釣りアプリの魚のエサや追加のゲーム内通貨などが例として挙げられます。 - **非消耗型アイテム**: 1回購入すると永続的に使用できるアイテム。ゲームアプリのレーストラックや広告非表示版などが該当します。 - **非更新型サブスクリプション**: 一定期間後に期限切れとなり、自動更新されないサブスクリプション。コンテンツカタログへの1年間アクセスなどが例として挙げられます。コンテンツは静的なものでよく、期限が切れると更新されません。 :::note このチャートは購入イベントのみを集計し、返金された購入分は差し引きません。非サブスクリプションプロダクトで返金が多い場合、表示される件数は実際に収益を生んだ購入数より多くなります。 ::: ## 利用可能なフィルターとグループ化 \{#available-filters-and-grouping\} :::link メイン記事:[アナリティクスのコントロール](controls-filters-grouping-compare-proceeds) ::: - ✅ フィルター:アトリビューション、オーディエンス、国、ペイウォール、A/B テスト、プレースメント、セグメント、ストア、プロダクト - ✅ グループ化:プロダクト、国、ストア、ペイウォール、オーディエンス、プレースメント、セグメント、アトリビューション ## 関連指標 \{#similar-metrics\} これらの指標を横並びで比較するには、[指標比較表](metric-comparison-table#revenue)をご覧ください。 - [アクティブなサブスクリプション](active-subscriptions) - [新規サブスクリプション](reactivated-subscriptions) - [解約(期限切れ)サブスクリプション](churned-expired-subscriptions) - [キャンセルされたサブスクリプション](cancelled-subscriptions) --- # File: cancelled-subscriptions --- --- title: "サブスクリプションの自動更新キャンセル" description: "Adaptyの管理ツールを使って、キャンセルされたサブスクリプションを効率的に管理する方法を解説します。" --- 「サブスクリプションの自動更新キャンセル」チャートは、自動更新がオフに切り替えられた(ユーザーによってキャンセルされた)サブスクリプションの数を表示します。サブスクリプションの自動更新がオフになると、次の期間は自動的に更新されません。ただし、ユーザーは現在の期間が終了するまで、アプリのプレミアム機能へのアクセスを引き続き利用できます。 ## 計算方法 \{#calculation\} 「サブスクリプションの自動更新キャンセル」指標は、指定期間内に自動更新がオフに切り替えられたサブスクリプションをカウントします。ユーザーは現在の請求期間が終了するまでプレミアムアクセスを維持しますが、その後サブスクリプションは自動的に更新されません。 ## 利用可能なフィルターとグループ化 \{#available-filters-and-grouping\} :::link メイン記事: [アナリティクスの操作](controls-filters-grouping-compare-proceeds) ::: - ✅ フィルター: アトリビューション、オーディエンス、国、ペイウォール、A/B テスト、プレースメント、期間、セグメント、ストア、プロダクト、利用期間 - ✅ グループ化: プロダクト、国、ストア、ペイウォール、オーディエンス、プレースメント、利用期間、セグメント、アトリビューション ## 関連指標 \{#similar-metrics\} これらの指標を並べて比較するには、[指標比較表](metric-comparison-table#churn)をご覧ください。 - [アクティブなサブスクリプション](active-subscriptions) - [チャーン(期限切れ)サブスクリプション](churned-expired-subscriptions) - [新規サブスクリプション](reactivated-subscriptions) - [買い切り購入](non-subscriptions) --- # File: churned-expired-subscriptions --- --- title: "解約済み(期限切れ)サブスクリプション" description: "解約済みおよび期限切れサブスクリプションを管理して、ユーザー維持率を改善しましょう。" --- 解約済み(期限切れ)サブスクリプションチャートは、期限切れになったサブスクリプションの件数、つまりユーザーがアプリのプレミアム機能へのアクセスを失った件数を表示します。これは通常、ユーザーがサブスクリプション期間終了時に更新をやめた場合や、支払いの問題が発生した場合に起こります。失効理由でグループ化することで、自発的な解約と課金起因の解約を区別できます。 ## 計算方法 \{#calculation\} 解約済み(期限切れ)サブスクリプション指標は、対象期間中に期限切れとなったサブスクリプション件数をカウントします。これには、更新しなかったユーザーと、支払い問題によってサブスクリプションを失ったユーザーの両方が含まれます。 ## 利用可能なフィルターとグループ化 \{#available-filters-and-grouping\} :::link メイン記事: [アナリティクスのコントロール](controls-filters-grouping-compare-proceeds) ::: - ✅ フィルター条件: アトリビューション、オーディエンス、国、ペイウォール、A/B テスト、プレースメント、セグメント、ストア、プロダクト、期間。 - ✅ グループ化: 失効理由、プロダクト、国、ストア、ペイウォール、オーディエンス、プレースメント、期間、セグメント、アトリビューション。 ## 関連指標 \{#similar-metrics\} これらの指標を並べて比較するには、[指標比較テーブル](metric-comparison-table#churn)をご覧ください。 - [有効なサブスクリプション](active-subscriptions) - [新規サブスクリプション](reactivated-subscriptions) - [キャンセル済みサブスクリプション](cancelled-subscriptions) - [非サブスクリプション](non-subscriptions) --- # File: active-trials --- --- title: "アクティブトライアル" description: "Adapty アナリティクスを使ってアクティブなサブスクリプショントライアルを追跡・管理しましょう。" --- Adapty のアクティブトライアルチャートは、指定期間の終了時点でまだ有効な無料トライアルの数を表示します。「アクティブ」とは、まだ期限切れになっていないサブスクリプションを指します。つまり、ユーザーはアプリの有料機能に引き続きアクセスできる状態です。 ## 計算方法 \{#calculation\} アクティブトライアルの指標は、各期間の終了時点で期限切れになっていない無料トライアルをカウントします。自動更新をキャンセルしてもカウントからは除外されません。除外されるのは期限切れになった場合のみです。 例: 昨日のアクティブトライアルが 100 件、本日新たに 10 件追加、本日 5 件が期限切れ = 本日のアクティブトライアルは 105 件。 ## 利用可能なフィルターとグループ化 \{#available-filters-and-grouping\} :::link メイン記事: [アナリティクスの操作](controls-filters-grouping-compare-proceeds) ::: - ✅ フィルター対象: アトリビューション、オーディエンス、国、オファータイプ、オファー ID、オファー割引タイプ、ペイウォール、A/B テスト、プレースメント、セグメント、ストア、プロダクト、期間。 - ✅ グループ化: 期間、更新ステータス、プロダクト、国、ストア、ペイウォール、オーディエンス、プレースメント、期間、オファータイプ、オファー割引タイプ、オファー ID、セグメント、アトリビューション。 ## 関連指標 \{#similar-metrics\} これらの指標を並べて比較するには、[指標比較表](metric-comparison-table#subscribers-and-conversion)を参照してください。 - [新規トライアル](new-trials) - [トライアル更新キャンセル](trials-renewal-cancelled) - [期限切れトライアル](expired-churned-trials) --- # File: new-trials --- --- title: "新規トライアル" description: "新規サブスクリプショントライアルを管理し、トライアルから有料への転換率を最適化します。" --- 新規トライアルチャートは、選択した期間中に開始されたトライアルの数を表示します。広告キャンペーンやその他の獲得施策からのトライアル数を追跡するために使用してください。 ## 計算方法 \{#calculation\} 新規トライアル指標は、その期間が終了した時点でまだアクティブかどうかに関わらず、期間中に開始されたトライアルをカウントします。 たとえば、5月に50人のユーザーがトライアルを開始した場合、5月のデータポイントは50と表示されます。チャートを確認する時点で一部がすでに期限切れになっていたり有料に転換していたりしても、この数値は変わりません。 ## 利用可能なフィルターとグループ化 \{#available-filters-and-grouping\} :::link メイン記事:[アナリティクスの操作](controls-filters-grouping-compare-proceeds) ::: - ✅ フィルター対象:アトリビューション、オーディエンス、国、オファータイプ、オファーID、オファー割引タイプ、ペイウォール、A/B テスト、プレースメント、セグメント、ストア、プロダクト、期間。 - ✅ グループ化の基準:プロダクト、国、ストア、ペイウォール、オーディエンス、プレースメント、期間、オファータイプ、オファー割引タイプ、オファーID、セグメント、アトリビューション。 ## 関連指標 \{#similar-metrics\} これらの指標を並べて比較するには、[指標比較表](metric-comparison-table#subscribers-and-conversion)をご覧ください。 - [アクティブトライアル](active-trials) - [トライアル更新のキャンセル](trials-renewal-cancelled) - [期限切れトライアル](expired-churned-trials) --- # File: trials-renewal-cancelled --- --- title: "トライアル更新キャンセル" description: "Adaptyのインサイトでトライアルの更新、キャンセル、サブスクリプションフローを理解しましょう。" --- トライアル更新キャンセルチャートは、更新がキャンセルされたトライアル(ユーザーによるキャンセル)の件数を表示します。トライアルの更新が無効になると、そのトライアルは有料サブスクリプションに自動的に移行しなくなります。ただし、ユーザーは現在の期間が終了するまでアプリのプレミアム機能を引き続き利用できます。 ## 計算方法 \{#calculation\} トライアル更新キャンセルの指標は、当該期間中にユーザーによって自動更新がオフにされたトライアルの件数をカウントします。ユーザーはトライアル期間が終了するまでアクセスを維持できますが、そのトライアルは有料サブスクリプションに自動的に移行しません。 ## 利用可能なフィルターとグルーピング \{#available-filters-and-grouping\} :::link 関連記事:[アナリティクスの操作](controls-filters-grouping-compare-proceeds) ::: - ✅ フィルター項目:アトリビューション、オーディエンス、国、ペイウォール、A/B テスト、プレースメント、セグメント、ストア、プロダクト、期間 - ✅ グループ項目:プロダクト、国、ストア、ペイウォール、オーディエンス、プレースメント、期間、セグメント、アトリビューション ## 関連指標 \{#similar-metrics\} これらの指標を並べて比較する場合は、[指標比較表](metric-comparison-table#churn)をご覧ください。 - [新規トライアル](new-trials) - [アクティブトライアル](active-trials) - [期限切れトライアル](expired-churned-trials) --- # File: expired-churned-trials --- --- title: "期限切れ(チャーン)トライアル" description: "Adapty アナリティクスで期限切れ・チャーンしたトライアルを効果的に管理しましょう。" --- 期限切れ(チャーン)トライアルチャートは、期限切れとなりユーザーがアプリのプレミアム機能にアクセスできなくなったトライアルの件数を表示します。多くの場合、これはユーザーがアプリへの課金をやめた場合や、請求の問題が発生した場合に起こります。 ## 計算方法 \{#calculation\} 期限切れトライアルの指標は、対象期間中に終了したトライアル(ユーザーがプレミアム機能へのアクセスを失ったもの)をカウントします。これには、自発的に継続しなかったユーザーと、請求の問題により継続に失敗したユーザーの両方が含まれます。 **Expiration reason** でグループ化すると、自発的なチャーンと請求起因のチャーンを分けて確認できます。 ## 利用可能なフィルターとグループ化 \{#available-filters-and-grouping\} :::link メイン記事:[アナリティクスのコントロール](controls-filters-grouping-compare-proceeds) ::: - ✅ フィルター:アトリビューション、オーディエンス、国、ペイウォール、A/B テスト、プレースメント、セグメント、ストア、プロダクト、期間 - ✅ グループ化:有効期限の理由、プロダクト、国、ストア、ペイウォール、オーディエンス、プレースメント、期間、セグメント、アトリビューション ## 関連指標 \{#similar-metrics\} これらの指標を並べて比較するには、[指標比較テーブル](metric-comparison-table#churn)を参照してください。 - [新規トライアル](new-trials) - [アクティブトライアル](active-trials) - [トライアル更新キャンセル](trials-renewal-cancelled) --- # File: refund-events --- --- title: "返金イベント" description: "Adaptyで返金イベントを管理し、チャーンを抑制して収益を最適化しましょう。" --- 返金イベントチャートは、返金された購入件数とサブスクリプション件数を表示します。Adaptyは各返金イベントを、サブスクリプションの開始日ではなく、返金が発生した日付に紐づけます。 ## 計算方法 \{#calculation\} Adaptyは、選択した期間内に返金されたすべての購入またはサブスクリプションをカウントします。各返金は、サブスクリプションが開始された日ではなく、返金が発生した日付に紐づけられます。トライアルの返金は、トライアルが収益を生まないため、除外されます。 ## 指標ごとの返金の扱い方 \{#how-metrics-handle-refunds\} 指標によって返金の扱い方は異なります。同じ返金イベントでも、あるチャートでは即座に減少し、別のチャートでは遡及的に(過去の期間の値を変更して)減少し、また別のチャートにはまったく影響しない場合があります。以下の表に、各指標のルールをまとめています。 | 指標 | 返金の適用 | 帰属日 | マイナスになる可能性 | 備考 | | --- | --- | --- | --- | --- | | [収益](revenue) | あり | 返金日(元の購入日ではない) | あり(返金が新規収益を上回る日) | 収益 = 総トランザクション − 返金 | | [MRR](mrr) | あり(遡及的) | サブスクリプションがアクティブだったすべての期間から削除 | なし | 返金後に過去の期間の値が減少する場合があります。 | | [ARR](arr) | あり(遡及的) | MRRと同様 | なし | 返金後に過去の期間の値が減少する場合があります。 | | [ARPU](arpu) | あり | 返金日 | あり(返金が多い期間) | 返金は収益の分子から差し引かれます。 | | [ARPPU](arppu) | あり(分子のみ) | 返金日 | あり(返金が多い期間) | 返金は収益の分子から差し引かれます。返金済みユーザーは支払いユーザーの分母に残るため、返金が多いとARPPUは予想以上に下がります。 | | [アクティブサブスクリプション](active-subscriptions) | あり(遡及的) | カウントからサブスクリプションが削除される | なし | | | [新規サブスクリプション](reactivated-subscriptions) | **なし** | — | なし | 後に返金されたサブスクリプションもカウントに含まれます。正味の影響については[返金イベント](refund-events)と比較してください。 | | [返金金額](refund-money) / [返金イベント](refund-events) | 返金**そのもの**がデータ | 返金日 | なし(常に ≥ 0) | | | [リテンション](analytics-retention) | **なし** | — | なし | 返金済みユーザーはリテンション曲線にカウントされたままになります。そのため、同じコホートで[アクティブサブスクリプション](active-subscriptions)や[収益](revenue)よりリテンションが高く見える場合があります。 | | [コホート収益](analytics-cohorts) | あり(累積) | 返金日 | なし(累積の差し引きによりコホート収益がマイナスになることはない) | 返金はコホート収益から発生時点で差し引かれます。 | | [ペイウォール指標](paywall-metrics) / [A/B テスト指標](results-and-metrics)(カウント) | **なし** | — | なし | これらのページのサブスクライバー数、有料サブスクライバー数、ARPPUのカウントは返金を控除しません。 | | GCS / S3 エクスポート | 返金は独自のイベント行として記録 | `event_datetime` = 返金タイムスタンプ | 集計時にネット列がマイナスになる場合あり | 返金行には `is_refund = true`(S3/GCS)またはイベントタイプ `subscription_refunded`(Webhook)が含まれます。 | ### マイナス値 \{#negative-values\} 集計ビュー(収益チャート、エクスポートのカスタム分析)では、特定の期間やグループ内の返金が同じバケット内の新規収益を超えると、指標がマイナス値を示すことがあります。これはバグではなく、設計通りの計算結果です。 例:ある国で火曜日に新規購入がなかったものの、過去の購入に対する$100の返金がその日に処理された場合、その国の火曜日の収益は −$100 と表示されます。 ## 利用可能なフィルターとグループ化 \{#available-filters-and-grouping\} :::link メイン記事:[アナリティクスコントロール](controls-filters-grouping-compare-proceeds) ::: - ✅ フィルター項目:アトリビューション、オーディエンス、返金理由、国、オファータイプ、オファーID、オファー割引タイプ、ペイウォール、A/B テスト、プレースメント、期間、セグメント、ストア、プロダクト、期間。 - ✅ グループ化項目:返金理由、プロダクト、国、ストア、ペイウォール、オーディエンス、プレースメント、期間、オファータイプ、オファー割引タイプ、オファーID、セグメント、アトリビューション。 ## 関連指標 \{#similar-metrics\} これらの指標を並べて比較するには、[指標比較表](metric-comparison-table#revenue)をご覧ください。 - [返金金額](refund-money) - [請求問題](billing-issue) - [グレース期間](grace-period) --- # File: refund-money --- --- title: "返金" description: "Adapty で収益を失わずにサブスクリプションの返金を処理する方法を学びましょう。" --- 「返金金額」チャートは、選択した期間中に返金された金額を表示します。Adapty は各返金イベントを処理された日付に紐付けるため、その期間の収益がその分だけ減少します。 ## 計算方法 \{#calculation\} Adapty は収益を生成するトランザクション(新規有料サブスクリプション、更新、買い切り購入)のみをカウントします。収益が発生せず返金もできない無料トライアルは除外されます。各返金金額は処理された日付に紐付けられるため、収益の減少はその同じ期間に反映されます。 :::info 返金金額は、ストアの手数料が差し引かれる前の金額で計算されます。 ::: ## 利用可能なフィルターとグループ化 \{#available-filters-and-grouping\} :::link メイン記事: [アナリティクスのコントロール](controls-filters-grouping-compare-proceeds) ::: - ✅ フィルター対象: アトリビューション、オーディエンス、返金理由、国、オファータイプ、オファーID、オファー割引タイプ、ペイウォール、A/B テスト、プレースメント、期間、セグメント、ストア、プロダクト、期間。 - ✅ グループ化: 返金理由、プロダクト、国、ストア、ペイウォール、オーディエンス、プレースメント、期間、オファータイプ、オファー割引タイプ、オファーID、セグメント、アトリビューション。 ## 返金リクエストの管理 \{#refund-request-management\} 返金セーバーは、Adapty ユーザーが Apple の App Store からの返金リクエストを自動化によってより効率的に処理するためのツールです。プロセスを効率化することで時間を節約し、収益の損失を減らします。リアルタイム通知と実用的なインサイトにより、Apple のガイドラインに準拠しながら返金リクエストに対応しやすくなります。 詳しくは [返金セーバー](refund-saver) をご覧ください。 ## 関連指標 \{#similar-metrics\} これらの指標を並べて比較するには、[指標比較表](metric-comparison-table#revenue) をご覧ください。 - [返金イベント](refund-events) - [請求の問題](billing-issue) - [グレース期間](grace-period) --- # File: grace-period --- --- title: "グレース期間" description: "サブスクリプションのグレース期間の仕組みを理解し、ユーザーリテンションを向上させましょう。" --- グレース期間チャートは、[請求の問題](billing-issue)によってグレース期間の状態に入ったサブスクリプションの数を表示します。この期間中、ストアがサブスクライバーへの支払い請求を試みる間もサブスクリプションはアクティブな状態を維持します。グレース期間が終了するまでに支払いが正常に受け取られなかった場合、サブスクリプションは請求の問題の状態に移行します。 ## 計算方法 \{#calculation\} グレース期間の指標は、選択した期間中にグレース期間に入ったサブスクリプションの数をカウントします。グレース期間は、サブスクリプションの更新支払いが失敗したときに開始され、週次サブスクリプションの場合は最大6日間、その他の請求期間の場合は最大16日間続きます。この期間内に支払いが完了した場合、サブスクリプションは通常通り継続されます。支払いが完了しなかった場合、サブスクリプションは[請求の問題](billing-issue)の状態に移行します。 ## 利用可能なフィルターとグループ化 \{#available-filters-and-grouping\} :::link メイン記事:[アナリティクスのコントロール](controls-filters-grouping-compare-proceeds) ::: - ✅ フィルター対象:アトリビューション、オーディエンス、国、ペイウォール、A/B テスト、プレースメント、期間、セグメント、ストア、プロダクト、デュレーション - ✅ グループ化:プロダクト、国、ストア、ペイウォール、オーディエンス、プレースメント、デュレーション、セグメント、アトリビューション ## 関連指標 \{#similar-metrics\} これらの指標を並べて比較するには、[指標比較表](metric-comparison-table#billing-issues-and-revenue-recovery)をご覧ください。 - [返金金額](refund-money) - [返金イベント](refund-events) - [請求の問題](billing-issue) --- # File: grace-period-converted --- --- title: "グレース期間からの復旧件数" description: "グレース期間に入り、期間終了前に更新されたサブスクリプションの件数を追跡します。" --- **Grace period converted** チャートは、[グレース期間](grace-period)の状態に入り、期間終了前に正常に更新されたサブスクリプションの件数を表示します。 ### 計算方法 \{#calculation\} Grace period converted チャートは、グレース期間中のユーザーにおけるサブスクリプション更新の日次件数を表示します。 グレース期間は、支払い失敗により請求問題の状態に入ったときに始まり、一定の期間(週次サブスクリプションは6日間、その他のサブスクリプションはすべて16日間)が経過するか、支払いが正常に受領された時点で終了します。このチャートは、グレース期間機能の有効性を把握するためのインサイトを提供し、支払い処理やサブスクリプション管理における潜在的な問題の特定にも役立ちます。 ### 利用可能なフィルター \{#available-filters\} :::link 関連記事:[アナリティクスの操作](controls-filters-grouping-compare-proceeds) ::: - ✅ フィルター対象:アトリビューション、オーディエンス、返金理由、国、オファータイプ、オファーID、オファー割引タイプ、ペイウォール、A/B テスト、プレースメント、期間、セグメント、ストア、プロダクト、期間長。 - ✅ グループ化:プロダクト、国、ストア、ペイウォール、オーディエンス、プレースメント、期間長、セグメント、アトリビューション。 ### Grace period converted チャートの使い方 \{#grace-period-converted-chart-usage\} このチャートを使って、グレース期間機能が支払い問題のあるサブスクリプションをどれほど効果的に回復しているかを追跡しましょう。時系列での復旧トレンドをモニタリングすることで、支払い解決のパターンを把握し、グレース期間中の支払い更新フローやコミュニケーション施策の変更が与える影響を評価できます。 ### 関連指標 \{#similar-metrics\} - [請求問題](billing-issue) - [請求問題からの復旧件数](billing-issue-converted) - [請求問題からの復旧収益](billing-issue-converted-revenue) - [グレース期間](grace-period) - [グレース期間からの復旧収益](grace-period-converted-revenue) - [返金額](refund-money) - [返金イベント](refund-events) --- # File: grace-period-converted-revenue --- --- title: "グレース期間コンバージョン収益" description: "グレース期間コンバージョンの総収益を追跡します。" --- **Grace period converted revenue** チャートは、[グレース期間コンバージョン](grace-period-converted)から生み出された収益を表示します。これは、[グレース期間](grace-period)状態に入り、期間が終了する前に正常に更新されたサブスクリプションの収益です。 ### 計算方法 \{#calculation\} Grace period converted revenue チャートは、グレース期間中のユーザーのサブスクリプション更新によって生み出された日次収益を表示します。 グレース期間は、支払い失敗によるサブスクリプションの請求問題状態への移行時に開始し、指定された期間(週次サブスクリプションは6日間、その他すべてのサブスクリプションは16日間)が経過するか、支払いが正常に受領されると終了します。このチャートは、グレース期間機能の効果についての洞察を提供し、支払い処理またはサブスクリプション管理における潜在的な問題を特定するのに役立ちます。 ### 利用可能なフィルター \{#available-filters\} :::link メイン記事: [アナリティクスのコントロール](controls-filters-grouping-compare-proceeds) ::: - ✅ フィルター対象: アトリビューション、オーディエンス、返金理由、国、オファータイプ、オファーID、オファー割引タイプ、ペイウォール、A/B テスト、プレースメント、期間、セグメント、ストア、プロダクト、期間。 - ✅ グループ化: プロダクト、国、ストア、ペイウォール、オーディエンス、プレースメント、期間、セグメント、アトリビューション。 ### Grace period converted revenue チャートの使い方 \{#grace-period-converted-revenue-chart-usage\} このチャートを使用して、支払い問題のあるサブスクリプションから回収した収益を追跡することで、グレース期間機能の財務的影響を測定します。これにより、グレース期間戦略の効果を定量化し、グレース期間関連の機能やコミュニケーションを実装した際の投資対効果を評価できます。 ### 関連指標 \{#similar-metrics\} - [請求問題](billing-issue) - [請求問題コンバージョン](billing-issue-converted) - [請求問題コンバージョン収益](billing-issue-converted-revenue) - [グレース期間](grace-period) - [グレース期間コンバージョン](grace-period-converted) - [返金額](refund-money) - [返金イベント](refund-events) --- # File: billing-issue --- --- title: "課金エラー" description: "Adaptyのサポートツールを使用してサブスクリプションの課金エラーを解決します。" --- 課金エラーチャートは、課金エラー状態に入ったサブスクリプションの数を表示します。この状態は通常、AppleやGoogleなどのストアが何らかの理由でサブスクライバーから支払いを受け取れない場合に発生します。クレジットカードの有効期限切れや残高不足などが原因として考えられます。 ## 計算方法 \{#calculation\} 課金エラー指標は、指定期間内に課金エラー状態に入ったサブスクリプションの数をカウントします。サブスクリプションがこの状態に入るのは、ストア(AppleまたはGoogle)が更新支払いを処理できない場合です。主な原因としては、クレジットカードの有効期限切れや残高不足が挙げられます。課金エラー状態の間、サブスクリプションはアクティブではありません。 [グレース期間](grace-period)機能が有効になっている場合、サブスクリプションはグレース期間が支払いなしで終了した後にのみ課金エラー状態に入ります。 ## 利用可能なフィルターとグループ化 \{#available-filters-and-grouping\} :::link メインの記事:[アナリティクスのコントロール](controls-filters-grouping-compare-proceeds) ::: - ✅ フィルター: アトリビューション、オーディエンス、国、ペイウォール、A/B テスト、プレースメント、期間、セグメント、ストア、プロダクト、デュレーション。 - ✅ グループ化: プロダクト、国、ストア、ペイウォール、オーディエンス、プレースメント、デュレーション、セグメント、アトリビューション。 ## 関連指標 \{#similar-metrics\} これらの指標を並べて比較するには、[指標比較表](metric-comparison-table#billing-issues-and-revenue-recovery)をご参照ください。 - [課金エラーからの回復](billing-issue-converted) - [課金エラーからの回復による収益](billing-issue-converted-revenue) - [返金額](refund-money) - [返金イベント](refund-events) - [グレース期間](grace-period) - [グレース期間からの回復](grace-period-converted) - [グレース期間からの回復による収益](grace-period-converted-revenue) --- # File: billing-issue-converted --- --- title: "請求問題の解決" description: "請求サイクルが終了する前に解決された請求問題の件数を追跡します。" --- Billing issue converted チャートは、[Billing Issue(請求問題)](billing-issue)状態に入り、請求サイクルが終了する前に更新されたサブスクリプションの日次件数を表示します。 ### 計算方法 \{#calculation\} Billing issue converted チャートは、現在の請求サイクル内で[Billing Issue](billing-issue)状態に入り、当日に更新されたサブスクリプションの件数を表示します。 サブスクリプションは、クレジットカードの有効期限切れや残高不足など、何らかの理由でストア(Apple、Googleなど)がサブスクライバーへの請求処理に失敗した場合に、Billing Issue状態に入ります。Billing Issue状態中はサブスクリプションがアクティブとは見なされず、ストアの設定でグレース期間機能が有効になっている場合、グレース期間が終了した後にのみBilling Issue状態へ移行します。 ### 利用可能なフィルター \{#available-filters\} :::link メイン記事:[アナリティクスのコントロール](controls-filters-grouping-compare-proceeds) ::: - ✅ フィルター対象:アトリビューション、オーディエンス、返金理由、国、オファータイプ、オファーID、オファー割引タイプ、ペイウォール、A/B テスト、プレースメント、期間、セグメント、ストア、プロダクト、期間。 - ✅ グループ化:プロダクト、国、ストア、ペイウォール、オーディエンス、プレースメント、期間、セグメント、アトリビューション。 ### Billing issue converted チャートの活用方法 \{#billing-issue-converted-chart-usage\} グレース期間終了後の請求サイクル内で、請求問題がどの程度効果的に解決されているかを追跡するためにこのチャートを活用してください。時系列での解決傾向を監視することで、支払い回収のパターンを把握し、請求問題発生時の支払い再試行ロジックやコミュニケーション戦略の変更による効果を評価できます。 ### 関連指標 \{#similar-metrics\} - [Billing issue(請求問題)](billing-issue) - [Billing issue converted revenue(請求問題解決の収益)](billing-issue-converted-revenue) - [Refund money(返金額)](refund-money) - [Refund events(返金イベント)](refund-events) - [Grace period(グレース期間)](grace-period) - [Grace period converted(グレース期間の解決)](grace-period-converted) - [Grace period converted revenue(グレース期間解決の収益)](grace-period-converted-revenue) --- # File: billing-issue-converted-revenue --- --- title: "請求問題からの回収収益" description: "Adaptyのサポートツールを使用してサブスクリプションの請求問題を解決する方法。" --- **Billing issue converted revenue** チャートは、[請求問題からの回収](billing-issue-converted)による収益、つまり[請求問題(Billing Issue)](billing-issue)状態に入り、請求サイクルの終了前に更新されたサブスクリプションの収益を表示します。 ### 計算方法 \{#calculation\} **Billing issue converted revenue** チャートは、現在の請求サイクルで[請求問題(Billing Issue)](billing-issue)状態に入り、当日に更新されたサブスクリプションの日次収益を表示します。 サブスクリプションが請求問題状態になるのは、有効期限切れのクレジットカードや残高不足などの理由により、ストア(Apple、Googleなど)がユーザーへの支払い処理を完了できない場合です。請求問題状態の間、サブスクリプションはアクティブとはみなされません。ストアの設定でグレース期間機能が有効になっている場合、グレース期間が終了した後にのみ請求問題状態へ移行します。 ### 利用可能なフィルター \{#available-filters\} :::link メイン記事:[アナリティクスの操作](controls-filters-grouping-compare-proceeds) ::: - ✅ フィルター対象:アトリビューション、オーディエンス、返金理由、国、オファータイプ、オファーID、オファー割引タイプ、ペイウォール、A/B テスト、プレースメント、期間、セグメント、ストア、プロダクト、利用期間 - ✅ グループ化:プロダクト、国、ストア、ペイウォール、オーディエンス、プレースメント、利用期間、セグメント、アトリビューション ### 請求問題からの回収収益チャートの活用方法 \{#billing-issue-converted-revenue-chart-usage\} このチャートを使用して、グレース期間終了後にサブスクリプションから回収された収益を追跡し、解決済みの請求問題による財務的影響を測定しましょう。請求問題の回収戦略の効果を数値化し、請求リトライの仕組みやターゲットユーザーへのコミュニケーション施策の投資対効果を評価するのに役立ちます。 ### 関連指標 \{#similar-metrics\} - [請求問題(Billing issue)](billing-issue) - [請求問題からの回収(Billing issue converted)](billing-issue-converted) - [返金金額(Refund money)](refund-money) - [返金イベント(Refund events)](refund-events) - [グレース期間(Grace period)](grace-period) - [グレース期間からの回収(Grace period converted)](grace-period-converted) - [グレース期間からの回収収益(Grace period converted revenue)](grace-period-converted-revenue) --- # File: ltv --- --- title: "Lifetime Value (LTV)" description: "Adapty で Lifetime Value (LTV) を計算・最適化する方法を学びましょう。" --- Realized LTV(ライフタイムバリュー)は、課金ユーザーコホートが実際に生み出した収益から返金を差し引いた金額を、そのコホートの課金ユーザー数で割ったものです。つまり、このチャートを見ると、課金ユーザー1人あたりの平均収益がわかります。 Adapty の LTV チャートは、アプリの収益とユーザー行動に関する次のような重要な問いに答えるよう設計されています。 1. 各コホートはアプリの利用期間全体でどれだけの収益をもたらすか? 2. コホートが元を取るのはいつの時点か? 3. LTV の高い優良ユーザーを獲得するために、マーケティングや獲得コストをどう最適化できるか? 4. 新規ユーザーの獲得コストを回収するまでにどれくらいかかるか? LTV チャートは、SDK とアプリ内イベントを通じて収集したデータをもとに動作します。 この情報を活用すると、サブスクリプションのパフォーマンスや、特定期間に購読者から得られる収益を把握できます。また、サブスクリプションの提供内容・広告費・ユーザー獲得戦略に関してデータに基づいた意思決定が可能です。さらに、フィルター機能を使えば国・アトリビューション・その他の変数でデータをセグメント化できるため、ユーザーベースをより細かく理解できます。 ### 更新回数別 LTV \{#ltv-by-renewals\} **更新回数別 LTV** ビューは、サブスクリプション期間(P)に関するデータを表示し、特にユーザーが初めて支払いを行ったタイミングを捉えます。週次サブスクリプションの場合、これは次の週次サブスクリプション期間に該当します。 ### 日数別 LTV \{#ltv-by-days\} **日数別 LTV** ビューは、日次・週次・月次の間隔でデータを整理・フィルタリングします。特定の日・週・月にアプリをインストールしたすべてのユーザーが生み出した総収益を、同期間の課金ユーザー数で割った値を提供します。このビューは収益の追跡に役立ち、時間の経過によるユーザー行動を総合的に把握できます。 ### コホートの長さと期間 \{#cohort-length-and-time-frame\} --- no_index: true --- テーブルの表示内容は、2つの時間設定で決まります。 - **Time frame** — 対象となる日付の範囲です。テーブル上部のカレンダーで設定します。 - **Cohort length** — 各行の粒度です。日・週・月・四半期・年から選べます。月単位にすると、各行がインストール1か月分に対応します。 この2つは独立して動作します。たとえば、Time frame を6か月、Cohort length を月単位にすると6行のテーブルになります。Time frame を1年、Cohort length を週単位にすると52行になります。 ### 計算方法 \{#calculation\} Realized LTV は、各ユーザーコホートから得られた総収益から返金を差し引いて計算されます。 _日次/週次/月次の LTV = 該当日/週/月にアプリをインストールしたすべての課金ユーザーから得た収益 ÷ 該当日/週/月にアプリをインストールした課金ユーザー数_ LTV の計算には、アップグレード・ダウングレード・再アクティベーション(ユーザーがサブスクリプションプランや価格を変更した場合など)が含まれます。初回サブスクリプションの収益と、更新後のプランに基づくその後の更新収益が考慮されます。 ### グルーピングとフィルタリング \{#available-grouping-and-filtering\} :::link メイン記事:[アナリティクスのコントロール](controls-filters-grouping-compare-proceeds) ::: フィルターとグルーピングはどちらも、LTV チャートの更新回数別ビューと日数別ビューの両方に適用でき、特定のコホートを詳しく調べ、時間の経過に伴う行動を把握できます。 - ✅ フィルター項目:アトリビューション、オーディエンス、国、ペイウォール、A/B テスト、プレースメント、セグメント、ストア、プロダクト、期間。 - ✅ グループ項目:プロダクト、国、ストア、期間、セグメント、コホート(日次、週次、月次、年次)。 Adapty の Realized LTV チャートは、ユーザー行動に関する有益なインサイトを得て、マーケティング戦略を最適化し、収益パフォーマンスを追跡し、顧客の長期的な価値を最大化するためのデータドリブンな意思決定を支援します。 --- # File: analytics-cohorts --- --- title: "コホート分析" description: "Adaptyのアナリティクスコホートを使って、ユーザーエンゲージメントとサブスクリプションのトレンドを把握しましょう。" --- Adaptyのコホートは、次のような重要な問いに答えるために設計されています。 1. コホートが元を取るのは何日目か? 2. 特定のコホートからアプリはどれだけの収益を得られるか? 3. 有料ユーザーを獲得するためにどれだけの費用をかけられるか? 4. 広告費を回収するまでにどれくらいかかるか? コホートは、SDKやストア通知を通じて収集されたアプリデータを使用するため、追加の設定は不要です。 ## 更新回数別または日数別のコホート \{#cohorts-by-renewals-or-by-days\} コホートは更新回数別または日数別で分析できます。この切り替えによってカラムの見出しが変わり、それに伴い分析のアプローチも変わります。 **日数別**のトラッキングは、予算管理や支払いタイムラインの把握に役立ちます。これは消耗型アイテムや買い切り購入といった非サブスクリプション型プロダクトの追跡に特に有用です。このモードでは、テーブルのセルの青色が行の中央付近に集中する傾向があります。これには2つの理由があります。まず、日数別でコホートを見ると、短期間プロダクトに関連する支払いを早期に確認できる一方、更新回数別では月次・年次の更新と一緒にグループ化されます。次に、遅延支払いが分布パターンに影響を与えるため、一部のユーザーが予定より遅く支払う場合があります。 一方、**更新回数別**のトラッキングは、日付を考慮せずに、支払いから支払いへのコホートのリテンションとチャーンを示します。つまり、何らかの遅延(数ヶ月になる場合もあります)があって支払いを行った遅延ユーザーは、対応するサブスクリプション期間の数に加算されます。このアプローチはカレンダー上の収益状況を反映しませんが、コホートのリテンションとチャーンを分析し、行動からインサイトを得るには非常に便利です。 用途に合ったモードを選択するか、より多くの結論やアイデアを得るために両方を活用してください。 ## Adaptyがコホートを構築する仕組み \{#how-adapty-builds-cohorts\} 更新回数別コホートを例に、テーブルの構成を見ていきましょう。コホートの構築には、アプリのインストール数とトランザクション(購入)の2つの指標を使用します。コホートの各行は、1日から1年までの特定の時間間隔を表します。各行は、その期間にアプリをインストールし、サブスクリプションを有効化するか、永続アクセスまたは非サブスクリプション型プロダクトを購入したユーザー数から始まります。 行の次以降のカラムは、その期間にサブスクリプションを更新したユーザー数を示します。M3は「3ヶ月目」を意味し、その時点までに3回連続で更新していることを表します。W7は7週目、Y2は2年目を意味します。コホートにP2が表示される場合があります。Pはサブスクリプションの「期間(Period)」を意味し、更新期間が異なる複数のプロダクトが同じコホートに混在しているときに、W/M/Yの代わりに表示されます。 グラデーションカラーを使ってコホート値の差を強調しています。数値が大きいほど、より濃い色で表示されます。 以下の画像に、典型的なコホートの例を示します。 1. このコホートは週次プロダクトのデータのみを表示しています(マーク #1)。 2. 手数料を除外せず、収益を絶対値で表示しています(マーク #2)。 3. 対象期間は過去6ヶ月で、コホート長は1ヶ月です(マーク #3)。 4. **Total** 行(マーク #4)は各期間の累計値を表示します。**Total** 行の最初のセルの$442Kは、タイムフレーム終了までのすべての月(11月、12月など)の初回期間(サブスクリプション有効化)収益を累積した値です。TotalセルはCは全期間にアプリをインストールした顧客数を示します。 5. Nov 2023行の最初のカラム(マーク #5)は、2023年11月にアプリをインストールした顧客の初回期間(サブスクリプション有効化)収益である$37.7Kを示しています。2023年11月にアプリをインストールした顧客数95,129人は、ヘッダーカラムに表示されています。 Nov 2023行の2番目のカラムは、2023年11月にアプリをインストールした顧客の2週目(2週目まで更新されたサブスクリプション)収益である$8,77Kを示しています。 6. テーブルには、合計収益、ARPU、ARPPU、ARPAS(マーク #6)が表示されます。これらについてはこの記事の後半で詳しく説明します。 7. テーブル右側の **Columns** ドロップダウンフィールド(マーク #7)でカラムを設定できます。 8. テーブル右上(マーク #8)には、特定のコホート分析に対してストアの手数料と税金の計算を設定するドロップダウンフィールドもあります。Adaptyがストアの手数料と税金を計算する方法については[こちらの記事](controls-filters-grouping-compare-proceeds#display-gross-or-net-revenue)をご覧ください。対応するオプションをドロップダウンから選択すると、収益データがそれに基づいて再計算されます。 9. テーブルの右側には、予測収益(Predicted Revenue)と予測LTV(Predicted LTV)が表示されます(マーク #9)。**Predicted Revenue** フィールドは、特定の期間内にサブスクライバーコホートが生み出すと見込まれる総収益を推定し、**Predicted LTV** フィールドはコホート内の各ユーザーの期待値を表します。 コホート内の任意のセルにカーソルを合わせると、その期間の詳細な指標を確認できます。 背景に斜線が入ったセルは、まだ完了していない期間を表しており、値が増加する可能性があります。 ## コホート長とタイムフレーム \{#cohort-length-and-time-frame\} --- no_index: true --- テーブルの表示内容は、2つの時間設定で決まります。 - **Time frame** — 対象となる日付の範囲です。テーブル上部のカレンダーで設定します。 - **Cohort length** — 各行の粒度です。日・週・月・四半期・年から選べます。月単位にすると、各行がインストール1か月分に対応します。 この2つは独立して動作します。たとえば、Time frame を6か月、Cohort length を月単位にすると6行のテーブルになります。Time frame を1年、Cohort length を週単位にすると52行になります。 ## フィルター、指標、コホートセグメント、CSV エクスポート \{#filters-metrics-cohort-segments-and-export-in-csv\} :::link メイン記事:[アナリティクスコントロール](controls-filters-grouping-compare-proceeds) ::: デフォルトでは、Adaptyはすべての購入データを使ってコホートを構築します。プロダクトの期間、特定のプロダクト、国、ストア、ペイウォール、セグメント、アトリビューションデータでフィルタリングできます。 コントロールパネルの右側には、コホートデータをCSVにエクスポートするボタンがあります。エクスポートしたファイルはExcelやGoogle Sheetsで開いたり、独自の分析システムにインポートしたりできます。 コホートで表示できる指標は6つあります:Subscriptions、Payers、Revenue、ARPU、ARPPU、ARPASです。これらは絶対値として表示することも、コホート開始時からの相対的な変化として表示することもできます。 ## サブスクリプション、支払者、総収益、ARPU、ARPPU、ARPAS \{#subscriptions-payers-total-revenue-arpu-arppu-and-arpas\} **Subscriptions** は、選択した期間内にコホートが行ったアクティブなサブスクリプション、永続アクセス購入、非サブスクリプション購入の総数です。この指標を監視することで、顧客の行動とオファーの効果を把握できます。これにより、プロダクト戦略の改善、マーケティング施策の最適化、収益フローの効率化が可能になります。 **Payers** は、コホート内で購入を行ったユーザーのユニーク総数です。収益に貢献するユニークユーザー数の把握に役立ちます。非サブスクリプション型購入が多いアプリでは、この指標によってプロダクトオファーの真のリーチが明確になり、幅広いユーザー層が購入しているのか、少数のリピーターが収益を牽引しているのかを確認できます。支払者数を把握することで、顧客エンゲージメントの評価、ターゲットマーケティングの計画、収益戦略の最適化に役立てられます。 **Total revenue** は、選択した期間(2022年11月25日〜2023年5月24日)内にコホートが積み上げた収益です。特定のコホートからどれだけの収益を得たかを把握し、ROASを計算するのに役立ちます。たとえば、2022年9月の広告費が$10,000で、2022年9月コホートの総収益が$30,000であれば、ROAS=3:1となります。 **ARPU** はユーザー1人あたりの平均収益です。総収益÷ユニークユーザー数で計算されます。$60,000の収益÷5,000ユーザー=$12 ARPUとなります。この値をインストール単価(CPI)と比較することで、マーケティングキャンペーンの効果を把握できます。 **ARPPU** は有料ユーザー1人あたりの平均収益です。総収益÷ユニーク有料ユーザー数で計算されます。$60,000の収益÷1,000人の有料ユーザー=$60 ARPPUとなります。有料顧客1人が平均的にどれだけの収益をもたらすかを把握するのに役立ちます。 **ARPAS** はアクティブなサブスクライバー1人あたりの平均収益です。総収益÷アクティブサブスクライバー数で計算されます。ここでのサブスクライバーとは、トライアル期間またはサブスクリプションを有効化したユーザーを指します。$60,000の収益÷1,500人のサブスクライバー=$40 ARPASとなります。 ## 手数料と税金 \{#commission-fees-and-taxes\} コホートの収益計算において重要な要素の一つが、ストアの手数料と税金(ユーザーのストアアカウントの国によって異なる場合があります)の算入です。Adaptyは現在、コホート分析においてApp StoreおよびPlay Store両方の手数料と税金の計算をサポートしています。 Adaptyがアナリティクスで税金と手数料を計算する方法の詳細については、[ドキュメント](controls-filters-grouping-compare-proceeds#display-gross-or-net-revenue)をご参照ください。 ## 売上と手取り収益 \{#revenue-vs-proceeds\} 売上(Revenue)と手取り収益(Proceeds)はどちらもお金に関する指標です。Revenueは売上総額、Proceedsは純収益と考えられます。RevenueはApp Store / Play Storeの手数料を考慮しませんが、Proceedsは考慮します。そのため、ProceedsはRevenueより常に少なくなります。 実際に差し引かれる手数料は、[Small Business Program](app-store-small-business-program)(15%)への適格性、長期サブスクリプションの優遇レート(1年以上更新後は15%)、国別レート、標準レート(最大30%)など、複数の要因によって異なります。 Adaptyは顧客が行うすべてのトランザクションに対して適用される手数料率を自動的に判定し、それに基づいてProceedsを計算します。手数料率の決定方法の詳細については、[ストアの手数料と税金](controls-filters-grouping-compare-proceeds#display-gross-or-net-revenue)のドキュメントをご参照ください。 ## 返金の処理 \{#refund-handling\} 返金はコホートの収益から累積的に差し引かれます。差し引きは元の購入日ではなく、返金日に行われます。 指標全体での比較については、[指標が返金を処理する方法](refund-events#how-metrics-handle-refunds)をご参照ください。 ## 予測:収益とLTV \{#prediction-revenue-and-ltv\} **Predicted revenue(予測収益)** は、コホート作成後の選択した期間内に有料サブスクライバーのコホートが生み出すと予測される総収益の推定値です。コホートの予測LTVに、コホート内の予測有料ユーザー数を掛けて計算されます。たとえば、予測LTVが$50で、コホート内の有料ユーザーが100人の場合、Predicted Revenueは$5,000となります。 **Predicted LTV(予測LTV)** は、有料サブスクライバー1人あたりの推定生涯価値であり、コホート作成後の選択した期間内に各有料サブスクライバーが生み出すと期待される平均収益を表します。 これらの予測は、過去のコホートリテンションパターンに基づいており、十分な履歴データがある場合はアプリ自身のデータを使用し、不足している場合はアプリ間の平均値を使用します。Adaptyの予測モデルの詳細なドキュメントについては、[予測ドキュメント](predicted-ltv-and-revenue)をご参照ください。 Adaptyのコホートは、アプリ内のユーザー行動と財務パフォーマンスについての詳細なインサイトを提供します。更新回数別または日数別でコホートを分析することで、コホートが収益化するタイミングの把握、収益の追跡、ユーザー1人あたりの平均収益の計算、広告費回収にかかる期間の理解が可能になります。カスタマイズ可能なフィルター、指標、エクスポートオプションを活用して、データに基づいた意思決定を行い、ユーザー獲得とマネタイズ戦略を最適化し、アプリの成功を最大化しましょう。 --- # File: analytics-funnels --- --- title: "ファネル分析" description: "Adaptyのアナリティクスファネルを理解して、ユーザー行動を把握しコンバージョンを改善する方法を学びましょう。" --- Adaptyのファネルは、次のような疑問に答えるために設計されています。 1. インストールのうち、何パーセントが有料ユーザーに転換するか? 2. プロダクトを試したユーザーのうち、何割がリピーターになるか? 3. どのステップで離脱が多く、改善が必要か? 4. なぜユーザーは課金をやめるのか? ファネルチャートでは、フィルターやグループを設定することで、ユーザー行動についてさらに深いインサイトを得ることができます。 ファネルはSDKおよびストア通知から収集したデータを使用するため、追加の設定は不要です。 :::note ファネルは、[App Settings](general#4-installs-definition-for-analytics) のインストール定義に従ってインストールデータを反映します。 ::: <img src="/assets/shared/img/funnels-tab.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## ファネルチャートをステップごとに解説 \{#funnel-chart-step-by-step\} チャート上でユーザーの行動を正しく読み取るために、ファネルの各要素を順番に確認していきましょう。 <img src="/assets/shared/img/ed5bf5d-CleanShot_2022-06-23_at_09.36.49.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### インストール \{#installs\} 1列目(1)はインストール数を表します。インストールの総数(ユニークユーザーではなく)が絶対値(2)として表示され、以降のコンバージョン計算の基準となる100%として扱われます。ユーザーがアプリを削除して再インストールした場合は、2件のインストールとしてカウントされます。 隣のグレーのエリアはステップ間の遷移パラメーターを示します。次のステップ(ペイウォール表示)へのコンバージョン率がフラグ(3)に表示され、離脱率と絶対値のチャーン数がその下(4)に表示されます。 <img src="/assets/shared/img/00416f9-CleanShot_2022-06-23_at_14.02.06.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### ペイウォール表示 \{#paywall-displayed\} 2列目(5)は、選択した期間内に少なくとも1回ペイウォールを閲覧したアプリユーザー数(6)を表します。この期間内にインストールしたユーザーのみが対象です。ペイウォールの閲覧が選択期間内であっても、インストール日が範囲外の場合はカウントされません。 また、1ステップ目からの割合(7)も表示されます。この割合は1ステップ目のグレーのフラグ(3)と同じ値になりますが、これは最初の2ステップ間だけに成立する関係です。 このステップのデータは、`logShowFlow()`(iOS SDK v4+)/ `logShowPaywall()` メソッドを使用しているすべてのペイウォールから収集されます。そのため、[ドキュメント](present-remote-config-paywalls#track-paywall-view-events)に記載されているように、このメソッドを使ってすべてのペイウォール表示をAdaptyに送信してください。 2列目の隣にあるグレーのエリアは遷移を表します。次のステップ(トライアル)へのコンバージョン率がフラグ(8)に表示され、ペイウォール後の離脱率と絶対値のチャーン数がその下(9)に表示されます。 <img src="/assets/shared/img/fb11650-CleanShot_2022-06-23_at_15.54.32.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### トライアル \{#trials\} 3列目(10)は、選択した期間内にインストールしたユーザーがペイウォールで有効化したトライアル数(11)を表します。フィルターがトライアルなしのプロダクトに設定されている場合、この値はゼロになり、列は空になります。 1ステップ目からのトライアル割合も表示され、インストールからトライアルへのコンバージョン率(12)を確認できます。 この割合は前のステップのグレーのフラグ(8)と一致しないことに気づくでしょう。これは、チャート上部では現在の値を1ステップ目と比較し、グレーのフラグでは直前のステップと比較しているためです。 3列目の隣のグレーエリアは、次のステップ(有料)へのコンバージョン率をフラグ(13)で表示します。トライアル期間中の離脱率と絶対値のチャーン数がその下(14)に表示されます。 <img src="/assets/shared/img/7b88909-CleanShot_2022-06-23_at_15.54.32_-_2.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### サブスクリプションと更新 \{#subscriptions-and-renewals\} 4列目はアクティベートされたサブスクリプション数(15)を示します。トライアルなしのプロダクトはペイウォールからの直接サブスクリプションが含まれ、トライアルありのプロダクトはトライアルから有料サブスクリプションに転換した数が含まれます。両方のタイプがある場合は合算されます。 上部の割合はインストールからのコンバージョン(16)を示します。 グレーのフラグの割合は次のステップ(2期目への更新)へのコンバージョン(17)を示します。 2期目への更新前の離脱率と絶対値はコンバージョンの下(18)に表示されます。 <img src="/assets/shared/img/d13bf9b-CleanShot_2022-06-23_at_15.54.32-3.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> このステップ以降は、同じ構造のステップが続きます。2回目の更新、3回目、4回目と続き、アプリの履歴データが十分あれば、水平スクロールで数十期分を確認できます。各ステップの見方は共通です。 - 上部にインストールからの割合、 - 下部に直前のステップからの割合、 - 上部に更新数の絶対値、 - 下部にチャーン数の絶対値、 - チャーン理由のポップアップ表示(ホバー時)。 ### チャーンの理由 \{#churn-reasons\} Adaptyはトライアルステージ以降の*チャーン*統計を詳細に表示します。あるステージに入ったが次のステージに進まなかったユーザーは、すべてチャーンとしてカウントされます。 * 特定のイベント(例:トライアルの期限切れや支払い問題)がコンバージョンの失敗を引き起こした場合、Adaptyはその理由を表示します。 * **unknown**ステータスは一時的な状態です。ユーザーが次のステージに進むために必要なイベントにまだ遭遇していないことを示します。 トライアルステージでは、通常はトライアルがまだ終了していないことを意味します。トライアルの解決には時間がかかるため、短い日付範囲や単日でファネルを確認する場合によく見られます。 ユーザーがコンバージョンするかトライアルをキャンセルした時点で、Adaptyが情報を更新します。 <img src="/assets/shared/img/churn-reasons.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### テーブルビュー、フィルター、CSVエクスポート \{#table-view-filters-and-csv-export\} ファネルチャートには数値データを扱いやすいテーブルが付属しています。 <img src="/assets/shared/img/4787aff-CleanShot_2022-06-23_at_21.01.44.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> このテーブルはファネルと同じアプローチを踏まえつつ、一部変更が加えられています。 1回目の有料サブスクリプションのステップを除くすべてのステップのデータが列として表示されます。 その代わりに、「インストール → 有料」と「トライアル → 有料」の2つの列が用意されており、無料ユーザーが有料ユーザーになる核心的なコンバージョンポイントを示しています。 「インストール → 有料」列はトライアルなしのプロダクトのみ、「トライアル → 有料」列はトライアルありのプロダクトのみを示しているように見えるかもしれませんが、正確にはそうではありません。トライアルが期限切れになり、ユーザーがトライアルなしのように扱ってトライアルありのプロダクトを購入した場合も考慮されるためです。 <img src="/assets/shared/img/a9bcbc7-CleanShot_2022-06-23_at_21.29.12.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 数値をさらに深掘りしていくと、新たな仮説のための強力なフィルタリングツールが見つかります。 さまざまなディメンションで条件を自由に設定し、データに基づいた真のインサイトを得ましょう。 以下を組み合わせてみてください。 1. プロダクトタイプ(価格帯、期間など) 2. 期間。 3. 国別セグメンテーション。 4. トラフィックのアトリビューション。 5. ストア。 必要なデータだけを表示するために、絶対値 #、相対値 %、またはその両方を選択できます。 <img src="/assets/shared/img/1475e42-CleanShot_2022-06-23_at_21.50.33_-2.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> コントロールパネルの右側には、ファネルデータをCSVでエクスポートするボタンがあります。エクスポートしたファイルはExcelやGoogle スプレッドシートで開いたり、独自の分析システムにインポートしたりできます。 :::important アプリが手数料減額プログラムに登録されている場合は、Adaptyにお知らせください。正確な計算のために、[アプリ設定](general)で[Small Business Program](app-store-small-business-program)および[Reduced Service Fee program](google-reduced-service-fee)のステータスを設定してください。 ::: <img src="/assets/shared/img/ff23846-CleanShot_2022-06-23_at_22.15.49.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> --- # File: analytics-retention --- --- title: "リテンション分析" description: "ユーザーリテンション分析を理解し、サブスクリプション戦略を最適化する方法を説明します。" --- リテンションチャートは、次のような疑問に答えるのに役立ちます。 1. アプリはユーザーを期間ごとにどのように維持しているか? 2. どのプロダクトがより魅力的で、継続率が高いか? 3. どのユーザーグループがより忠実か? 4. 成長のベンチマークとして使えるリテンションレベルはどのくらいか? 5. そして当然ながら、新規ユーザーの獲得ではなく、既存オーディエンスへの投資でコストを節約するにはどうすればよいか? フィルターやグループを設定することで、ユーザー行動に関する貴重なインサイトが得られます。 リテンションは、SDK とストア通知から収集したデータをもとに算出されるため、追加の設定は不要です。 ### リテンションの計算方法 \{#how-do-we-calculate-retention\} リテンションチャートでは、ユーザー数がステップ(トライアル(「トライアルを表示」チェックボックスが有効な場合)、1回目の支払い、2回目の支払いなど)に応じてどう変化するかを確認できます。日付範囲を選択した際にカウントされるユーザーについて説明します。 例えば、カレンダーで過去3か月を選択し、「トライアルを表示」チェックボックスがオフの場合、過去3か月以内に初回サブスクリプションを開始したユーザーのみがカウントされます。「トライアルを表示」がオンで過去3か月を選択した場合は、その期間中にトライアルを開始したすべてのユーザーがカウントされます。これらのサブスクライバーについて、N番目のステップの絶対リテンションはN回目の支払いをしたユーザー数として表示され、N番目のステップの相対リテンションは、選択した期間内のサブスクリプション(またはトライアル)総数に対するN回目の支払い件数の割合として算出されます。 :::info リテンションは遡って変化します チャートを確認するタイミングに関わらず、選択した期間のベースライン(100%)は変わりません。一方、次の期間へのリテンションは時間とともに増加することがあります。 例えば、月次サブスクリプションの場合、12月1日〜31日に20件の初回購入があったとすると、ユーザーが通常通り、あるいは何らかの理由(グレース期間など)でやや遅れて次のサブスクリプション期間に移行するにつれ、2回目の期間へのリテンションは1月を通じて(場合によってはそれ以降も)増加していくことが想定されます。 ::: ### 返金の取り扱い \{#refund-handling\} 返金はリテンションから**除外されません**。返金されたユーザーはリテンションカーブに残るため、同じコホートにおいて[アクティブサブスクリプション](active-subscriptions)や[収益](revenue)よりもリテンションが高く見える場合があります。 各指標での返金の扱いについては、[指標が返金イベントをどのように処理するか](refund-events#how-metrics-handle-refunds)を参照してください。 ### リテンション活用のヒント \{#retention-opportunities\} Adaptyのリテンション機能をより活用する方法を見ていきましょう。 数字への純粋な関心だけでなく、分析結果を実装したあとのビジネス価値を重視するなら、まず目的を明確にすることが大切です。チャート機能を深く理解することで、このデータが持つインパクトも見えてきます。 では、「なぜ」と「どのように」を一緒に整理していきましょう。 1 - オーディエンスへのアプローチ。 まず、リテンションはターゲットオーディエンス、その好み、そしてプロダクトが利用期間中に期待に応えているかどうかに関するものです。収益を生み出すビジネスの核心的な関係性を測る方法をお探しなら、リテンションがその答えです。 このような測定が有効なのは、一般的に既存顧客への販売は新規顧客への販売よりもコストが低いためです。その理由は2つあります。販売にかかる手間が少なく、平均単価が高いのです。そのため、リテンションが低下したときはサブスクライバーのロイヤルティに投資することが賢明な選択かもしれません。 2 - プロダクトへのアプローチ。 2つ目の理由として、リテンションチャートはプロダクトの実際の利用期間を示し、長期的な予測を可能にします。改善したい場合は、プロダクトを提供する施策を修正してその期間を延ばし、再度予測してビジネス目標に近づけましょう。こうした取り組みは、予測ルーティンと組み合わせた戦略的ビジョンの一部になり得ます。そして、絶えず変化する環境で同じ場所にとどまるために皆が全力で走り続けているように、このプロセスに終わりはありません。 3 - 市場へのアプローチ。 主要な競合他社より速く動くことは重要ですが、時には通常の競争から抜け出すことでより大きな成果が得られることもあります。異なる国やストアのユーザー行動を分析すると、地域特有の特性から優れたインサイトやビジネスの新たな機会が見えてくることがあります。文化的・市場的背景をリテンションの観点から分析し、セグメンテーションや今後の開発に活かすことができます。例えば、特定の地域でブルーオーシャンを見つけ、そこで急速に成長できるかもしれません。 リテンションデータの活用はもちろんこの基本的な解釈に限りませんが、素早く実際の価値を得たい場合の良いスタートになるでしょう。 ### カーブ、テーブルビュー、フィルター、CSVエクスポート \{#curves-table-view-filters-and-csv-export\} リテンションの目的と基本的な解釈について共通認識が持てたところで、これらを便利に使うためのツールを見ていきましょう。 Adaptyのリテンション機能の核となるのはチャートです。リテンションレベルが顧客のライフタイムのステップにどう依存するかを示します。 ステップは横軸に表示されます:トライアル、有料(1回目のサブスクリプション)、P2(2回目のサブスクリプション)、P3、P4など。 「トライアルを表示」チェックボックスが選択されている場合のみ、軸はトライアルステップから始まります。 データの計算において、このチェックボックスは次のように機能します。「トライアルを表示」が選択されていて軸がトライアルステップから始まる場合、トライアルを含むシナリオのみが表示され、インストールから直接行われたトランザクションは表示されません。また、「有料」ステップにはトライアルから移行したトランザクションのみが含まれます。「トライアルを表示」が選択されておらず軸が有料ステップから始まる場合、この最初のステップにはトライアルからのものとインストールから直接のものの両方を含む、すべての初回トランザクションが含まれます。 チャート上にマウスを乗せると、データのサマリーポップアップが表示されます。また、下のテーブルの列にマウスを乗せると、チャート上に関連データのサマリーポップアップが表示されます。 テーブルには、チャートで選択したグループとフィルターが同様に反映されます。 フィルターとグループを自由に組み合わせて高度な分析を行いましょう。データに基づいた真のインサイトを収集できます。 以下を組み合わせて活用してください: 1. プロダクトタイプ 2. 期間 3. 時間範囲 4. 国 5. トラフィックアトリビューション 6. ストア 「#絶対値」と「%相対値」コントロールを使って必要なデータを表示してください。 最後に、コントロールパネルの右側にはファネルデータをCSVにエクスポートするボタンがあります。ExcelやGoogleスプレッドシートで開いたり、独自の分析システムにインポートして、使いやすい環境で分析や予測を続けることができます。 :::warning [Adapty General Settings](https://app.adapty.io/settings/general) で、アプリがSmall Business Programに含まれていることを必ず設定してください。 ::: --- # File: analytics-conversion --- --- title: "コンバージョン分析" description: "Adaptyのアナリティクスツールを使ってサブスクリプションのコンバージョン率を測定しましょう。" --- ファネルが全体像を把握するためのもので、リテンションがユーザーロイヤルティに焦点を当てるものだとすれば、コンバージョン分析はユーザージャーニーの各重要ステップにおける効果を時系列で評価するためのものです。 コンバージョンは次のような疑問に答えます: 1. アプリのコンバージョンは時間とともにどのように変化しているか?季節的なトレンドはあるか? 2. マーケティング活動や新たな状況が発生した時点でコンバージョンはどう変化したか? 3. 異なる地域のユーザーはアプリのアップデートにどう反応しているか? 4. どのプロダクトタイプが時間とともによりコンバージョンしやすいか? コンバージョンはAdapty SDKとストア通知から収集したデータをもとに行われるため、追加の設定は必要ありません。 ## メインコントロールとチャート \{#main-controls-and-charts\} 収益は成功を測る定番の指標ですが、それは全体像の一部に過ぎません。異なるユーザー行動やライフサイクルステージ全体にわたって、ビジネスが時間とともにどのように推移しているかを把握することも同様に重要です。そこで役立つのがコンバージョン分析です。 フィルターやグループを設定することで、ユーザー行動についてより深いインサイトを得られます。トレンドを特定して分析するために、コンバージョンが日次・月次・年次でどのように推移しているかをモニタリングしましょう。 チャートの左側にはコンバージョンステップのコントロールがあります。ここで追跡したいコンバージョン(例:インストール → トライアル、トライアル → 有料、有料 → 更新)を選択できます。 各コンバージョン指標は次のロジックに従います: - **X** を選択した日に開始ステートに入ったユーザー数(例:インストール数)とします。 - **Y** をそのユーザーのうち最終的にターゲットステートに到達したユーザー数(例:トライアル開始数)とします。 - コンバージョン率の計算式:**コンバージョン = (Y / X) × 100%** :::note チャートに表示される日付は、ユーザーが初期ステート(X)に入った時点、つまりコンバージョン対象となった瞬間に対応しています。 ::: 各コンバージョンの説明と参考例を以下に示します。 ### インストール → 有料 \{#install---paid\} この指標は、特定の日にアプリをインストールしたユーザーのうち、最終的に初回サブスクリプションを購入した割合を示します。 <details> <summary>仕組み</summary> **定義**: - **X** = 選択した日のインストール数(インストール時点ではプロダクトが選択されていないため、全プロダクトで同じ値)。 - **Y** = そのユーザーのうち最終的に初回サブスクリプション(トライアルまたは非トライアル)を購入したユーザー数。 **計算式**:コンバージョン = (Y / X) × 100% **例**: - 1月1日に100件のインストールがあった。 - 1月8日までに、そのうち20人がサブスクリプションを購入した。 - 1月8日時点での1月1日のコンバージョン = (20 / 100) × 100% = 20% - 2月1日までに、1月1日のインストールグループからさらに30人がサブスクリプションを購入した。 - 2月1日時点での1月1日のコンバージョン = ((20 + 30) / 100) × 100% = 50% つまり、1月1日にアプリをインストールしたユーザーの50%が、現時点までに有料サブスクリプションへコンバージョンしたことになります。 </details> ### インストール → トライアル \{#install---trial\} この指標は、特定の日にアプリをインストールしたユーザーのうち、最終的にトライアルを開始した割合を示します。 <details> <summary>仕組み</summary> **定義**: - **X** = 選択した日のインストール数(インストール時点ではプロダクトが選択されていないため、全プロダクトで同じ値)。 - **Y** = そのユーザーのうち、任意のタイミングでトライアルを有効化したユーザー数。 **計算式**:コンバージョン = (Y / X) × 100% **例**: - 1月1日に100件のインストールがあった。 - 1月8日までに、そのうち20人がトライアルを開始した。 - 1月8日時点での1月1日のコンバージョン = (20 / 100) × 100% = 20% - 2月1日までに、1月1日のインストールグループからさらに30人がトライアルを開始した。 - 2月1日時点での1月1日のコンバージョン = ((20 + 30) / 100) × 100% = 50% つまり、1月1日にアプリをインストールしたユーザーの50%が、現時点までにトライアルを開始したことになります。 </details> ### ペイウォール表示 → トライアル \{#paywall-view---trial\} この指標は、ペイウォールを見たユーザーのうちトライアルを開始したユーザーの割合を追跡します。 <details> <summary>仕組み</summary> **定義**: - **X** = 選択した日にペイウォールを見たユーザー数。 - **Y** = その後任意のタイミングでトライアルを開始したユーザー数。 **計算式**:コンバージョン = (Y / X) × 100% **例**: - 1月1日に100件のペイウォール表示があった。 - 1月8日までに、そのうち20人がトライアルを開始した。 - 1月8日時点での1月1日のコンバージョン = (20 / 100) × 100% = 20% - 2月1日までに、さらに30人がトライアルを開始した。 - 2月1日時点での1月1日のコンバージョン = ((20 + 30) / 100) × 100% = 50% これは、1月1日にペイウォールを見たユーザーの50%が、現時点までにトライアルを開始したことを示しています。 </details> ### ペイウォール表示 → 有料 \{#paywall-view---paid\} この指標は、ペイウォールを見たユーザーのうち購入したユーザーの割合を追跡します。 <details> <summary>仕組み</summary> **定義**: - **X** = 選択した日にペイウォールを見たユーザー数。 - **Y** = その後任意のタイミングで購入したユーザー数。 **計算式**:コンバージョン = (Y / X) × 100% **例**: - 1月1日に100件のペイウォール表示があった。 - 1月8日までに、そのうち20人が購入した。 - 1月8日時点での1月1日のコンバージョン = (20 / 100) × 100% = 20% - 2月1日までに、さらに30人が購入した。 - 2月1日時点での1月1日のコンバージョン = ((20 + 30) / 100) × 100% = 50% これは、1月1日にペイウォールを見たユーザーの50%が、現時点までに購入したことを示しています。 </details> ### トライアル → 有料 \{#trial---paid\} この指標は、特定の日にトライアルを開始したユーザーのうち、その後初回サブスクリプションを購入した割合を示します。 <details> <summary>仕組み</summary> **定義**: - **X** = 選択した日に開始されたトライアル数。 - **Y** = そのユーザーのうち、トライアル後に最終的にサブスクリプションを購入したユーザー数。 **計算式**:コンバージョン = (Y / X) × 100% **例**: - 1月1日に100件のトライアルが開始された。 - 1月8日までに、そのうち20人がサブスクリプションを購入した。 - 1月8日時点での1月1日のコンバージョン = (20 / 100) × 100% = 20% - 2月1日までに、1月1日のトライアルグループからさらに30人がサブスクリプションを購入した。 - 2月1日時点での1月1日のコンバージョン = ((20 + 30) / 100) × 100% = 50% つまり、1月1日にトライアルを開始したユーザーの50%が、現時点までに有料サブスクリプションへコンバージョンしたことになります。 </details> ### 有料 → 2期目 \{#paid---2nd-period\} この指標は、初回支払い後にサブスクリプションを更新したユーザーの割合を示します。 <details> <summary>仕組み</summary> **定義**: - **X** = 選択した日の初回サブスクリプション数。 - **Y** = 任意のタイミングで2期目に更新したユーザー数(通常1サブスクリプションサイクル後。グレース期間中の更新を含む)。 - **計算式**:コンバージョン = (Y / X) × 100% **例**: - 1月1日に100件の初回サブスクリプションがあった。 - 1月8日までに、そのうち20件が更新された。 - 1月8日時点での1月1日のコンバージョン = (20 / 100) × 100% = 20% - 2月1日までに、そのグループからさらに30人が更新した。 - 2月1日時点での1月1日のコンバージョン = ((20 + 30) / 100) × 100% = 50% これは、1月1日に初回サブスクリプション支払いをしたユーザーの50%が、現時点までに2期目へ更新したことを示しています。 </details> ### 2期目 → 3期目 \{#2nd-period---3rd-period\} この指標は、2期目のサブスクリプション後に再度更新したユーザーの割合を追跡します。 <details> <summary>仕組み</summary> **定義**: - **X** = 選択した日の2期目サブスクリプション数。 - **Y** = 任意のタイミングで3期目に更新したユーザー数(通常もう1回の請求サイクル後。グレース期間中の更新を含む)。 **計算式**:コンバージョン = (Y / X) × 100% **例**: - 1月1日に100件の2期目サブスクリプションがあった。 - 1月8日までに、そのうち20人が更新した。 - 1月8日時点での1月1日のコンバージョン = (20 / 100) × 100% = 20% - 2月1日までに、さらに30人が更新した。 - 2月1日時点での1月1日のコンバージョン = ((20 + 30) / 100) × 100% = 50% これは、1月1日に2期目のサブスクリプションに入ったユーザーの50%が、現時点までに3期目へ更新したことを示しています。 </details> ### 3期目 → 4期目 \{#3rd-period---4th-period\} この指標は、3期目のサブスクリプション後に更新したユーザーの割合を示します。 <details> <summary>仕組み</summary> **定義**: - **X** = 選択した日の3期目サブスクリプション数。 - **Y** = 任意のタイミングで4期目に更新したユーザー数(通常1回の請求サイクル後。グレース期間中の更新を含む)。 **計算式**:コンバージョン = (Y / X) × 100% **例**: - 1月1日に100件の3期目サブスクリプションがあった。 - 1月8日までに、20人が更新した。 - 1月8日時点での1月1日のコンバージョン = (20 / 100) × 100% = 20% - 2月1日までに、さらに30人が更新した。 - 2月1日時点での1月1日のコンバージョン = ((20 + 30) / 100) × 100% = 50% つまり、1月1日に3期目のサブスクリプションに入ったユーザーの50%が、現時点までに4期目へ更新したことになります。 </details> ### 4期目 → 5期目 \{#4th-period---5th-period\} この指標は、4期目のサブスクリプション後に更新したユーザーの割合を示します。 <details> <summary>仕組み</summary> **定義**: - **X** = 選択した日の4期目サブスクリプション数。 - **Y** = 任意のタイミングで5期目に更新したユーザー数(通常1回の請求サイクル後。グレース期間中の更新を含む)。 **計算式**:コンバージョン = (Y / X) × 100% **例**: - 1月1日に100件の4期目サブスクリプションがあった。 - 1月8日までに、20人が更新した。 - 1月8日時点での1月1日のコンバージョン = (20 / 100) × 100% = 20% - 2月1日までに、さらに30人が更新した。 - 2月1日時点での1月1日のコンバージョン = ((20 + 30) / 100) × 100% = 50% つまり、1月1日に4期目のサブスクリプションに入ったユーザーの50%が、現時点までに5期目へ更新したことになります。 </details> ### 6ヶ月以上 \{#6-months-\} この指標は、初回サブスクリプションから6ヶ月以上サブスクリプションを継続したユーザーの割合を示します。 <details> <summary>仕組み</summary> **定義**: - **X** = 選択した日の初回サブスクリプション数。 - **Y** = そのユーザーのうち、元のサブスクリプション日から6ヶ月以降に少なくとも1回更新したユーザー数。 **計算式**:コンバージョン = (Y / X) × 100% **例**: - 1月1日に100件の初回サブスクリプションがあった。 - 7月第1週までに、そのうち20人が更新した(例:25回目の週次サブスクリプション)。 - 7月8日時点での1月1日のコンバージョン = (20 / 100) × 100% = 20% - 8月1日までに、さらに30人が6ヶ月以降に更新した。 - 8月1日時点での1月1日のコンバージョン = ((20 + 30) / 100) × 100% = 50% つまり、1月1日にサブスクリプションを開始したユーザーの50%が、8月1日時点で6ヶ月を超えてサブスクリプションを継続したことになります。 </details> ### 1年以上 \{#1-year-\} この指標は、初回サブスクリプションから12ヶ月以上サブスクリプションを継続したユーザーの割合を示します。 <details> <summary>仕組み</summary> **定義**: - **X** = 選択した日の初回サブスクリプション数。 - **Y** = そのユーザーのうち、元のサブスクリプション日から12ヶ月以降に少なくとも1回更新したユーザー数。 **計算式**:コンバージョン = (Y / X) × 100% **例**: - 2021年1月1日に100件の初回サブスクリプションがあった。 - 2022年1月第1週までに、20人が更新した。 - 2022年1月8日時点でのコンバージョン = (20 / 100) × 100% = 20% - 2022年2月1日までに、さらに30人が12ヶ月以降に更新した。 - 2022年2月1日時点でのコンバージョン = ((20 + 30) / 100) × 100% = 50% つまり、2021年1月1日にサブスクリプションを開始したユーザーの50%が、1年以上アクティブを維持したことになります。 </details> ### 2年以上 \{#2-years-\} この指標は、初回支払い日から24ヶ月以上サブスクリプションを継続したユーザーの割合を示します。 <details> <summary>仕組み</summary> **定義**: - X = 選択した日の初回サブスクリプション数。 - Y = そのユーザーのうち、元のサブスクリプション日から24ヶ月以降に少なくとも1回更新したユーザー数。 **計算式**:コンバージョン = (Y / X) × 100% **例**: - 2020年1月1日に100件の初回サブスクリプションがあった。 - 2022年1月第1週までに、そのうち20人が更新した。 - 2022年1月8日時点でのコンバージョン = (20 / 100) × 100% = 20% - 2022年2月1日までに、さらに30人が2年以降に更新した。 - 2022年2月1日時点でのコンバージョン = ((20 + 30) / 100) × 100% = 50% つまり、2020年1月1日にサブスクリプションを開始したユーザーの50%が、2022年2月1日時点で2年以上アクティブだったことになります。 </details> ### グレース期間 → 有料 \{#grace-period---paid\} この指標は、[サブスクリプショングレース期間](grace-period)に入ったユーザーのうち、グレース期間終了*前*に問題を解決したユーザーの割合を示します。 <details> <summary>仕組み</summary> **定義**: - X = グレース期間に入ったサブスクライバー数。 - Y = そのユーザーのうち、グレース期間が終了する前にサブスクリプションを更新したユーザー数。 **計算式**:コンバージョン = (Y / X) × 100% **例**: - 2025年1月1日に、100人のサブスクリプションが自動更新できなくなった。彼らは1月17日までの16日間のグレース期間に入った。 - 1月1日から1月17日の間に50人が支払い情報を更新し、サブスクリプションが正常に更新された。 - 2025年1月17日時点でのコンバージョン = (50 / 100) × 100% = 50% </details> ### 請求問題 → 有料 \{#billing-issue---paid\} この指標は、[請求問題](/billing-issue)が発生したユーザーのうち、請求サイクル終了前に支払いを再開したユーザーの割合を示します。 <details> <summary>仕組み</summary> **定義**: - X = 請求問題が発生したサブスクライバー数。 - Y = そのユーザーのうち、請求問題発生から請求サイクル終了までの間にサブスクリプションを更新したユーザー数。 **計算式**:コンバージョン = (Y / X) × 100% **例**: - 1月1日に、100人のサブスクライバーのサブスクリプションが自動更新できず、請求問題が発生した。 - 注意:グレース期間が有効な場合、請求問題ステートはグレース期間終了後にのみ開始されます。この例ではグレース期間が1月1日に終了したと仮定します。 - 1月8日までに、そのうち10人が支払い問題を解決して更新した。 - 1月8日時点での1月1日のコンバージョン = (10 / 100) × 100% = 10% - 1月31日(請求サイクル終了)までに、さらに10人が更新した。 - 1月31日時点での1月1日のコンバージョン = ((10 + 10) / 100) × 100% = 20% これは、1月1日に請求問題ステートに入ったユーザーの20%が、請求サイクル終了前に問題を解決して更新したことを示しています。 </details> ## グループ化と期間 \{#grouping-and-time-ranges\} コンバージョンを選択した際の分析対象はチャートです。チャートはコンバージョン率が時間とともにどのように変化するかを表示します。日付ピッカーを使って期間のクイックオプションを選択してください。 チャートには通常複数のカーブが表示されます。デフォルトではグループ化リストから最大5つが選択されており、チャート右側のエリアにあるチェックボックスで選択を変更できます。 初めてページを開いたときは、デフォルトのグループ化としてプロダクトの期間が選択されます。その後、設定はキャッシュに保存され、次回アクセス時には最後に選択したグループが表示されます。 利用可能なグループ化は以下の通りです: - プロダクト - 国 - ストア - ペイウォール - 期間 - マーケティングアトリビューション 選択した日付範囲で結果が表示されない場合、関連する日付と日付範囲を自動調整するオプションを提案する通知が表示されます。ワンクリックで調整できます。 ## テーブル表示、フィルター、CSVエクスポート \{#table-view-filters-and-csv-export\} カーブの比較で全体像をつかめますが、さらに詳しく分析するにはチャート下のテーブル表示を使用してください。テーブルはチャートと同期しており、列にカーソルを合わせるとカーブ上に関連するポップアップが表示されます。 上述のグループ化はチャートとテーブルの両方に適用されます。プロダクトによるクイックフィルターや、プロダクト・国・ストア・期間・アトリビューションなどの高度なフィルターを設定できます。 数字を自分のやり方で扱えることが重要だと分かっています。そのため、コントロールパネルの右側にはファネルデータをCSVにエクスポートするボタンがあります。ExcelやGoogle Sheetsで開いたり、独自の分析システムにインポートして、好みの環境で分析や予測を続けることができます。 :::important アプリが手数料減額プログラムに登録されている場合は、Adaptyに通知してください。正確な計算のために、[アプリ設定](general)で[スモールビジネスプログラム](app-store-small-business-program)と[手数料減額サービスプログラム](google-reduced-service-fee)のステータスを指定してください。 ::: --- # File: reports --- --- title: "レポート" description: "Adapty で詳細なサブスクリプションレポートを生成し、アプリの収益とユーザー行動を分析します。" --- 収益、チャーン率、アクティブサブスクライバー数、アクティブトライアル数など、[チャート](charts)で確認できるのと同じ指標を、タイムリーかつ関連性の高い情報としてメールで受け取ることができます。レポートは毎日・毎週・毎月の頻度で届き、直近の期間と前の期間を比較した推移が確認できます。 レポートで送信されるデータは、[**Overview**](https://app.adapty.io/overview) ページで設定した内容(指標の種類・並び順・レポートのタイムゾーン・収益タイプ)に基づいています。 レポートの詳細レベルは、サマリーまたはアプリ別から選択できます。サマリーレポートは、全アプリ(または選択したアプリ)の集計情報を1通のメールにまとめたものです。アプリ別レポートは、選択した単一のアプリのデータのみを含みます。全アプリのサマリーレポートと、最近リリースしたアプリや優先度の高いアプリ、あるいは自分が担当しているアプリのアプリ別レポートを有効にすることをお勧めします。 詳細レベルにかかわらず、メールレポートはあなたのローカルタイムゾーンの午前9時に届きます。毎日レポートは毎日、毎週レポートは毎週月曜日、毎月レポートは毎月1日に送信されます。各レポートには最新のデータと前の期間との比較が含まれます(例:本日の毎日レポートであれば昨日と一昨日のデータを比較、本日の毎週レポートであれば先週と先々週のデータを比較、など)。 選択したレポートの種類に関係なく、最新かつ正確な情報が確実にメールで届きます。 ## レポートを有効にする \{#enable-reports\} 1. Adapty のトップメニューで [**Account**](https://app.adapty.io/account) セクションを開きます。 2. **Email reports** セクションで、受け取りたいレポートの種類(毎日・毎週・毎月)を選択します。 2. **Edit** ボタンをクリックして、各レポートタイプに含めるアプリをカスタマイズします。 3. レポートウィンドウで、含めたいアプリを選択します。 4. **Save changes** ボタンをクリックして選択内容を保存します。 ## タイムゾーンを設定する \{#set-your-time-zone\} 1. Adapty メインメニューで [**Overview**](https://app.adapty.io/overview) セクションを開きます。 2. **Edit** ボタンをクリックし、タイムゾーンを選択します。 3. **Done** ボタンをクリックして保存します。 --- # File: discrepancies-and-troubleshooting --- --- title: "データの相違をトラブルシューティングする" description: "データの乖離の原因を探る" --- Adapty ユーザーは、異なるソースから得た類似データを比較した際に**相違**が生じることがあります。特に以下のような比較で発生しやすいです: * Adapty チャートとストアレポートの比較 * Adapty チャートとサードパーティのチャートの比較 * Adapty 内の異なるチャート同士の比較 ## トラブルシューティングのアルゴリズム \{#troubleshooting-algorithm\} Adapty と他のプラットフォームの間に生じる相違のほとんどは、想定内であり正常です。**異なるソースが同じデータを異なる方法で処理する**ために発生します。 一方で、**Adapty の設定に問題**があることを示す場合もあります。 プラットフォーム間でデータが異なると疑われる場合は、[生データをエクスポート](export-analytics-api-requests)して**ファイルを比較する**のが最善です。 * ストアもデータの処理や表示に関する問題が発生することがあります。最も正確な比較のために、ストアの**生トランザクションデータ**にアクセスしてください。 * Adapty と別のアナリティクスプラットフォームを比較する場合は、ストアのトランザクションレポートを真実の源として比較の基準にしてください。 * 限られたデータセットで比較する方が不整合を見つけやすくなります。少量のデータを比較し、特定のプロダクトと 1 日分に絞って確認しましょう。 * 相違が**価格**の違いによるものか、**イベント数**の違いによるものかを特定してください。価格の問題は[プロダクトの価格更新](#product-pricing)で解決できます。イベントの問題は[サーバー側の問題](#issues-with-server-notifications-and-rtdn)を示している可能性があります。 * [イベントフィード](event-feed)を表示して受信イベントを監視してください。予期しない動作に気づくことがあります。 データがどこで乖離しているかを特定したら、以下の一般的な原因を調査してみてください: ## サーバー通知と RTDN の問題 \{#issues-with-server-notifications-and-rtdn\} ストア接続を正しく設定していない場合、Adapty は必要なイベントデータを受信できません。これは特に、サブスクリプションの更新や請求問題など、ユーザーが直接関与しないイベントに影響します。 できるだけ早くサーバー間の設定を完了し([App Store](enable-app-store-server-notifications) | [Play Store](enable-real-time-developer-notifications-rtdn))、ストアが接続を確立するまで[待機](#data-delays)してください。 不足している App Store Connect のデータは Adapty に[手動でアップロード](importing-historical-data-to-adapty)できます。 ## データの欠落 \{#missing-data\} ### 古いバージョンのアプリを使用しているユーザー \{#users-with-out-of-date-app-versions\} 一部のユーザーが Adapty SDK を含まない古いバージョンのアプリを使用している場合、Adapty はそれらのユーザーのデータを受信できません。そのため、Adapty と他のソースの数値が乖離します。 ### インテグレーションの問題 \{#integration-issues\} 一部の Adapty インテグレーション(Adjust や AppsFlyer など)は、動作するためにアプリケーションコードの追加が必要です。Adapty ダッシュボードを設定しても、アプリケーションを更新していない場合、必要なデータが Adapty に表示されません。 ### 過去データの欠落 \{#missing-historical-data\} Adapty は、[手動でインポート](importing-historical-data-to-adapty)しない限り、アプリケーションの過去データにアクセスできません。チャートの[期間](controls-filters-grouping-compare-proceeds#set-the-date-range)が Adapty を導入する前から始まっており、過去データをインポートしていない場合、その値は他のソースと異なります。 ## データの遅延 \{#data-delays\} Adapty はアプリケーションの経済状況をほぼリアルタイムで分析することを目指しています。ただし、以下の制限と例外があります: * Adapty を最初に導入した際、データはすぐに表示されない場合があります。 * サードパーティプラットフォームとのインテグレーションを有効にした際、データが完全に同期されるまでに遅延が生じる場合があります。 * Adapty がストアのデータを受信してから、Analytics ページで処理・表示されるまでに**15〜30 分**かかります。 * 関係する変数の数が多いため、Adapty とサードパーティ間のデータ交換は**常にリアルタイムとは限りません**。 * 一部の高度な指標([コホート予測](predicted-ltv-and-revenue)など)の計算には一定量のデータが必要です。十分なデータが集まったときのみ、Adapty はこれらの計算を実行します。 ## 時間とカレンダー \{#time-and-calendar\} #### 日付とタイムゾーン \{#dates-and-timezones\} データの相違として認識される最も一般的な原因の一つが、タイムゾーン設定の違いです。 Adapty は `UTC` タイムゾーンを基準に日数をカウントします。別のプラットフォームが異なるタイムゾーンを使用している場合、計算結果が異なります。スケールを大きくすると差異は小さくなります。 アプリケーションごとに[タイムゾーン設定を変更](general#3-reporting-timezone)できます。 #### Apple の会計カレンダー \{#the-apple-fiscal-calendar\} Apple は販売期間と支払い日を決定するために独自の[会計カレンダー](https://adapty.io/apple-fiscal-calendar/)を使用しています。 カレンダーの各「月」は**4 週または 5 週**で構成されており、**隣接するカレンダー月の日数が含まれる場合があります**。支払いは通常、販売期間終了後 30〜45 日以内に行われます。 例えば、「2026 年 1 月」の販売期間は、カレンダー月の開始より 4 日前となる 2025 年 12 月 28 日から始まります。この期間の推定支払い日は 3 月 5 日です。 Apple の支払いレポートのデータをカレンダー月と比較しないでください。代わりに、必要な販売期間に対応する[カスタム期間](controls-filters-grouping-compare-proceeds#set-the-date-range)を選択してください。 #### トランザクションの日付 \{#transaction-dates\} 一部のサービス(例:AppsFlyer)では、トランザクションの表示に[コホート](analytics-cohorts)ルールを適用し、トランザクションが発生した日付ではなく、アプリのインストール日に帰属させる場合があります。 ## 収益の計算 \{#revenue-calculation\} ### 手数料と税金 \{#fees-and-taxes\} [設定](controls-filters-grouping-compare-proceeds#display-gross-or-net-revenue)によって、Adapty チャートは**グロス収益**、**ストア手数料差し引き後の収益**、または**ストア手数料と税金差し引き後の収益**を表示できます。 一部のストアやサードパーティプラットフォームでは、グロス収益を表示する機能がなかったり、税金を自動的に差し引いたりする場合があります。2 つの異なる収益チャート間で相違が見られる場合は、比較が適切かどうかを確認してください。 ### キャンセルと返金 \{#cancellations-and-refunds\} プラットフォームによって返金データの表示方法が異なります。Adapty は返金をマイナスの収益として扱います。ユーザーがサブスクリプションを購入し、翌日に返金を申請した場合、両方のイベントが Adapty チャートに反映されます(それぞれ別の日に)。他のプラットフォームでは、返金額を元のトランザクションから差し引く場合があります。 ## サンドボックス購入 \{#sandbox-purchases\} [イベントフィード](event-feed)にはサンドボックスアカウントによる購入が表示されます。アナリティクスチャートには表示されません。ただし、過去のインポートデータにサンドボックス購入が含まれている場合、Adapty はそれらを区別できないため、チャートに過去のサンドボックス購入が反映されます。 ## インストールとダウンロード \{#installs-and-downloads\} ストア(特に Apple App Store)はユーザーのダウンロードを直接追跡できます。統計にはアプリがインストールされたものの、一度も起動されなかったケースが含まれる場合があります。 Adapty は[インストールの定義](general#4-installs-definition-for-analytics)に関わらず、ユーザーがアプリを起動したときのみインストールを記録できます。 ## 国とストア \{#country-and-store\} 正確なレポートを確保するために、Adapty はユーザーの国を IP アドレスから[推測する場合があります](controls-filters-grouping-compare-proceeds#filter-and-group-data)。ストアは常にダウンロードと購入を特定のアプリストアに帰属させます。 両者を明確に区別する必要がある場合は、`Country by store account` 属性を持つ[新しいユーザーセグメントを作成](segments)し、[セグメントでアナリティクスをフィルタリング](controls-filters-grouping-compare-proceeds#filter-and-group-data)できます。 ## プロダクトの価格 \{#product-pricing\} 誤ったプロダクト価格が収益の相違を引き起こしている場合、価格を変更しても遡及的には修正されません。既存のトランザクションの価格を変更するには、正しいデータをインポートして強制的に上書きする必要があります。 価格変更後にユーザーが古い購入を復元した場合、Apple は購入価格を誤って報告する場合があります。Adapty が正しい値を反映するには、過去データをインポートする必要があります。 ## アトリビューションの競合 \{#attribution-conflicts\} Adapty は各トランザクションに対して[単一のアトリビューションソース](attribution-integration#prevent-data-issues)のみ使用できます。このデータを後から上書きすることはできません。 セットアップに互いに矛盾する複数のアトリビューションプロバイダーが含まれている場合、2 つの異なるプラットフォーム上の同じトランザクションが 2 つの異なるトラフィックソースを持つように見える場合があります。 ## 用語の違い \{#differences-in-terminology\} プラットフォームによっては、同じ概念に異なる名称を使用している場合があります。[収益](#fees-and-taxes)に関連する指標はプラットフォームによって名称が異なります: | Adapty | App Store Connect | Google Play Console | |--------|-------------------|----------------------| | **Gross revenue** | Sales | Gross Revenue | | **Proceeds after store commission** | N/A | N/A | | **Proceeds after store commission and taxes** | Proceeds | Earnings | | **ARPPU** | Proceeds per paying user | ARPPU | 他の指標も定義が異なる場合があります: - **サブスクリプション**: - Adapty は新規トライアルをサブスクリプションとしてカウントしません。[新規サブスクリプション](reactivated-subscriptions)は常に金銭的なトランザクションから開始されます。 - Google Play Console などの他のプラットフォームでは、最初の支払いが行われる前であっても、**各トライアルを新規サブスクリプションとしてカウント**する場合があります。 - **リテンション**: - Adapty はサブスクリプションの更新回数に基づいてリテンションを測定します。 - App Store Connect は、指定された日にアプリケーションを開いたユーザーをリテインしたとみなします。サブスクリプションを持たないユーザーもカウントされますが、その日にアプリを開かなかったサブスクリプションユーザーはカウントされません。 - Google Play Console の「Retained Installers」指標は、アプリケーションがユーザーのデバイスにインストールされたままの日数に基づいてリテンションを測定します。アプリを開かないユーザーもこの指標にカウントされます。 ## 新規サブスクリプション指標と `subscription_started` イベント \{#new-subscriptions-metric-vs-the-subscription_started-event\} [新規サブスクリプション](reactivated-subscriptions)指標と `subscription_started` [インテグレーションイベント](events)はそれぞれ異なるものをカウントするため、合計値は一致しません。この指標はトライアルなしで行われた初回購入とトライアルから有料への転換の両方をカウントします。`subscription_started` イベントはトライアルなしの初回購入のみで発火します。トライアルが有料に転換した場合、Adapty は代わりに `trial_converted` を送信します。その結果、アプリにトライアル転換がある場合、新規サブスクリプション数は `subscription_started` イベント数より多くなります。 --- # File: predicted-ltv-and-revenue --- --- title: "コホートの予測" description: "AdaptyのアナリティクスでLTVと収益を予測する方法を説明します。" --- Adapty の予測機能は、以下の疑問に答えるために設計されています。 1. ユーザーコホートの予測ライフタイムバリュー(LTV)はいくらか? 2. 将来的に最も高い収益を生み出す可能性が高いコホートはどれか? 3. 予測される収益を踏まえて、どれくらい投資できるか? Adapty の予測機能を使えば、収益と成長に関してデータに基づいた意思決定ができます。 Adapty の予測モデルは、アプリのユーザーコホートが長期的に生み出す収益ポテンシャルを推定します。各コホートについて、収益・有料サブスクリプション者数・平均 LTV が時間とともにどのように推移するかを予測します。これにより、ユーザー獲得・マーケティング戦略・プロダクト開発に関して十分な情報に基づいた意思決定が可能になります。 Adapty は、有料サブスクリプション者のコホートに対して予測 LTV と予測収益を提供します。予測はコホート作成から 3・6・9・12・18・24 ヵ月後の値として、コホート分析ページに表示されます。 過去のデータが極めて少ないアプリでは、モデルはアプリ横断の平均値にフォールバックします。そのため、新しいアプリへの予測は、そのアプリ固有のユーザー行動を十分に反映しない場合があります。 ## モデルの仕組み \{#how-the-model-works\} Adapty の予測モデルは、過去のコホートデータのリテンションパターンを使って、将来の収益と LTV を予測します。 アプリとサブスクリプション種別の組み合わせごとに、モデルは更新期間ごとに有料サブスクリプション者数と総収益がどのように変化するかを計測します。アプリの過去のコホートをもとに、サブスクリプション者用とと収益用の 2 種類のリテンション率を算出します。これらの率を新しいコホートに適用することで、コホート作成から 3・6・9・12・18・24 ヵ月後の成長を予測します。使用するデータは完全に匿名化されています。 モデルは各コホートに対して 2 つの値を算出します。 - **予測収益**:選択した期間内にコホートが生み出すと予測される総収益。 - **予測 LTV**:予測収益を、コホートの予測有料サブスクリプション者数で割った値。 ### アプリ固有の重みとアプリ横断の重み \{#app-specific-and-cross-app-weights\} デフォルトでは、コホートの予測にはそのアプリ自身の過去コホートから学習したリテンションの重みが使用され、アプリ固有のユーザー行動が反映されます。 特定の予測期間について十分な履歴がないアプリの場合、Adapty は同じサブスクリプション種別のすべてのアプリを横断して平均化したリテンションの重みにフォールバックします。たとえば、6 ヵ月しか経過していないアプリへの 12 ヵ月予測ではアプリ横断のフォールバックが使用されます。このフォールバックは期間ごとに独立して適用されるため、同じコホートで 3 ヵ月予測にはアプリ固有の重みが使われ、12 ヵ月予測にはアプリ横断の重みが使われる場合があります。 ### 利用可能時期と更新頻度 \{#availability-and-updates\} 予測は、コホートが最初の更新期間を完了した後に利用可能になります。週次サブスクリプションでは作成から約 1 週間後、月次サブスクリプションでは約 4 週間後が目安です。以降は最新のトランザクションデータを使って毎日更新されるため、コホートの動向に合わせた最新の予測が常に提供されます。 ### 制限事項 \{#limitations\} - **データの質**:コホートの動作が通常と異なる場合や、有料サブスクリプション者が非常に少ないコホートは精度が低下します。有料サブスクリプション者が 100 名未満のコホートは、モデルのトレーニングデータから除外されます。 - **新しいアプリ**:十分な履歴がないアプリにはアプリ横断のフォールバック重みが使われるため、そのアプリ固有のユーザー行動を反映しない場合があります。 - **コホートの経過期間**:指定した予測期間をコホートが超えると、その予測は非表示になります。たとえば、3 ヵ月予測は 3 ヵ月を過ぎると表示されなくなり、24 ヵ月を超えたコホートには予測が表示されません。 ## ダッシュボードでの確認 \{#in-the-dashboard\} 予測を確認するには、Adapty ダッシュボードのコホート分析ページに移動してください。コホートの詳細については、[コホート分析](analytics-cohorts)を参照してください。 <img src="/assets/shared/img/4d808b4-Export-1691486610612.gif" alt="予測収益と予測 LTV 列を表示したコホート分析ページ" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> **Predicted revenue** 列には、コホート作成後に選択した期間中にサブスクリプション者のコホートが生み出すと予測される総収益の推定値が表示されます。この値は、アプリの過去のコホートリテンションパターンをもとに Adapty の予測モデルが算出します。 **Predicted LTV** 列には、選択したコホートの各ユーザーの推定ライフタイムバリューが表示されます。この値は、予測収益をコホート内の予測有料ユーザー数で割って算出されます。 ### 予測期間の選択 \{#select-the-horizon\} 予測期間を変更するには、**Predictions** ドロップダウンから値を選択してください。選択できるオプションは、コホート作成から 3・6・9・12・18・24 ヵ月後です。 ### プロダクトでフィルタリング \{#filter-by-product\} 予測収益と LTV をプロダクト別にフィルタリングできます。デフォルトではすべての購入データをもとに予測が構築されます。プロダクトでフィルタリングすると、各プロダクトの貢献度を確認できます。 <img src="/assets/shared/img/66a9c61-Export-1691486288948.gif" alt="プロダクト別にフィルタリングされたコホート分析" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## 予測が利用できない場合 \{#when-predictions-are-unavailable\} コホートの予測を生成できない場合、予測収益と予測 LTV の列には値の代わりにダッシュ(—)が表示されます。これは以下のような理由で発生します。 - **コホート作成からの時間が不十分**:予測はコホートが最初の更新期間を完了した後にのみ利用可能になります。週次サブスクリプションでは約 1 週間後、月次サブスクリプションでは約 4 週間後が目安です。 - **コホートサイズが小さすぎる**:信頼性の高い予測を生成できるほどの有料サブスクリプション者がいない。 - **コホートの動作が通常と異なる**:コホートがモデルの想定するパターンから大きく外れている。数週間待つとデータが蓄積され、解消される場合があります。 - **予測期間を超過**:コホートが選択した予測期間よりも古い。たとえば、3 ヵ月予測は 3 ヵ月後に非表示になり、12 ヵ月予測は 12 ヵ月後に非表示になります。また、24 ヵ月を超えたコホートには予測が表示されません。 :::warning 予測を有効にする際には、収益と LTV の予測データが Adapty ダッシュボードに表示されるまで、最大 24 時間の遅延が発生する場合があることにご注意ください。 ::: --- # File: predictions-in-ab-tests --- --- title: "A/B テストの予測" description: "A/B テストの予測がサブスクリプション価格戦略の改善にどう役立つかを学びましょう。" --- Adapty の A/B テスト機能における予測分析のドキュメントへようこそ。このツールは、実行中の A/B テストの将来の結果に関するインサイトを提供し、Adapty の ML ベースの予測でデータに基づいた意思決定を素早く行えるよう支援します 🚀 ### A/B テストの予測とは? \{#what-are-ab-test-predictions\} Adapty の A/B テスト予測は、高度な機械学習技術(勾配ブースティングモデル)を活用して、A/B テストで比較されるペイウォールの長期的な収益ポテンシャルを予測します。 この予測モデルにより、テスト実行中に観察できる指標だけに頼るのではなく、1 年後の予測収益に基づいて最も効果的なペイウォールを選択できます。これにより、データが蓄積されるのを何週間も待つことなく、より確実かつ迅速に勝者を決定できます。 ### モデルはどのように機能するのか? \{#how-does-the-model-work\} このモデルは、さまざまなカテゴリのアプリから収集した大量の A/B テスト履歴データで学習されています。実験開始から 1 年後にペイウォールが生み出す収益を予測するために、幅広い特徴量を組み込んでいます。これらの特徴量には以下が含まれます。 - 異なる期間にわたるユーザーのトランザクションとコンバージョン率 - ユーザーの地理的分布 - プラットフォームの利用状況(iOS または Android) - オプトアウト率と返金率 - サブスクリプションプロダクトとその期間(日次・月次・年次など) - その他のトランザクション関連データ このモデルはペイウォールのトライアル期間も考慮しており、ユーザーがすでにコンバージョンしたかのように収益を予測するために、履歴のコンバージョン率を使用しています。アクティブなトライアルが将来的に収益をもたらす可能性についても考慮するため、トライアルオファーのあるペイウォールとないペイウォールを公平に比較できます。 ### 予測 P2BB と通常の P2BB の違いは? \{#how-is-predicted-p2bb-different-from-just-the-p2bb\} Adapty の A/B テストはベイズアプローチを採用しています。具体的には、ユーザーあたりの収益(「1,000 ユーザーあたりの収益」)の分布をモデル化し、一方の分布がもう一方よりも偶然ではなく「真に」優れている確率を計算します。これが「ベスト確率(P2BB)」と呼ばれるものです(詳細なアプローチについては[こちら](maths-behind-it)をご覧ください)。 重要な点として、この計算はテストが実行された期間中に蓄積された収益のみに基づいています。たとえば、年次サブスクリプションと週次サブスクリプションを比較するテストを実行する場合、どちらが優れているかを真に理解するまでに非常に長い時間がかかります。同様に、A/B テストでトライアルサブスクリプションと非トライアルサブスクリプションを比較する場合も同じ問題が起きます。勝者の動向を左右する可能性があるアクティブなトライアルが、収益の計算において常に考慮されないためです。 ここで予測モデルが活躍します。A/B テストの現在の収益分布を持ち、大規模なデータセットで学習されているこのモデルは、将来の収益分布(具体的には 1 年後)を予測できます。そして、その結果として「予測 P2BB」を算出します。これは、テストを 1 年間丸ごと実行した場合に得られるであろう P2BB です。 予測 P2BB が現在の P2BB と矛盾することがある点に注意してください。そのような場合、以下のようにバリアントの行が黄色でハイライト表示されます。 <img src="/assets/shared/img/74577c6-CleanShot_2024-02-15_at_13.08.452x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> これは、勝者を確認するためにさらにデータを蓄積するか、A/B テストを深く掘り下げてその原因を調査すべきシグナルと考えています。一般的に、予測 P2BB はより多くのデータを考慮しているため、現在の P2BB よりも予測 P2BB を信頼することを推奨しますが、最終的な判断はもちろんユーザー自身に委ねられています。 ### モデルの精度と確実性 \{#model-accuracy-and-certainty\} このモデルは高い精度を実現しており、平均絶対誤差率(MAPE)は 10% をわずかに下回ります。この精度により、データに基づいた意思決定においてモデルの予測を自信を持って活用できます。 安定性をさらに確保するために、モデルは 3 つの要素に基づく「確実性」基準を採用しています。 - 予測区間が狭い — モデルが結果に高い確信を持っている - テスト内のサブスクリプション数と収益が十分である - テスト開始から少なくとも 2 週間が経過している これら 3 つの基準のうち少なくとも 2 つが満たされた場合に、予測が信頼できるとみなされます。 新しい A/B テストが開始されると、モデルは各ペイウォールについて 1 年先の 1,000 ユーザーあたりの収益(A/B テストのメイン指標)の予測を提供します。予測は確実性基準を満たした場合のみ表示されます。データが不十分な場合、モデルは「予測に必要なデータが不足しています」と表示します。 ### 制限事項と注意点 \{#limitations-and-considerations\} 予測モデルは強力なツールですが、その制限事項を理解しておくことが重要です。 モデルのパフォーマンスは、利用可能なデータの質と代表性に依存します。通常とは異なるコホートの挙動や、学習セットに含まれていない新しいアプリは、予測精度に影響を与える可能性があります。 それでも、予測は最新のデータとユーザー行動を反映するために毎日更新されます。これにより、受け取るインサイトが常に最新の情報に基づいていることが保証されます。 🚧 注意:このツールは、あなたの専門的な判断やアプリ独自のダイナミクスへの理解を補完するものであり、代替するものではありません。これらの予測は、他の指標や市場知識と組み合わせて活用し、情報に基づいた意思決定のためのガイドとしてご利用ください。 --- # File: adapty-ads-manager --- --- title: "Apple Ads Manager" description: "Get realtime analytics from Apple Ads and manage and optimize your campaigns" --- **Apple Ads Manager** is an all-in-one platform designed to help you manage, optimize, and scale your Apple Ads campaigns more efficiently. It connects your Apple Search Ads performance with key revenue metrics such as installs, trials, subscriptions, and lifetime value without requiring an MMP. With real-time analytics, AI-driven forecasts, and smart automation, Apple Ads Manager eliminates tedious manual bid changes, spreadsheets, and guesswork, and replaces them with clear insights and tools that help you take action faster. With Apple Ads Manager, you get: - **[Overview](ads-manager-overview)**: All key metrics at a glance — spend, revenue, ROAS, CPA, and more — each with a daily trend chart - **Real-time performance data**: Across campaigns, ad groups, and keywords - **End-to-end revenue tracking**: From search → install → trial → subscription → LTV - **AI predictions & recommendations**: For profitable scaling - **Bulk management**: Of bids, budgets, statuses, and structures - **Rule-based automations**: Manage the full keyword lifecycle - **[Market Intelligence](ads-manager-market-intelligence)**: Competitor keyword strategies across 50+ countries - **[CPP A/B Tests](ads-manager-cpp-ab-tests)**: Compare custom product pages head-to-head and find the best performer <CustomDocCardList ids={['adapty-ads-manager-get-started', 'ads-manager-overview', 'adapty-ads-manager-analytics', 'ads-manager-create-campaign', 'ads-manager-create-ad-group', 'ads-manager-manage-keywords', 'ads-manager-automations', 'ads-manager-market-intelligence', 'ads-manager-cpp-ab-tests']} /> ## Why Apple Ads Manager? Because we give you the **most accurate data in the market.** Unlike the native Apple Ads console or MMPs, our data is **real-time, lossless, and fully connected** to trials, subscriptions, and LTV — without delays or attribution gaps. With its easy implementation and smooth user experience, you can manage everything in one place without having to switch between multiple tools. ## Get started To get started with Apple Ads Manager, follow the [guide](adapty-ads-manager-get-started), and you're all set to explore --- # File: adapty-ads-manager-get-started --- --- title: "Apple Ads Managerを始める" description: "Apple Adsから過去データをインポートし、ダッシュボードでリアルタイム更新を受け取る" --- [Apple Ads Manager](adapty-ads-manager) は、Apple Ads の最適化・分析プラットフォームです。 このガイドでは、Apple Ads Manager を 2 つのステップで使い始める方法を説明します。 1. Adapty SDK をインストールし、購入データを追跡させる。 2. Apple Ads Manager を Apple Ads アカウントに接続し、過去データをインポートしてリアルタイム更新の追跡を開始する。 :::note Apple Ads Manager は **App settings** の [Apple Ads インテグレーション](apple-search-ads) を使いません。 Apple Ads Manager を使うには、このガイドで説明するセットアップを完了するだけで十分です。 ::: ## 1. Adapty SDK をインストールする \{#1-install-the-adapty-sdk\} :::important Adapty Ads Manager は**スタンドアロンプロダクト**です。ペイウォール、サブスクリプション、アナリティクスを Adapty で管理していない場合でも利用できます。スタック全体を Adapty に移行する必要はありません。 正確な収益データを取得するための最小構成は、Adapty SDK をオブザーバーモードでインストールし、Adapty で App Store サーバー通知を有効にすることです。 ::: 収益データとキャンペーンパフォーマンスを紐付けるために、Adapty に購入を追跡させます。 1. 最初のステップは、すでにアプリ内課金を実装しているかどうかによって異なります。 - **Adapty でアプリ内課金をすでに実装している場合**、この段階で追加の作業は不要です。 - **Adapty を使わずにアプリ内課金をすでに実装しており、Adapty への移行を予定していない場合**、お使いのプラットフォーム向けの Adapty SDK をオブザーバーモードでインストールします。この段階では、SDK をプロジェクトに追加し、オブザーバーモードを有効にして起動し、トランザクションを報告するだけで構いません。 - [iOS](implement-observer-mode) - [Android](implement-observer-mode-android) - [React Native](implement-observer-mode-react-native) - [Flutter](implement-observer-mode-flutter) - [Unity](implement-observer-mode-unity) - [Kotlin Multiplatform](implement-observer-mode-kmp) - [Capacitor](implement-observer-mode-capacitor) - **アプリ内課金をまだ実装しておらず、Adapty を使いたい場合**、[クイックスタートガイド](quickstart) の手順を完了して、購入処理を Adapty に委任します。 2. App Store から収益に関する更新を直接受け取るために、[Adapty で App Store サーバー通知を有効化](enable-app-store-server-notifications) します。 ## 2. Apple Ads を接続する \{#2-connect-apple-ads\} :::important Adapty に Apple Ads を接続するには、Apple Ads で **Account Admin** ロールが必要です。 ::: 次に、Apple Ads Manager アカウントを Apple Ads アカウントに接続します。 1. Adapty ダッシュボードの左上で Apple Ads Manager に切り替えます。 2. **Continue with Apple** をクリックします。 3. Apple アカウントにサインインします。 4. Apple Ads Manager に付与するアクセス権を選択します。 - **Read and Write**: すべてのキャンペーングループへのアクセスを提供します。 - **Limited access**: 特定のキャンペーングループを選択し、**Read & Write** ロールを割り当ててそのグループのみにアクセスを付与します。 5. **Grant access** をクリックします。 完了すると、Adapty が Apple Ads から過去データの同期を開始します。Adapty Ads Manager はすぐに使い始められますが、すべての過去データがインポートされるまで少し時間がかかります。 ## 次のステップ \{#whats-next\} トランザクションデータの同期が完了したら、次の操作方法を確認しましょう。 - [キャンペーン、広告グループ、キーワードを管理する](ads-manager) - [キャンペーンパフォーマンスに基づいて入札を自動調整するオートメーションルールを設定する](ads-manager-automations) --- # File: ads-manager-overview --- --- title: "Apple Ads Managerの概要" description: "Apple Adsの主要指標をすべて一か所で確認でき、各指標にはトレンドチャートが表示されます。" --- **Overview** ページでは、Apple Adsの主要指標をすべて一か所で確認でき、各指標にはトレンドチャートが表示されます。 デフォルトでは、接続されているすべてのアプリのデータが表示されます。特定のアプリのみ表示したい場合は、ヘッダーのアプリドロップダウンから選択してください。 開くには、Apple Ads Managerの左サイドバーにある **Overview** をクリックします。 ## 指標 \{#metrics\} 各指標は、選択した期間のトレンドチャートとともにカードとして表示されます。指標の定義と計算式については、[Apple Ads Managerの指標](adapty-ads-manager-metrics)をご覧ください。 ## 表示する指標の設定 \{#configure-displayed-metrics\} **Overview** ページに表示する指標を変更するには、**Edit metrics** をクリックします。そこから以下の操作が可能です: - **指標を追加する**:**Add metric** をクリックし、追加したい指標のチェックボックスを選択します。 - **指標を削除する**:**Add metric** パネルでチェックボックスをオフにするか、指標の横にある **×** をクリックします。 ## コントロール \{#controls\} 上部のコントロールを使って、**Overview** ページの表示内容を調整できます: - **Date range**:プリセット期間(**Last 7 days**、**Last 30 days**、**Last 90 days**)から選択するか、カスタム範囲を入力します。すべてのチャートと集計値が選択した期間に合わせて更新されます。 - **Chart type**:積み上げ縦棒、折れ線、円グラフのビューを切り替えられます。 - **Revenue display**:収益指標の計算方法を選択します: - **Gross revenue**:控除前の総収益。 - **Proceeds after store commission**:Appleの手数料を差し引いた後の収益。 - **Proceeds after store commissions and taxes**:Appleの手数料と適用される税金を両方差し引いた後の純収益。 --- # File: adapty-ads-manager-metrics --- --- title: "Apple Ads Managerの指標" description: "Apple Ads Managerでアプリのアナリティクスを確認します。" --- Apple Ads Managerでは、キャンペーンのパフォーマンスとユーザー行動を測定するための包括的な指標が提供されています。 ## パフォーマンス \{#performance\} | 指標 | 説明 | |--------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Spend | 広告がタップされるたびに発生するコストの合計。 | | Impressions | レポート期間内に、App Storeの検索結果にスポンサー広告が表示された回数。 | | CPM | 広告1,000インプレッションあたりの平均支払額。平均CPM = 支出 / (インプレッション / 1000)。注: CPT価格モデルのApp Store検索結果キャンペーンでは、実効CPMが表示されます。 | | Taps | レポート期間内に広告がユーザーにタップされた回数。 | | CPT | 広告1タップあたりの平均支払額。平均CPT = 支出 / タップ数 | | TTR | 広告のタップ数をインプレッション総数で割った値。TTR = タップ数 / インプレッション数 × 100% | | Downloads (Total) | レポート期間内に広告経由で発生したタップスルーおよびビュースルーによる新規ダウンロードと再ダウンロードの合計数。 | | Downloads (View-Through) | 広告を閲覧したがタップしなかったユーザーによる、24時間以内のダウンロードおよび再ダウンロード数。 | | Downloads (Tap-Through) | 広告をタップしたユーザーによる、30日間以内の新規ダウンロードおよび再ダウンロードの合計数。 | | Avg CPA (Total) | トータル平均コストパーアクリジション(CPA)は、キャンペーン総支出をレポート期間内の広告ビューまたはタップによるダウンロード総数で割った値。 | | Avg CPA (Tap-Through) | タップスルー平均コストパーアクリジション(CPA)は、キャンペーン総支出をレポート期間内のタップスルーダウンロード数で割った値。 | | Download Rate (Total) | 広告のビューまたはタップによる総ダウンロード数をレポート期間内のタップ総数で割った値。計算式: タップ数 > 0 の場合 (総ダウンロード数 / タップ数) × 100%、それ以外は 0% | | Download Rate (Tap-Through) | 広告タップによる総ダウンロード数をレポート期間内のタップ総数で割った値。計算式: タップ数 > 0 の場合 (タップスルーダウンロード数 / タップ数) × 100%、それ以外は 0% | | DPM (Total) | Downloads per Mille(DPM)は1,000インプレッションあたりのダウンロード数。計算式: インプレッション数 > 0 の場合 (総ダウンロード数 / インプレッション数) × 1000、それ以外は 0 | ## コンバージョン \{#conversions\} :::note Revenue、ARPU、ARPPU、ARPAS、ROAS、ROIは、ユーザーグループの時系列分析のためのコホート指標としても利用できます。 ::: | 指標 | 説明 | |--------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Conversions | Conversionsは、レポート期間内のコンバージョンイベントの合計数。計算式: トライアル開始数 + サブスクリプション開始数 + 非サブスクリプション数 | | Conversion CR | Conversion CR(コンバージョン率)は、総ダウンロード数のうちコンバージョンに至った割合。計算式: 総ダウンロード数 > 0 の場合 (コンバージョン数 / 総ダウンロード数) × 100%、それ以外は 0% | | Cost per Conversion | Cost per Conversionは、総支出をコンバージョン数で割った値。計算式: コンバージョン数 > 0 の場合 支出 / コンバージョン数、それ以外は 0 | | Revenue | Revenueは、選択した期間内にアプリでの購入・更新・その他の収益化コンバージョンから得られた総収益(ストア手数料控除前)。 | | ROAS | ROAS(Return on Ad Spend)は、広告収益を広告支出で割ったもので、パーセンテージで表示されます。計算式: 支出 > 0 の場合 (Revenue / 支出) × 100%、それ以外は 0% | | ROI | ROI(Return on Investment)は、支出に対する純利益を測定します。計算式: 支出 > 0 の場合 ((Revenue − 支出) / 支出) × 100%、それ以外は 0% | | ARPU | ARPU(Average Revenue per User)は、ユーザーあたりの平均収益。総収益をユニークユーザー数で割って算出します。例: $60,000 revenue / 5,000 users = $12 ARPU。インストールあたりのコスト(CPI)と比較することで、マーケティングキャンペーンの効果を把握できます。 | | ARPPU | ARPPU(Average Revenue per Paying User)は、課金ユーザーあたりの平均収益。総収益をユニーク課金ユーザー数で割って算出します。例: $60,000 revenue / 1,000 paying users = $60 ARPPU。課金ユーザー1人が平均的にどれだけの収益を生み出しているかを把握できます。 | | ARPAS | ARPASは、アクティブサブスクライバーあたりの平均収益。計算式: 総収益 / アクティブサブスクライバー数。サブスクライバーとは、トライアル期間またはサブスクリプションを有効化したユーザーを指します。例: $60,000 revenue / 1,500 subscribers = $40 ARPAS。 | | Installs | Installsは、アプリを初めてインストールしたユーザー数と既存ユーザーによる再インストール数の合計。異なるデバイスでの同一ユーザーによる複数インストールも含みます。ダウンロードが完了する前にキャンセルされた場合はカウントされません。 | | Installs CR | Installs CR(コンバージョン率)は、総ダウンロード数のうちアプリをインストールしたユーザーの割合。計算式: 総ダウンロード数 > 0 の場合 (インストール数 / 総ダウンロード数) × 100%、それ以外は 0% | | CPI | CPI(Cost per Install)は、Adaptyが計測するインストールあたりのコスト。計算式: インストール数 > 0 の場合 支出 / インストール数、それ以外は 0 | | Trials | Trialsは、レポート期間内に開始された新規トライアルサブスクリプションの数。 | | Trial CR | Trial CR(コンバージョン率)は、総ダウンロード数のうちトライアルを開始した割合。計算式: 総ダウンロード数 > 0 の場合 (トライアル数 / 総ダウンロード数) × 100%、それ以外は 0% | | Cost per Trial | Cost per Trialは、総支出を新規トライアル開始数で割った値。計算式: トライアル数 > 0 の場合 支出 / トライアル数、それ以外は 0 | | Trials converted | Trials convertedは、レポート期間内にトライアルサブスクリプションから有料サブスクリプションへ転換した数。 | | Trial converted CR | Trial converted CR(コンバージョン率)は、トライアルサブスクリプションのうち有料サブスクリプションへ転換した割合。計算式: トライアル数 > 0 の場合 (転換トライアル数 / トライアル数) × 100%、それ以外は 0% | | Cost per Trial converted | Cost per Trial convertedは、総支出を同期間内の転換トライアル数で割った値。計算式: 転換トライアル数 > 0 の場合 支出 / 転換トライアル数、それ以外は 0 | | Subscriptions | Subscriptionsは、レポート期間内の新規サブスクリプション登録数(トライアルを除く)の合計。 | | Subscription CR | Subscription CR(コンバージョン率)は、総ダウンロード数のうち無料トライアルなしで有料サブスクリプションを開始した割合。計算式: 総ダウンロード数 > 0 の場合 (サブスクリプション数 / 総ダウンロード数) × 100%、それ以外は 0% | | Cost per Subscription | Cost per Subscriptionは、総支出を新規サブスクリプション開始数で割った値。計算式: サブスクリプション数 > 0 の場合 支出 / サブスクリプション数、それ以外は 0 | | Non-subscriptions started | Non-subscriptions startedは、サブスクリプションではないアプリ内の買い切り購入の合計数。 | | Non-subscription CR | Non-subscription CR(コンバージョン率)は、総ダウンロード数のうち非サブスクリプション購入を行った割合。計算式: 総ダウンロード数 > 0 の場合 (非サブスクリプション開始数 / 総ダウンロード数) × 100%、それ以外は 0% | | Cost per Non-subscription | Cost per Non-subscriptionは、総支出を非サブスクリプション購入数で割った値。計算式: 非サブスクリプション開始数 > 0 の場合 支出 / 非サブスクリプション開始数、それ以外は 0 | ## 詳細ダウンロード \{#advanced-downloads\} | 指標 | 説明 | |--------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | New Downloads (Total) | レポート期間内のタップスルーおよびビュースルーによる新規ダウンロードの合計数。 | | New Downloads (View-Through) | 広告を閲覧したがタップせず、かつ以前にアプリをダウンロードしていないユーザーによる24時間以内の新規ダウンロード数。 | | New Downloads (Tap-Through) | 広告をタップし、以前にアプリをダウンロードしていないユーザーによる新規ダウンロード数。30日間のアトリビューションウィンドウ内でカウントされます。 | | New Download Share (Tap-Through) | タップによる総ダウンロード数のうち新規ダウンロードが占める割合(30日間のアトリビューションウィンドウ内で広告をタップしたユーザーによるもの)。 | | Redownloads (Total) | レポート期間内のタップスルーおよびビュースルーによる再ダウンロードの合計数。 | | Redownloads (View-Through) | 広告を閲覧したがタップしなかったユーザーによる24時間以内の再ダウンロード数。広告閲覧後にアプリを削除して同一または別のデバイスで再ダウンロードした場合にカウントされます。 | | Redownloads (Tap-Through) | 広告をタップしたユーザーによる30日間のアトリビューションウィンドウ内の再ダウンロード数。広告タップ後にアプリを削除して同一または別のデバイスで再ダウンロードした場合にカウントされます。 | | Redownloads Share (Tap-Through) | タップによる総ダウンロード数のうち再ダウンロードが占める割合。 | ## インサイト \{#insights\} | 指標 | 説明 | |--------|------------------------------------------------------------------------------------------------------------------------------------------| | Impression Share | Impression Shareは、同じ検索ワードに対する総インプレッション数のうち、自社広告が獲得したインプレッションの割合。 | | Rank | Rank(現在)は、特定の国または地域における選択した検索ワードでのインプレッションシェアに基づく、アプリの現在の順位。 | | Search Popularity | Search Popularity(現在)は、国または地域別の検索ワードの人気度。ランキングは1〜5で、5が最も検索ボリュームが高いことを示します。 | --- # File: ads-manager-create-campaign --- --- title: "Apple Ads Managerでキャンペーンを管理する" description: "Apple Ads ManagerでApple Adsキャンペーンを作成・編集します。" --- Apple Ads ManagerはApple Adsと双方向に連携しており、ほぼリアルタイムのパフォーマンスデータを取得できるほか、ネイティブUIよりもはるかに便利な形でAdaptyダッシュボードから直接キャンペーンを作成・編集できます。 ネイティブのApple Adsダッシュボードでキャンペーンを作成した場合、24時間以内にApple Ads Managerへ自動的に反映されます。 [包括的なキャンペーン指標の確認](adapty-ads-manager-analytics)に加えて、すべてのキャンペーン設定を管理できます: - キャンペーンの作成 - 既存キャンペーンの編集 - キャンペーンの開始・一時停止 ## キャンペーンとは \{#what-is-campaign\} キャンペーンは1つのアプリに絞り、App Store上の1つのプレースメントで広告を配信します。各キャンペーンには1日の予算と、アプリのプロモーション戦略に特化した[広告グループ](ads-manager-create-ad-group)が含まれます。キャンペーンは予算設定に従って継続的に消化されます。 :::important キャンペーン単体では配信できません。デフォルトの入札額、オーディエンス、キーワードを設定するのは広告グループのレベルです。広告グループがなければ、ターゲティングも入札もなく、広告は配信されません。キャンペーンを作成したら、必ず[1つ以上の広告グループを追加](ads-manager-create-ad-group)してください。 ::: ## キャンペーンを作成する \{#create-campaigns\} 新しいApple Adsキャンペーンを作成するには: 1. サイドバーメニューから **Ads Manager** に移動します。どのタブでも、テーブル上の **+** をクリックして **Create campaign** を選択します。 2. キャンペーンを開始するアプリを選択します。 3. キャンペーンのキャンペーングループを選択します。 4. **Campaign Settings** セクションで以下を設定します: - **Campaign name**: ダッシュボードでキャンペーンを識別・検索するためのラベルです。 - **Ad placement**: 広告が表示されるApp Storeの具体的な配置場所: - **Search tab**: ユーザーがApp StoreのSearchタブを開いたときに、おすすめアプリリストの最上部にアプリを表示します。 - **Search results**: ユーザーがApp Storeで関連アプリを検索したときに、検索結果の最上部にアプリを表示します。 - **Product pages**: 関連プロダクトページを下にスクロールしたユーザーに対して、**You might also like** リストの最上部に広告を表示します。 - **Countries or regions**: キャンペーンが配信・予算消化の対象となる地域です。 - **Ad scheduling**: 広告の開始日時。オプションで終了日時も設定できます。 5. **Bid Strategy** セクションで入札の管理方法を選択します: - **Manage Bids**: 広告グループおよびキーワードレベルで手動で入札額を設定・調整します。**Daily budget** を入力します。 - **Maximize Conversions**: Appleの自動入札により、予算内でダウンロード数を最大化します。**Daily budget** と、特定のダウンロード単価目標に向けてアルゴリズムを誘導するための **Target CPA** を入力します。[詳細はこちら](https://ads.apple.com/app-store/best-practices/maximize-conversions) 6. **Create** をクリックします。 7. キャンペーンを有効化するために、続けて[広告グループを作成](ads-manager-create-ad-group)します。 ## キャンペーンを編集する \{#edit-campaigns\} 作成済みのキャンペーンを編集するには: 1. 以下のいずれかの方法でキャンペーン設定を開きます: - **Ads Manager > Campaigns** でキャンペーン名をクリックし、右上の **Edit campaign** をクリックします。 - または、キャンペーン名の横にあるチェックボックスをオンにして、**Actions > Edit campaign settings** をクリックします。 2. キャンペーン設定を変更します。編集できるのは名前、国・地域、1日の予算のみです。広告プレースメントやスケジュールを変更したい場合は、新しいキャンペーンを作成してください。 3. **Save changes** をクリックします。 :::note Apple Adsで直接行ったキャンペーンの編集は自動的にApple Ads Managerに同期されますが、Apple Ads Managerへの反映には時間がかかる場合があります。 ::: ## キャンペーンをエクスポートする \{#export-campaigns\} キャンペーンテーブルをCSVとしてエクスポートするには、テーブル上のダウンロードアイコンをクリックして **Export current page** または **Export all pages** を選択します。 **Export all pages** は、全ページにわたるすべてのキャンペーンを1つのファイルにダウンロードします。進行状況を示すモーダルが表示され、いつでもキャンセルできます。2つのオプションフィルターが利用可能です: - **Enabled only**: 有効なキャンペーンのみを含めます。 - **With spend ≥**: 指定した閾値以上の消化金額があるキャンペーンのみを含めます。 - **Group by country**: 各キャンペーン行を国別に分解します。 テーブルは、表示列の選択も含め、ダッシュボードでの表示状態のままエクスポートされます。 ## キャンペーンを開始・一時停止する \{#launch--pause-campaigns\} Apple Ads Managerからキャンペーンを開始または一時停止するには: 1. **Ads Manager > Campaigns** に移動します。 2. **Status** 列のキャンペーン名の横にあるトグルをオン・オフに切り替えます。 --- # File: ads-manager-create-ad-group --- --- title: "Apple Ads Managerで広告グループを管理する" description: "Apple Ads ManagerでApple Adsの広告グループを作成・編集します。" --- Apple Ads ManagerはApple Adsと双方向に連携しています。ほぼリアルタイムのパフォーマンスデータを取得できるほか、ネイティブUIよりもはるかに使いやすいAdaptyダッシュボードから直接キャンペーンを作成・編集できます。 ネイティブのApple Adsダッシュボードで広告グループを作成した場合、24時間以内にApple Ads Managerに自動的に表示されます。 [包括的なキャンペーン指標の確認](adapty-ads-manager-analytics)に加えて、広告グループのすべての設定を管理できます: - 広告グループの作成 - 既存の広告グループの編集 - 広告グループの開始・一時停止 ## 広告グループとは \{#what-is-ad-group\} 広告グループは[キャンペーン](ads-manager-create-campaign)に属するもので、広告のターゲティングと入札戦略を設定する場所です。各広告グループには入札設定、オーディエンスターゲティング、そして広告をいつ誰に表示するかを決定する[キーワード](ads-manager-manage-keywords)が含まれます。広告グループを使うことで、キャンペーン内の広告戦略を整理し、異なるターゲティングアプローチをテストできます。 :::important キャンペーンは広告グループがなければ配信できません。広告グループはデフォルト入札、オーディエンス、キーワードを設定するレベルであるため、少なくとも1つの広告グループがないとキャンペーンにはターゲティングも入札も設定されず、配信されません。まずキャンペーンを作成してから、[少なくとも1つの広告グループを追加](ads-manager-create-ad-group)してアクティブ化してください。 ::: ## 広告グループを作成する \{#create-ad-groups\} 新しいApple Ads広告グループを作成するには: 1. サイドバーメニューから **Ads Manager** に移動します。どのタブでも、テーブル上の **+** をクリックし、**Create ad group** を選択します。 2. 広告グループを追加するアプリを選択します。 3. 広告グループを追加するキャンペーンを選択します。 4. 広告グループの設定を行います: - **Ad group name**:ダッシュボードで広告グループを識別・検索するために付けるラベルです。 - **Default max CPT bid**:広告のタップ1回に対して支払う最大金額です。この入札額は、個別のキーワード入札を設定しない限り、広告グループ内のすべてのキーワードに適用されます。 - **CPA cap (limits impressions)**(任意):タップスルーコンバージョン(ダウンロードや他のターゲットアクションなど)1件あたりに支払う最大金額を設定します。広告グループ内のすべてのキーワードに対して入札上限を設定します。 入札上限は、設定したCPAキャップにタップスルーコンバージョン率を掛けて計算されます:`CPAキャップ × CR(タップスルー)`。キーワードの最大CPT入札額がこの値より低い場合、低い方の最大CPT入札額が適用されます。 たとえば、CPAキャップが$5でタップスルーコンバージョン率が65%の場合、広告グループ内のすべてのキーワードに適用される最大入札額は$3.25になります。最大CPTが$4に設定されている場合も、適用される最大入札額は$3.25のままです。 - **Search Match**:キーワードを指定しなくても、関連する検索に自動的に広告をマッチさせるトグルです。有効にすると、Apple Adsはアプリのメタデータやカテゴリに関連する検索に対して広告を表示する場合があります。 - **Audience**:どのユーザーに広告を表示するかを決定するターゲティング条件です。 - **All eligible users**:キャンペーンの対象となるすべてのユーザーに広告を表示します。 - **Specific audiences**:以下を設定して特定のユーザーセグメントをターゲットにします: - **Devices**:iPad、iPhone、またはその両方をターゲットにします。 - **Customer type**:すべてのユーザー、新規ユーザー、またはリピーターをターゲットにします。 - **Gender**:性別でターゲットにするか、すべてのユーザーを対象にします。 - **Age range**:特定の年齢層またはすべてのユーザーをターゲットにします。 - **Ad scheduling**(任意):広告の配信開始タイミングを設定します: - **Start date and time**:広告グループが配信を開始する日時です。 - **End date**(任意):広告グループが配信を停止する日付です。 5. **Create** をクリックします。 6. キャンペーンのプレースメントタイプが **Search results** の場合、次に[キーワードを追加](ads-manager-manage-keywords)して広告の配信を開始できます。他のプレースメントタイプの場合は、これで設定完了です。 ## 広告グループを編集する \{#edit-ad-groups\} 作成済みの広告グループを編集するには: 1. 次のいずれかの方法でキャンペーン設定を開きます: - **Ads Manager > Ad groups** で広告グループ名をクリックし、右上の **Edit ad group** をクリックします。 - または広告グループ名の横にあるチェックボックスを選択し、**Actions > Edit ad group settings** をクリックします。 2. 広告グループの設定を変更します。アプリとキャンペーン以外のすべての設定を編集できます。 3. **Save changes** をクリックします。 :::note Apple Adsで直接行った広告グループへの変更はApple Ads Managerに自動的に同期されますが、Apple Ads Managerに反映されるまで時間がかかる場合があります。 ::: ## 広告グループをエクスポートする \{#export-ad-groups\} 広告グループテーブルをCSVとしてエクスポートするには、テーブル上のダウンロードアイコンをクリックし、**Export current page** または **Export all pages** を選択します。 **Export all pages** は、すべてのページの広告グループを1つのファイルにダウンロードします。進行状況モーダルでダウンロードの進捗を確認でき、いつでもキャンセル可能です。2つの任意フィルターが利用できます: - **Enabled only**:アクティブな広告グループのみを含めます。 - **With spend ≥**:指定した閾値以上の支出がある広告グループのみを含めます。 - **Group by country**:各広告グループの行を国別に分割します。 テーブルは、表示するよう選択した列を含め、ダッシュボードに表示されている状態でエクスポートされます。 ## 広告グループを開始・一時停止する \{#launch--pause-ad-groups\} Apple Ads Managerから広告グループを開始または一時停止するには: 1. **Ads Manager > Ad groups** に移動するか、キャンペーンページに移動してその広告グループを確認します。 2. **Status** 列の広告グループ名の横にあるトグルをオンまたはオフに切り替えます。 --- # File: ads-manager-manage-keywords --- --- title: "Apple Ads Managerでキーワードを管理する" description: "Apple Ads Managerで、Apple Adsのキーワード、除外キーワード、SKAGキーワードを追加・管理する方法を説明します。" --- Apple Ads ManagerはApple Adsとの双方向連携を備えており、ほぼリアルタイムのパフォーマンスデータを取得しつつ、ネイティブUIよりはるかに使いやすいAdaptyダッシュボードからキーワードの作成・編集が行えます。 ネイティブのApple Adsダッシュボードでキーワードを作成すると、24時間以内にApple Ads Managerへ自動的に反映されます。 [包括的なアナリティクスの確認](adapty-ads-manager-analytics)に加え、以下のキーワード設定をすべて管理できます。 - 広告グループへのキーワード追加 - 除外キーワードの追加 - SKAG(Single Keyword Ad Group)としてのキーワード追加 - テーブルでのキーワード直接編集 - 複数キーワードの一括操作 - キーワードの開始・一時停止 ## キーワードとは \{#what-are-keywords\} キーワードとは、App Storeの検索結果に広告を表示させるための検索語句です。[広告グループ](ads-manager-create-ad-group)内に整理され、広告グループは[キャンペーン](ads-manager-create-campaign)に属します。この階層構造により、広告戦略を体系的に管理・整理できます。 :::important キーワードは**Search results**プレースメントタイプのキャンペーンにのみ適用されます。他のプレースメントタイプ(Search TabやProduct Pages)のキャンペーンにはキーワードは使用されません。 ::: ### 標準キーワード \{#standard-keywords\} 標準キーワードは、広告を表示させるために入札する主要な語句です。ユーザーがApp Storeでこれらの語句を検索すると、広告が検索結果に表示される場合があります。 ### 除外キーワード \{#negative-keywords\} 除外キーワードは、アプリに関連しない検索で広告が表示されるのを防ぎます。除外キーワードを追加することで、関連性の低い検索への無駄な費用を削減できます。 除外キーワードは広告グループレベルで追加するか、複数のキャンペーンに同時に適用するクロスグループ除外キーワードとして追加できます。 ### SKAGとしてのキーワード(Single Keyword Ad Group) \{#keywords-as-skag-single-keyword-ad-group\} SKAG(Single Keyword Ad Group)は、1つの広告グループに1つのキーワードのみを含む形で個別の広告グループを作成する戦略です。このアプローチにより、以下のメリットが得られます。 - 価値の高いキーワードに対する入札の精密なコントロール - キーワードレベルでのパフォーマンス分析の向上 SKAGは、パフォーマンスの高いキーワードを特定し、専用の広告グループを通じてその可能性を最大化するのに特に有効です。 ## キーワードを追加する \{#add-keywords\} 広告グループにキーワードを追加するには: 1. サイドバーメニューから **Ads Manager** に移動します。任意のタブで、テーブル上の **+** をクリックし、ドロップダウンから **Add keywords** を選択します。 2. モーダルで、キーワードを追加するキャンペーンと広告グループを選択します。1つのキャンペーンで広告グループを選択した後、別のキャンペーンを選択してさらに広告グループをリストに追加できます。 3. **Select** をクリックして次に進みます。 4. **Add keywords** ダイアログで、**Keywords list** フィールドにキーワードを入力します。カンマ区切りのキーワードファイルがある場合は、その内容を貼り付けると、Apple Ads Managerがすべてのキーワードを一括でアップロードします。 5. テーブル内の各キーワードに対して以下を設定します: - **Match type**: **Exact**(完全一致)または **Broad**(部分一致)を選択 - **CPT bid**: このキーワードのタップあたりの最大入札額を設定するか、空欄のままにして広告グループのデフォルト最大CPT入札額を使用 6. キーワードを確認し、**Add X keywords**(Xは追加するキーワード数)をクリックします。 :::important キーワードを保存すると、マッチタイプは変更できません。マッチタイプを変更する必要がある場合は、キーワードを削除して希望のマッチタイプで再度追加してください。 ::: ## 除外キーワードを追加する \{#add-negative-keywords\} 除外キーワードを追加するには: 1. サイドバーメニューから **Ads Manager** に移動します。任意のタブで、テーブル上の **+** をクリックし、ドロップダウンから **Add negative keywords** を選択します。 2. **Add negative keywords to** モーダルで、除外キーワードを追加するレベルを選択します: - **Selected campaigns**: キャンペーンレベルの除外キーワードを追加します。 - **Selected ad groups**: 広告グループレベルの除外キーワードを追加します。 - **All ad groups in selected campaigns**: 選択したキャンペーン内のすべての広告グループに対して広告グループレベルの除外キーワードを追加します。 :::note 以下の点に注意してください: - 広告グループレベルの除外キーワードは、キャンペーンレベルの除外キーワードより優先されます。 - 選択したキャンペーンのすべての広告グループに除外キーワードを追加した場合、後でそのキャンペーンに新しい広告グループを追加するときは手動で追加する必要があります。 ::: 3. **Keywords list** フィールドに除外キーワードを入力します。カンマ区切りのキーワードファイルがある場合は、その内容を貼り付けると、Apple Ads Managerがすべてのキーワードを一括でアップロードします。 4. テーブル内の各キーワードについて、**Match type** を選択します: - **Exact**: 完全に一致するキーワードまたは非常に近い表現のみを除外します。 - **Broad**: キーワードおよび関連する検索語句を除外します。 または、複数のキーワードのチェックボックスを選択してマッチタイプを一括変更します。 5. 除外キーワードを確認し、**Add X keywords**(Xは追加するキーワード数)をクリックします。 :::note クロスグループ除外キーワードは、複数のキャンペーンにわたって特定の検索語句を一度に除外したい場合に特に有効で、時間を節約し広告戦略全体の一貫性を確保できます。 ::: ## SKAGとしてキーワードを追加する \{#add-keywords-as-skag\} SKAG(Single Keyword Ad Group)としてキーワードを追加するには: 1. サイドバーメニューから **Ads Manager** に移動します。任意のタブで、テーブル上の **+** をクリックし、ドロップダウンから **Add keywords as SKAG** を選択します。 2. SKAG広告グループを作成するキャンペーンを選択します。複数のキャンペーンを選択できます。 3. デフォルトでは、すべてのユーザーをターゲットとするデフォルト設定で新しい広告グループが作成されます。変更したい場合は、**Copy settings from ad group** を選択し、設定をコピーする既存の広告グループを選択します。 4. 新しい広告グループの設定を行います: - **Ad group name prefix**: 各広告グループ名に追加するオプションのプレフィックス(例:「SKAG_」と設定すると「SKAG_keyword1」「SKAG_keyword2」などが作成されます)。**Tag** をクリックすると、グループ名にキーワード、キャンペーン名、国を動的に追加できます。 - **CPT bid** と **CPA cap**: すべてのキーワードの入札額を一括設定するか、**Set CPT bid and CPA cap for each word manually** を選択して各キーワードに個別に設定します。 5. **Keywords list** フィールドにキーワードを入力します。カンマ区切りのキーワードファイルがある場合は、その内容を貼り付けると、Apple Ads Managerがすべてのキーワードを一括でアップロードします。 6. テーブル内の各キーワードについて、**Match type** を選択します: - **Exact**: 完全に一致するキーワードまたは非常に近い表現のみにマッチします。 - **Broad**: キーワードおよび関連する検索語句にマッチします。 または、複数のキーワードのチェックボックスを選択してマッチタイプを一括変更します。 7. **Check for duplicates in target campaign** を選択して、対象キャンペーンに同一のキーワードがないか確認します。 8. **Create** をクリックしてSKAG広告グループを作成します。 各キーワードは、選択した各キャンペーン内でそれぞれ独自の広告グループに配置され、個別に管理・最適化できます。 ## キーワードを編集する \{#edit-keywords\} 既存のキーワードを編集するには: 1. **Ads Manager > Keywords** または **Ads Manager > Negative keywords** に移動してテーブルで編集したいキーワードを探すか、キャンペーンページから広告グループページに移動してキーワードを探します。 2. テーブルで直接値を編集します: - **CPT bid**: 入札額をクリックして新しい最大タップあたりコストを入力 - **Status**: トグルスイッチを使ってキーワードを一時停止または有効化 :::note Apple Adsで直接行ったキーワードの編集はApple Ads Managerに自動的に同期されますが、Apple Ads Managerに表示されるまでに時間がかかる場合があります。 ::: ## 一括操作 \{#bulk-actions\} 複数のキーワードに対して一括操作を行うことで、時間を節約しながら効率的にキーワードを管理できます。 一括操作を行うには: 1. **Ads Manager > Keywords** または **Ads Manager > Negative keywords** タブに移動します。 2. 管理したいキーワードの横のチェックボックスを選択して複数のキーワードを選びます。 3. **Actions** ドロップダウンをクリックし、以下のいずれかを選択します: - **Add as keywords**: 選択したキーワードを標準キーワードとして追加 - **Add as negative keywords**: 選択したキーワードを除外キーワードとして追加 - **Add as SKAG**: 選択したキーワードのSingle Keyword Ad Groupを作成 - **Activate**: 選択したキーワードを有効化 - **Pause**: 選択したキーワードを一時停止 - **Edit CPT bids**: 選択したキーワードのCPT入札額を編集します。以下の方法で編集できます: - **Set to**: 複数の入札額を特定の金額に設定します。 - **Increase by/decrease by**: 入札額をUSDまたは入札割合で指定した分だけ増減します。誤って使いすぎを防ぐために、オプションで入札額の上限を設定できます。 - **Set to average CPT**: CPT(タップあたりコスト)指標に合わせて入札額を設定します。乗数係数を設定します。例えば、パフォーマンスが期待を下回っている場合は0.9、上回っている場合は1.1に設定します。 - **Set to average CPA**: CPA(獲得あたりコスト)指標に合わせて入札額を設定します。乗数係数を設定します。 :::tip 一括操作は特に以下の場面で有効です: - 異なるタイプ間(標準、除外、SKAG)でキーワードを変換する - 複数のキーワードに異なるマッチタイプを素早く追加する - パフォーマンスの高いキーワードを絞り込んで入札額を調整する - パフォーマンスの低いキーワードを特定して一時停止する ::: ## キーワードをエクスポートする \{#export-keywords\} キーワードテーブルをCSVとしてエクスポートするには、テーブル上のダウンロードアイコンをクリックして **Export current page** または **Export all pages** を選択します。 **Export all pages** は、すべてのページにわたるすべてのキーワードを1つのファイルにダウンロードします。進行状況モーダルでダウンロードを追跡でき、いつでもキャンセルできます。2つのオプションフィルターが利用可能です: - **Enabled only**: 有効なキーワードのみを含めます。 - **With spend ≥**: 指定した閾値以上の支出があるキーワードのみを含めます。 - **Group by country**: 各キーワード行を国別に分解します。 テーブルはダッシュボードに表示されている状態(選択した列)でエクスポートされます。 ## キーワードレベルのチャートを確認する \{#explore-keyword-level-charts\} **Ads Manager > Keywords** テーブルから、任意のキーワードのチャートを直接開けます。これにより、各キーワードの日別パフォーマンスを精密に分析できます。 チャートを表示するには、テーブルのキーワード横にあるチャートアイコンをクリックします。 デフォルトでは、選択したキーワードの **Spend** 指標がチャートに表示されます。 複数の指標を同時に表示して、相関関係や経時的な変化を把握できます。**+** をクリックして新しい指標を追加します。 **Reset** をクリックしてリセットするか、指標のチェックボックスをオフにして非表示にします。 ## 入札履歴 \{#bid-history\} キーワードの入札履歴を確認するには、テーブルのキーワード横にある **Bid History** ボタンをクリックします。2つのタブを持つパネルが開きます。 - **Metrics** タブには、経時的な指標チャートが表示されます。キーワードレベルのチャートと同じ方法で指標の追加・削除ができます。**+** をクリックして追加するか、チェックボックスをオフにして非表示にします。入札額が変更された各ポイントにマーカーが表示され、マーカーにホバーするとその日の正確な入札額を確認できます。これを使って入札変更とパフォーマンスの変動を関連付けることができ、変更後に指標が下落またはスパイクした場合、マーカーがその発生時点を示します。 - **Bid History** タブには、すべての入札変更が新しい順に表示されるテーブルがあり、変更前後の入札額、各変更の日付、変更のトリガーが確認できます。 --- # File: ads-manager-manage-ads --- --- title: "Apple Ads Managerで広告を管理する" description: "Apple Ads ManagerでApple Adsの広告を作成・編集します。" --- Apple Ads ManagerはApple Adsとの双方向インテグレーションを提供しています。ほぼリアルタイムのパフォーマンスデータを取得でき、ネイティブUIよりもはるかに便利な方法でAdaptyダッシュボードから直接広告を作成・編集できます。 ネイティブのApple Adsダッシュボードで広告を作成した場合、24時間以内に自動的にApple Ads Managerに表示されます。 ## 広告とは \{#what-are-ads\} 広告とは、[キャンペーン](ads-manager-create-campaign)内の[広告グループ](ads-manager-create-ad-group)に割り当てられた広告クリエイティブです。1つの広告グループにつき、アクティブな広告を1つ割り当てることができます。 ## 広告を作成する \{#create-ads\} 始める前に、以下を作成済みであることを確認してください。 - **広告グループ**。[Apple Ads Managerダッシュボードで直接作成](ads-manager-create-ad-group)できます。 - **カスタムプロダクトページ**。[Apple Adsで直接設定](https://developer.apple.com/help/app-store-connect/create-custom-product-pages/configure-multiple-product-page-versions/)する必要があります。広告で使用する前に、App Storeの審査を通過している必要があります。 :::note 選択した広告グループ内にすでにアクティブな広告がある場合、新しい広告を実行するためにその広告は一時停止されます。 ::: 新しいApple Ads広告を作成するには: 1. サイドバーメニューから **Ads Manager** に移動します。任意のタブで、テーブル上部の **+** をクリックし、**Create ad** を選択します。 2. 広告を出稿するアプリを選択します。 3. 広告の広告グループを選択します。 4. 広告名を入力します。 5. 広告のステータスを選択します。後で広告を開始する場合は、**Status** チェックボックスをオフにしてください。 6. **Select CPP** をクリックします。App Storeで承認済みのアプリのカスタムプロダクトページが一覧表示されます。選択できるカスタムプロダクトページは1つのみです。 7. **Create ad** をクリックします。 ## 広告を編集する \{#edit-ads\} :::note 広告を作成した後は、名前のみ編集できます。CPPの変更や別の広告グループへの移動はできません。 ::: 広告名を編集するには、以下のいずれかの方法を使用します。 - **Ads Manager > Ads** で広告名をクリックします。広告名を編集し、隣のチェックマークをクリックします。 - 広告名の横のチェックボックスを選択し、**Actions > Edit ad** をクリックします。広告名を変更し、**Save changes** をクリックします。 :::note Apple Adsで直接行った広告への編集はApple Ads Managerに自動的に同期されますが、Apple Ads Managerに表示されるまで時間がかかる場合があります。 ::: ## 広告をエクスポートする \{#export-ads\} 広告テーブルをCSVとしてエクスポートするには、テーブル上部のダウンロードアイコンをクリックし、**Export current page** または **Export all pages** を選択します。 **Export all pages** は全ページのすべての広告を1つのファイルにダウンロードします。進行状況モーダルでダウンロードを追跡でき、いつでもキャンセルできます。2つのオプションフィルターが利用可能です。 - **Enabled only**: アクティブな広告のみを含めます。 - **With spend ≥**: 指定したしきい値以上の支出がある広告のみを含めます。 - **Group by country**: 各広告の行を国別に分類します。 テーブルは、表示列を選択した状態でダッシュボードに表示されている通りにエクスポートされます。 ## 広告を開始・一時停止する \{#launch--pause-ads\} Apple Ads Managerから任意の広告を開始または一時停止するには、以下のいずれかの方法を使用します。 - **Ads Manager > Ads** の **Status** 列のチェックボックスをオンまたはオフにします。 - 広告名の横のチェックボックスを選択し、**Actions > Edit ad** をクリックします。広告名を変更し、**Save changes** をクリックします。 --- # File: ads-manager-create-segments --- --- title: "Apple Ads ManagerでApple Adsアトリビューションに基づいてセグメントを作成する" description: "Apple Ads Managerでキャンペーン、広告グループ、キーワードから2クリックでセグメントを作成できます。" --- [Apple Ads Manager](adapty-ads-manager) でキャンペーン、広告グループ、またはキーワードを選択し、数クリックでセグメントに変換することで、ユーザー[セグメント](segments)を直接作成できます。セグメントの条件を手動で設定しなくても、獲得ソースに基づいてペイウォールやオファーを簡単にパーソナライズできます。 セグメントを作成したら、異なるプロダクトや価格の割り当て、A/B テストの実施、ペイウォールの外観のカスタマイズに活用できます。 ## ユースケース \{#use-cases\} Apple Ads データから作成したセグメントを実際にどのように活用できるか、具体的な例を紹介します。 - **キーワードベースのペイウォール**。購買意欲の高いキーワードからのユーザーには機能を前面に押し出したペイウォールを、より広範な探索系キーワードからのユーザーには汎用的なペイウォールを表示します。 - **キャンペーンレベルのオファー**。特定の Apple Ads キャンペーン経由のユーザーには長めのトライアルや特別価格を提供し、それ以外のユーザーには標準のオファーを維持します。 - **広告クリエイティブとペイウォールの一貫性**。特定の機能を訴求した広告グループからのユーザーを、その機能を最初に強調したペイウォールへ誘導します。 - **ROIの高いキャンペーンの最適化**。継続的に高い生涯価値をもたらすキャンペーン経由のユーザーには、プレミアム優先・正規価格のペイウォールを表示します。 ## セグメントを作成する \{#create-segments\} Apple Ads Manager からセグメントを作成するには: 1. **Ads Manager** に移動し、**Campaigns**、**Ad groups**、または **Keywords** タブに切り替えます。使用したいエンティティのチェックボックスを選択します。複数のエンティティを選択した場合、エンティティごとに個別のセグメントが作成されるのではなく、それらすべてをまとめた1つのセグメントが作成されます。 2. **Actions > Create segment from campaigns/ad groups/keywords** をクリックします。 3. 必要に応じて、**Create segment** ウィンドウでセグメントの詳細を更新します。 - **Adapty project**: このセグメントを作成したい Adapty 内のアプリ - **Build segment from campaign/ad group**: キャンペーンまたは広告グループからセグメントを作成する場合、このステップで選択したキャンペーンや広告グループを調整できます - **Segment name** - **Segment description** 4. **Create** をクリックします。 5. セグメントが作成されたら、次の方法で活用の準備ができます。 - [プレースメント](placements)に追加して既存のペイウォールまたはオンボーディングと組み合わせる - セグメントのユーザーに表示する新しい[ペイウォール](adapty-paywall-builder)または[オンボーディング](onboardings)をデザインする - [A/B テスト](ab-tests)を実施する --- # File: ads-manager-automations-keyword-rules --- --- title: "Apple Ads Managerのキーワードルール" description: "キャンペーンのパフォーマンスに基づいて、入札額の調整、キーワードの有効化・停止、広告グループ間の移動など、キーワードのライフサイクルを自動的に管理します。" --- キーワードルールは、インストールからトライアル、サブスクリプション、収益までのフルファネルパフォーマンスに基づいて、キーワードに対して自動的に処理を実行します。スペンド、CPA、ROAS、コホートデータなどの指標を使って条件を定義し、その条件が満たされたときにルールが実行するアクションを設定します。 ルールは設定したスケジュールで実行され、手動での操作なしにパフォーマンスの変化に対応します。 ## 利用可能なアクション \{#available-actions\} 各キーワードルールは、条件が満たされたときに1つのアクションを実行します。 | アクション | 内容 | |--------|-------------| | **Change bid** | CPT入札額を増加・減少・設定する | | **Enable keyword** | 停止中のキーワードを再有効化する | | **Pause keyword** | アクティブなキーワードを停止する | | **Add as keyword to…** | 指定した入札額とマッチタイプで別の広告グループにキーワードをコピーする | | **Add as negative keyword to…** | 指定した広告グループまたはキャンペーンにネガティブキーワードとして追加する | ## キーワードルールの作成 \{#create-a-keyword-rule\} キーワードルールは、テンプレートを使うか、ゼロから手動で作成できます。 ### テンプレートから作成する \{#from-a-template\} Adaptyでは、よくある最適化シナリオに対応したすぐに使えるテンプレートを提供しています。主なテンプレートには以下が含まれます。 - **Cut waste on non-converting keywords**: スペンドがXを超え、インストールまたはトライアルが0の場合に入札額を下げる。 - **Scale winning keywords**: ROASが目標を超えるか、CPAが目標を下回る場合に入札額を上げる。 テンプレートからルールを作成するには: 1. 左サイドバーで **Automations** に移動し、**Templates** をクリックします。 2. テンプレートを選択して **Next** をクリックします。 3. 事前に入力された設定を確認・調整します。 - **Rule name**: テンプレート名と現在の日付が自動的に設定されます(例: "Scale Winning Keywords - [2025-11-12]")。 - **Apply to**: ルールを適用するキャンペーングループ、アプリ、キャンペーン、または広告グループを選択します。 - **Conditions**: 必要に応じて事前設定された条件を変更します。 - **Action**: 必要に応じて事前設定されたアクションを変更します。 - **Schedule**: ルールの実行頻度を設定します。 4. **Save** をクリックしてルールを有効化します。 ### 手動で作成する \{#manually\} ゼロからカスタムキーワードルールを作成するには: 1. 左サイドバーで **Automations** に移動し、**Create rule** をクリックして、ルールタイプとして **Keywords** を選択します。 2. わかりやすい **Rule name** を入力します。 3. **Apply to** セクションで、ルールを適用するキャンペーングループ、アプリ、キャンペーン、または広告グループを選択します。 4. **Add condition** をクリックし、リストから[指標](adapty-ads-manager-metrics)を選択します。 指標は、アカウントの通貨で選択した期間に基づいて計算されます。データはほぼリアルタイムで更新されるため、ルールは常に最新のパフォーマンスデータを使用します。 5. 期間(例: 過去3日間または過去7日間)を設定し、比較演算子を選択して、しきい値を入力します。 6. 条件を追加するには、**Add condition** をクリックし、左側で **And** または **Or** 演算子を選択します。 7. **Action** セクションで、条件が満たされたときに実行する処理を選択します。 **Change bid** - **Action type**: **Increase by**、**Decrease by**、または **Set to** を選択します。 - **Value type**: **$**(絶対値)と **%**(ルール実行時の現在の入札額に対する相対値)を切り替えます。 - **Upper bid limit**(任意): 強いシグナルによってルールが繰り返しトリガーされた場合に過剰な入札を防ぐための最大入札上限。 **Enable keyword** - 追加設定なし。条件を満たした停止中のキーワードを再有効化します。 **Pause keyword** - 追加設定なし。条件を満たしたアクティブなキーワードを停止します。 **Add as keyword to…** - **Target ad groups**: コピーしたキーワードを受け取る広告グループを選択します。 - **CPT bid**: コピーしたキーワードの初期入札額を設定します。 - **Match type**: **Exact** または **Broad** を選択します。 - **Skip if keyword already exists**: 有効にすると、ターゲット広告グループにすでに存在するキーワードをスキップします。 **Add as negative keyword to…** - **Scope**: ネガティブキーワードを追加する広告グループまたはキャンペーンを選択します。 - **Match type**: **Exact** または **Broad** を選択します。 8. **Schedule** セクションで: - 頻度を選択します: **Every day**、**Every 2 days**、**Every week** など。 - 実行時刻を選択します(すべての時刻はUTC)。 ルールはUTCでスケジュールされた時刻に実行されます。通常、実行は数分以内に完了し、その後Logsとメインダッシュボードで変更を確認できます。 9. **Save** をクリックしてルールを作成します。 ## ベストプラクティス \{#best-practices\} - **最初は範囲を絞る**: 新しいルールは、広げる前にいくつかのキャンペーンまたは広告グループに適用して動作を確認してください。 - **アクティブなキャンペーンには短い遡及期間を使用する**: 動きの速いキャンペーンでは、30日間より過去3〜7日間の方が通常うまく機能します。 - **スペンドとコンバージョンを組み合わせる**: 単一の指標によるルールは避けてください。より信頼性の高いシグナルを得るために、スペンドとインストール、トライアル、またはROASを組み合わせて使用してください。 - **Change bidルールには入札上限を設定する**: 強いシグナルによってルールが複数回トリガーされた場合に入札が際限なく上がらないよう、上限入札額を設定してください。 - **Enable keywordをコホートデータと組み合わせる**: 初期CPAが悪くて早期に停止されたキーワードも、コホートデータが成熟するにつれてD31またはD61の強いROASを示す場合があります。コホートROASの条件を設定し、目標値を超えたときに自動的に再有効化してください。 - **Add as keyword to…をテストからスケールへのパイプラインに使用する**: テストキャンペーンのキーワードがCPA目標を達成したら、スケールキャンペーンに自動的にコピーします。 - **Add as negative keyword to…でDiscoveryキャンペーンをクリーンに保つ**: キーワードが完全一致キーワードとして確認されたら、同じクエリで競合しないようDiscoveryまたはSearch Matchキャンペーンでネガティブ設定してください。 - **新たに昇格したキーワードへの入札ルール適用は待つ**: [検索語句の自動化](ads-manager-automations-search-terms)を使用してキーワードキャンペーンにキーワードを昇格させた場合は、まずそのキーワードが1〜2日間データを蓄積できるよう待ってください。 --- # File: ads-manager-automations-search-terms --- --- title: "Apple Ads Manager の検索語句オートメーション" description: "勝利した検索語句をキーワードに自動昇格させ、ソースでネガティブ設定することで、手動作業なしにディスカバリートラフィックを拡大できます" --- ディスカバリーキャンペーンとSearch Matchキャンペーンは検索語句データを生成します。そのデータを構造化されたキーワードリストに変換するには、レポートをダウンロードし、語句をフィルタリングして、手動で広告グループに追加する必要があります。検索語句オートメーションはこの作業を自動化します。語句が設定した条件を満たすと、ルールは設定したアクションに基づいて処理を実行します。 検索語句ルールのアクションタイプは2種類あります: - **キーワードとして追加**:語句をターゲット広告グループの完全一致キーワードに昇格させ、必要に応じてソースキャンペーンでネガティブ設定することで重複コストを防ぎます。 - **ネガティブキーワードとして追加**:昇格させずに語句を直接ネガティブ設定します。ディスカバリーキャンペーンやSearch Matchキャンペーンから無関係または無駄なコストが発生する検索語句を除外するために使用します。 **キーワードとして追加**の代表的なユースケース:ディスカバリーまたはSearch Matchキャンペーンで実際のユーザークエリを収集し、パフォーマンスの閾値を超えた語句を検出して、ソースでネガティブ設定しながらProbingキャンペーンに完全一致キーワードとして追加するルールを使用します。Probingキャンペーンとは、管理されたビッドで昇格キーワードをテストするために使用するApple Search Adsキャンペーンです。 **ネガティブキーワードとして追加**の代表的なユースケース:語句が頻繁に表示されるがコンバージョンが発生しない場合(例:インプレッション数は多いがタップ数がゼロ)、予算の無駄遣いを防ぐために自動的にネガティブ設定します。 ## 検索語句オートメーションルールを作成する \{#create-a-search-term-automation-rule\} 検索語句オートメーションルールはテンプレートから作成することも、最初から手動で作成することもできます。 :::note ルールを作成する前に、ディスカバリーキャンペーンまたはSearch Matchキャンペーンがアクティブに実行されており、検索語句データを収集していることを確認してください。完全一致のみのキャンペーンは検索語句レポートを生成しないため、ルールが処理する対象がなくなります。 ::: ### テンプレートから \{#from-a-template\} テンプレートからルールを作成するには: 1. 左サイドバーで **Automations** に移動し、**Templates** をクリックします。 2. テンプレートを選択して **Next** をクリックします。 3. 事前入力された設定を確認・調整します: - **Rule name**:テンプレート名と現在の日付が自動的に設定されます。 - **Apply to**:ルールが検索語句を探すキャンペーングループ、アプリ、キャンペーン、または広告グループを選択します。 - **Conditions**:必要に応じて事前設定された条件を変更します。 - **Actions**:必要に応じてターゲット広告グループ、CPTビッド、ネガティブキーワードのスコープを調整します。 - **Schedule**:ルールの実行頻度を設定します。 4. **Save** をクリックしてルールを有効化します。 ### 手動で \{#manually\} 最初からカスタム検索語句オートメーションルールを作成するには: 1. 左サイドバーで **Automations** に移動し、**Create rule** をクリックして、ルールタイプとして **Search terms** を選択します。 2. ルールの目的を識別するための **Rule name** を入力します。 3. **Apply to** セクションで、ルールが検索語句を探すキャンペーングループ、アプリ、キャンペーン、または広告グループを選択します。 4. **Add condition** をクリックし、リストから[指標](adapty-ads-manager-metrics)を選択します。 指標は選択した期間についてアカウントの通貨で計算されます。データはほぼリアルタイムで更新されるため、ルールは常に最新のパフォーマンスデータを使用します。 5. 期間(例:直近3日間または直近7日間)を設定し、比較演算子を選択して閾値を入力します。 6. 条件を追加するには **Add condition** をクリックし、左側で **And** または **Or** 演算子を選択します。 7. **Action** セクションで、検索語句が条件を満たした場合の処理を選択します: **キーワードとして追加** 一致した検索語句をターゲット広告グループの完全一致キーワードとして昇格させます。 - **Target ad groups**:昇格したキーワードを受け取る広告グループを選択します。ディスカバリーパイプラインを構築するには、Probingキャンペーンや他の構造化キャンペーンの広告グループを選択します。 - **CPT bid**:昇格した各キーワードの初期コストパータップビッドを設定します。オプション:広告グループのデフォルトビッド、検索語句の現在のCPT、または特定の値。 - **Skip if keyword already exists**:有効にすると、ターゲット広告グループにすでに存在する語句をスキップします。 - **Add as negative**:同じ語句をネガティブキーワードとして追加し、同じトラフィックに二重に課金されるのを防ぎます。 - **Scope**:ネガティブキーワードを追加する広告グループを選択します。 :::tip 同じルールで **Add as negative** を有効にすると、語句を構造化キャンペーンに昇格させながら、1ステップでソースでのネガティブ設定も完了します。これによりディスカバリーキャンペーンをクリーンに保ちつつ、キーワードファネルを自動的に構築できます。 ::: **ネガティブキーワードとして追加** 一致した検索語句を昇格させずにネガティブ設定します。 - **Scope**:ネガティブキーワードを追加する広告グループまたはキャンペーンを選択します。 - **Match type**:**Exact** または **Broad** を選択します。 このアクションは、ディスカバリーキャンペーンやMax Conversionキャンペーンから無関係または低品質な検索語句を除外するために使用します。例:インプレッション数が50以上でタップ数がゼロの語句を自動的にネガティブ設定します。 8. **Schedule** セクションで: - 頻度を選択します:**Every day**、**Every 2 days**、**Every week** など。 - 実行時間を選択します(すべての時間はUTCです)。 ルールはUTCでスケジュールされた時間に実行されます。通常は数分以内に完了し、その後ログとメインダッシュボードで変更を確認できます。 9. **Save** をクリックしてルールを作成します。 ルール実行後、**Automations** → **Logs** に移動してルールのエントリを開きます。正常に実行された場合、評価された各検索語句とソースキャンペーン、ターゲット広告グループ、アクション結果、ネガティブ設定の結果が一覧表示されます。語句が表示されない場合は条件が満たされていません。閾値を見直すか、ルックバック期間を延ばしてください。 ## ベストプラクティス \{#best-practices\} - **ソースにはディスカバリーまたはSearch Matchキャンペーンを使用する**:これらのキャンペーンタイプは実際のユーザークエリを収集するため、ルールが評価する検索語句のプールが大きくなります。 - **閾値をルックバック期間に合わせる**:7日間で2回以上のダウンロードが合理的な出発点です。より長い期間(14〜30日間)は実質的な基準が下がり、不定期なコンバージョンでも語句が通過できるようになります。高ボリュームアプリの場合は期間を短縮して閾値を上げてください。 - **昇格させる場合は必ずソースでネガティブ設定する**:Probingキャンペーンでキーワードとして追加してもディスカバリーでネガティブ設定しない場合、両方のキャンペーンが同じクエリで競合します。同じルールで **Add as negative** を有効にしてください。 - **ターゲット広告グループを慎重に選択する**:昇格した語句は幅広いキャンペーンではなく、特定のProbing広告グループにルーティングします。これによりキーワード構造をクリーンに保ち、パフォーマンス分析が容易になります。 - **各実行後にログを確認する**:ログタブで昇格した語句と追加先を確認します。最初のうちはセットアップ後にルールを手動で実行し、期待通りに動作することを検証してください。ログの読み方については[オートメーション](ads-manager-automations#explore-logs)を参照してください。 - **昇格したキーワードにキーワードルールが作用するまで時間を与える**:同じキャンペーンでキーワードルールを使用している場合は、新しく昇格したキーワードを除外するか、ルールが実行される前に1〜2日待ちます。キーワードルールはパフォーマンス履歴のない新しい語句に反応して、コンバージョン前にビッドを下げてしまう可能性があります。 - **インプレッション数が多くタップ数がゼロの語句にはネガティブキーワードとして追加を使用する**:ディスカバリーキャンペーンやMax Conversionキャンペーンでは無関係な検索語句が表示されることがよくあります。「インプレッション数 > 50 AND タップ数 = 0」のルールを使用すると、これらを自動的に検出して、無駄なインプレッションが積み重なる前にネガティブ設定できます。 ## 検索語句をエクスポートする \{#export-search-terms\} 検索語句テーブルをCSVとしてエクスポートするには、テーブル上部のダウンロードアイコンをクリックして **Export current page** または **Export all pages** を選択します。 **Export all pages** は全ページにわたるすべての検索語句を1つのファイルにダウンロードします。進捗モーダルがダウンロードを追跡し、いつでもキャンセルできます。 テーブルは表示されている状態、つまり選択して表示している列でエクスポートされます。 --- # File: ads-manager-market-intelligence --- --- title: "Apple Ads ManagerのMarket Intelligence" description: "50カ国以上で競合他社がどのキーワードでApple Adsを出稿しているかを確認し、キャンペーンに直接追加できます。" --- Market Intelligenceは、Apple Adsで競合他社が入札しているキーワードを50カ国以上にわたって表示します。データは過去30日間の集計で、毎日更新されます。 活用シーン: - **Discoveryキャンペーンをスキップ**: 何が効果的かを探るために予算を使う前に、競合他社がすでに入札しているキーワードを確認できます。初日から実績のあるキーワードリストで始めましょう。 - **競争の少ないキーワードを見つける**: 競合他社のShare of Voice(表示シェア)が低いロングテールキーワードを特定します。競争が少なく、タップ単価が低く、CPAも改善できます。 - **ブランドを守る**: 競合他社がどの国であなたのアプリ名に入札しているかを確認し、そのトラフィックを取り戻しましょう。 - **データを活用して新市場に参入**: 新しい国に1ドルも費やす前に、競合他社がそこでどのキーワードを出稿しているかを確認できます。 - **見落としていた競合他社を発見**: キーワード検索で、カテゴリ内のキーワードでオーガニック上位に表示されているアプリを見つけ、分析に追加できます。 ## Market Intelligence分析を実行する \{#run-a-market-intelligence-analysis\} ### 1. アプリを選択する \{#1-select-your-app\} 左サイドバーで **Market Intelligence** に移動します。ドロップダウンから分析したいアプリを選択し、**Continue** をクリックします。 ### 2. 競合他社を選択する \{#2-select-competitors\} 分析したい競合他社を追加します: - **Suggested competitors(候補)**: Adaptyがアプリのカテゴリをもとに競合候補を自動検出します。リストを確認し、含めたいものを選択してください。 - **キーワードまたはアプリ名で検索**: 検索フィールドにキーワード(例:「budget tracker」)またはアプリ名を入力します。必要に応じて国を変更し、結果からアプリを選択してください。異なるキーワードで繰り返すことで、さまざまな検索意図の競合他社を発見できます。 - **保存済みリスト**: **Create list** をクリックして、最大20件の競合他社を保存し、今後の分析で再利用できます。以前に作成したリストを読み込むこともできます。 競合他社を選択したら、**Run analysis** をクリックします。 ### 3. 結果を確認する \{#3-explore-results\} 結果は **Overview**、**Most Contested**、**By App**、**By Country** の4つのタブに整理されています。 #### Overview \{#overview\} デフォルトのタブで、分析のサマリーを表示します: - **Stats bar**: 分析した競合他社の総数、Apple Adsの活動がある国数、全市場で見つかったユニークキーワード数、最も競争の激しい単一のキーワード。 - **Keywords found by country**: 上位25市場における国別のキーワード件数を示す棒グラフ。 - **Top 10 competitors by keyword coverage**: 各競合他社のキーワード総数、平均Share of Voice(Avg SOV)、アクティブな国を示すランキングテーブル。 #### Most Contested \{#most-contested\} 最も多くの競合他社が同時に入札しているキーワードを表示します。このタブを使って、カテゴリ内の需要の高いキーワードを把握し、競争が最も集中している場所を確認しましょう。検索フィールドでキーワードを絞り込むこともできます。 #### By App \{#by-app\} 競合他社ごとのキーワードデータを表示します。特定アプリのキーワード戦略を国別に掘り下げたいときに使用してください。**Add filter** をクリックして、アプリ、国、またはキーワードで絞り込めます。CSVとしてデータをエクスポートするには、ダウンロードアイコンをクリックします。 #### By Country \{#by-country\} 市場別にグループ化されたキーワードデータを表示します。参入または拡大を検討している特定の国の競合状況を把握したいときに使用してください。**Add filter** をクリックして、アプリ、国、またはキーワードで絞り込めます。CSVとしてデータをエクスポートするには、ダウンロードアイコンをクリックします。 ### 4. キャンペーンにキーワードを追加する \{#4-add-keywords-to-campaigns\} テストする価値のあるキーワードを見つけたら、ツールを離れることなくキャンペーンに追加できます: 1. キーワードテーブルで、使用したいキーワードの横にあるチェックボックスを選択します。表示されているすべてのキーワードを選択するには、テーブルヘッダーのチェックボックスを使用してください。 2. **Add to campaign** をクリックします。 3. キーワード、ネガティブキーワード、SKAGのいずれとして追加するかを選択します。次に、ターゲットのキャンペーンと広告グループを選択し、マッチタイプとCPTビッドを設定して確認します。 ## 結果で注目すべきポイント \{#what-to-look-for\} 結果を確認する際に注目したいパターンを紹介します: - **Share of Voiceが低いロングテールキーワード**: 競合他社のインプレッションシェアが低いキーワードは競争が少ないです。ユーザーの検索意図がより具体的なため、タップ単価が低く、コンバージョン率も高い傾向があります。 - **自分のキャンペーンにまだないキーワード**: 競合他社が出稿しているが、自分はまだ試していないキーワードを探しましょう。これらはカテゴリ内でApple Adsのトラフィックを獲得できることが実証されています。 - **ブランドキーワードのカバレッジ**: 自分のアプリ名で検索してみてください。競合他社が表示される場合、あなたのブランドに入札しています。そのキーワードを積極的なビッドでキャンペーンに追加し、トラフィックを守りましょう。 - **国別のギャップ**: 競合他社がどの国でアクティブかを確認します。競合他社の活動がほとんどない市場は参入しやすく、トラクション獲得に必要な予算も少なく済みます。 --- # File: ads-manager-cpp-ab-tests --- --- title: "Apple Ads ManagerでのCPP A/Bテスト" description: "Apple AdsでカスタムプロダクトページをA/Bテストし、最もパフォーマンスの高いページを見つけましょう。" --- CPP A/B テストでは、Apple Ads内でカスタムプロダクトページ(CPP)同士を比較できます。2〜4つのプロダクトページを選択すると、[Apple Ads Manager](adapty-ads-manager)がそれらの間でトラフィックをローテーションし、パフォーマンスデータを収集して、どのページのコンバージョンが最も高いかを教えてくれます。 **デフォルトプロダクトページ**をバリアントの1つとして含めることができるため、カスタムページが現在のデフォルトよりも優れたパフォーマンスを発揮するかどうかをテストできます。 ## 前提条件 \{#prerequisites\} CPP A/B テストを作成する前に、以下を確認してください: - **Apple Ads Manager が接続されていること**:まだ接続していない場合は、[セットアップガイド](adapty-ads-manager-get-started)に従ってください。 - **テスト対象の広告グループにトラフィックがあること**:テストする広告グループは少なくとも28日以上稼働しており、その期間中にインプレッション、タップ、インストールの実績がある必要があります。Apple Ads Managerはこの履歴を使用して、テスト期間と必要なサンプルサイズを推定します。 - **少なくとも1つのカスタムプロダクトページがあること**:まずApp Store ConnectでCPPを作成してください。Apple Ads Managerは自動的にそれらを読み込みます。 ## CPP A/B テストを作成する \{#create-a-cpp-ab-test\} テストを作成するには、左のサイドバーで **CPP A/B Tests** に移動し、**Create A/B Tests** をクリックします。 ウィザードには4つのステップがあります:**Ad Group(s)**、**Ad Creative(s)**、**Testing Method**、**Review**。 ### 1. Ad Group(s) \{#1-ad-groups\} **Test Name** を入力し、**Select Ad Group** をクリックしてテストしたいCPPを持つ広告グループを選択します。同じキャンペーンから最大4つの広告グループを選択できますが、これは1つの広告クリエイティブを複数の広告グループでテストする場合のみです。複数のCPPを比較するには、1つの広告グループを選択してください。 ### 2. Ad Creative(s) \{#2-ad-creatives\} 比較するCPPを選択します。**Default Product Page**(**Control** としてマーク)と最大3つの**Custom Product Pages**を合わせて、合計2〜4つのバリアントを含めることができます。 - **Default Product Page**:**+ Add Default** をクリックして、既存のデフォルトプロダクトページをコントロールバリアントとして追加します。 - **Custom Product Pages**:**+ Select CPP** をクリックして、App Store Connectからカスタムプロダクトページを選択します。 ### 3. Testing Method \{#3-testing-method\} テストの実行方法を設定します。Apple Ads Managerは**Calculated Test Duration**、**Start Time**、**End Time**を自動的に計算します。以下の3つの設定のいずれかを変更すると、値が更新されます。 #### Switch Time Preset \{#switch-time-preset\} システムがバリアントをローテーションする頻度です。トラフィックレベルに対して高すぎる設定を選択した場合、システムは自動的にダウングレードします。 | インターバル | 典型的なトラフィックレベル | スロット期間 | 典型的なテスト期間 | |--------------|----------------------------------------|---------------|---------------------| | **Hourly** | 高(1日あたり5,000以上のインプレッション) | 7時間 | 数日 | | **Daily** | 通常 | 24時間 | 数週間 | | **Weekly** | 低(1日あたり400未満のインプレッション) | 7日 | 数ヶ月 | **スロット**とは、システムが次のバリアントへの切り替えを検討する前に、1つのバリアントが実行される基本時間です。 #### Desired Precision \{#desired-precision\} テストで確実に検出できるコンバージョン率の最小差異です。オプション:**1%**、**2%**、**3%**、**4%**、**5%**。デフォルト:**5%**。精度1%のテストは小さな差異を検出できますが、より多くのデータが必要でテスト期間が長くなります。精度5%のテストは早く終わりますが、大きな差異しか検出できません。 | 精度 | 使用するタイミング | |-----------|-----------------------------------------------------------------------------------| | 1〜2% | CPP間の差異が小さいと予想され、トラフィックの多い広告グループがある場合。 | | 3〜4% | ほとんどのテストに適したバランスのとれたデフォルト。 | | 5% | 明確な勝者が出ると予想され、早く結果を得たい場合。 | #### Confidence Level \{#confidence-level\} 結果がランダムノイズではなく実際のものである確信度です。オプション:**80%**、**85%**、**90%**、**95%**、**99%**。デフォルト:**90%**。信頼度が高いほど、より多くのデータが必要です。 | 信頼度 | トレードオフ | |------------|---------------------------------------------------------------------------------| | 80〜85% | 早く終わりますが、結果がノイズである可能性が高くなります。 | | 90% | ほとんどのテストに推奨されるデフォルト。 | | 95〜99% | 最も保守的。最も多くのデータと最長のテスト期間が必要です。 | ### 4. Review \{#4-review\} 概要(選択した広告グループ、クリエイティブ、テスト方法、期間、精度、信頼度)を確認し、**Start CPP A/B Tests** をクリックします。 テストを開始すると、システムはバリアントごとに広告グループを複製し、最初のバリアントをアクティブにします。テストのステータスは数分以内に **Running** に移行します。 ## 実行中のテストを監視する \{#monitor-a-running-test\} テスト一覧を開くには、左のサイドバーで **CPP A/B Tests** に移動します。ページ上部の4つのタブでテストを状態別にフィルタリングできます: - **Live**:現在実行中のテスト。 - **Completed**:完了したテスト。 - **Draft**:まだ開始されていないテスト。 - **Archive**:メインビューに表示する必要がなくなった古いテスト。 各テストカードには、名前、ステータス、スイッチインターバル、希望精度、実行時間が表示されます。**View metrics** をクリックするとバリアントテーブルが展開されます。 ### バリアントのパフォーマンス \{#variant-performance\} バリアントテーブルは、テスト内のすべてのバリアントのパフォーマンスを比較します: | 列 | 説明 | |--------------------------|-----------------------------------------------------------------------------------------------------| | **Variant Name** | テスト対象のCPP。バリアントAは常に最初に追加したバリアントです。 | | **Confidence Level** | 必要なサンプルサイズに対するバリアントの達成率(0〜100%)。 | | **Impressions** | Appleがこのバリアントの広告を表示した回数。 | | **TTR** | タップスルー率:インプレッション数に対するタップ数の割合。 | | **Tap → Download CR** | タップからダウンロードへのコンバージョン率。 | | **CPT** | タップあたりの平均コスト。 | | **Avg CPA (Tap-Through)** | タップスルーダウンロードに基づく獲得あたりの平均コスト。 | | **Spend** | バリアントに帰属する総支出。 | | **Revenue** | バリアントに帰属する総収益。 | | **ROAS** | 広告費用対効果:支出に対する収益の割合。 | 各バリアントのインプレッション数が同程度になるまで、Apple Ads Managerは勝者をハイライトしません。データがまだ集計中の場合、テーブルの上にバナーが表示されます:**Winner highlighting is paused — variants don't have comparable impressions yet.** ### 詳細指標 \{#detailed-metrics\} テストのより詳細なビューを表示するには、**View metrics** をクリックして詳細指標ページを開きます。このページには、コホートリテンション曲線、ARPPU比較、および2つのセクションに分類された指標テーブルが含まれています: - **Top of funnel · Apple Search Ads**:バリアントごとのTTR、ダウンロード率、CPM、CPT、平均CPA。 - **Bottom of funnel · Monetization**:バリアントごとの有料ユーザー数、有料CR、有料獲得コスト、ARPPU、収益、ROAS。 **Winner** 列は、各指標でどのバリアントがリードしているかを示します。バリアントが主要指標でリードし、信頼度が少なくとも95%に達した場合にのみ、そのバリアントが総合的な勝者としてマークされます。 指標の定義については、[Apple Ads Managerの指標](adapty-ads-manager-metrics)を参照してください。 ## テストを停止する \{#stop-a-test\} テストはいつでも停止できます。テストは **Stopped** としてマークされ、元の広告グループが復元され、複製された広告グループは一時停止されます。 実行中のテストを停止するには: 1. 左のサイドバーで **CPP A/B Tests** に移動します。 2. テストカードの **Stop A/B test** をクリックするか、テストを開いて **Stop Test** をクリックします。 3. **Stop A/B Test?** ダイアログで確認します。 :::important テストの停止は最終的な操作です。再開することはできません。これまでに収集された結果は **Completed** タブで引き続き確認できます。 ::: ## テストのステータス \{#test-statuses\} すべてのテストは固定のステータスの流れを経ます: | ステータス | 意味 | |---------------|------------------------------------------------------------------------------------------| | **Draft** | テストは作成されましたが開始されていません。まだ編集できます。 | | **Starting** | セットアップ中——システムが広告グループを複製して広告を作成しています。 | | **Running** | テストが実行中です。バリアントがローテーションされ、指標が収集されています。 | | **Completed** | 予定された期間が終了したか、信頼度に達しました。元の広告グループが復元されます。 | | **Stopped** | テストを手動で停止しました。元の広告グループが復元されます。 | | **Failed** | セットアップに失敗したか、連続エラーが多すぎました。失敗したテストは再起動できます。 | ## 仕組み \{#how-it-works\} Apple Ads Managerは**広告グループスイッチ**方式を使用します: 1. テストが開始されると、システムはバリアントごとにソース広告グループを1回複製します。各複製は異なるCPP(そのうちの1つはデフォルトページでも可)を指します。 2. 一度に実行される複製は1つだけです。システムは固定のスケジュール(毎時、毎日、または毎週)でアクティブな複製をローテーションします。 3. テスト実行中は元の広告グループが一時停止されます。テスト終了時には以前の状態に復元されます。 4. Apple Ads Managerはバリアントごとのインプレッション、タップ、ダウンロードを収集し、各バリアントが統計的に意味のあるサンプルにどれだけ近づいているかを追跡します。 5. 各バリアントが十分なデータを収集するか、予定された期間に達すると、テストは自動的に終了します。 ## テスト実行中に期待されること \{#what-to-expect-while-a-test-runs\} ダッシュボードで実行中のテストがどのように動作するかについて、知っておくべきことがいくつかあります: - **バリアントは固定の時間に切り替わるわけではありません**:スイッチインターバルは基準となる設定ですが、Apple Ads Managerは各バリアントが公平な割合のインプレッションを収集できるようにタイミングを調整します。バリアントがインプレッション数で遅れている場合、1スロットよりも長くアクティブな状態が続くことがあります。 - **End Timeが延長される場合があります**:予定終了時刻が近づいてもバリアントのデータが不足している場合、タップの収集を続けるためにテストが自動的に延長されます。新しいEnd Timeがテストカードに表示されます。 - **テスト終了時に元の広告グループが復元されます**:複製されたすべての広告グループが一時停止され、ソース広告グループはテスト前の状態に戻ります。結果は **Completed** タブで引き続き確認できます。 --- # File: ads-manager-settings --- --- title: "Apple Ads Managerの設定" description: "Apple Ads Managerで設定を構成します。" --- Apple Ads Managerダッシュボードの左下にある **Settings** に移動して、アカウント設定を構成します。 ## キャンペーングループ \{#campaign-groups\} **Campaign groups** タブでは、Apple Ads Managerに接続されているすべてのApple Adsアカウントを確認したり、新しいアカウントを追加したりできます。複数のApple Adsアカウントを接続すると、それらすべてのアナリティクスが1つのApple Ads Managerダッシュボードに集約されます。 新しいApple Adsアカウントを追加するには、**Connect Apple Ads account** をクリックし、[ガイド](adapty-ads-manager-get-started)に従って操作してください。 ## サブスクリプションの管理 \{#manage-subscription\} **Manage subscription** タブでは、現在のサブスクリプションプランを確認したり、支払い方法を更新したりできます。 ## ユーザー設定 \{#user-settings\} **User settings** タブでは、**Hide Paused by Default** スイッチをオンにできます。有効にすると、一時停止中のキャンペーン、広告グループ、キーワードが非表示になり、アクティブなパフォーマンスデータに集中しやすくなります。 キャンペーン、広告グループ、キーワードの起動と一時停止を頻繁に試している場合は、このオプションを有効にしないことをお勧めします。一時停止したアイテムにいつでもアクセスできるようにしておく必要があるためです。 --- # File: adapty-user-acquisition --- --- title: "ユーザーアクイジション(Adapty UA)" description: "MMP が不要になり、アプリ全体の経済を一か所で計算できます。" --- <CustomDocCardList ids={['user-acquisition', 'ua-analytics', 'ua-integrations', 'ua-tracking-links', 'ua-deferred-data']} /> Adapty ユーザーアクイジションは、広告キャンペーンとアプリインストール・サブスクリプション収益を紐づけるアトリビューションソリューションです。広告プラットフォーム、トラッキングリンク、アプリのデータを統合し、すべてのアクイジションデータを一か所に集約した統合マーケティング分析ダッシュボードを提供します。 - すべてのチャネルにわたる ROAS(広告費用対効果)を算出 - アプリ全体の経済状況をひとつの画面で把握 - より良い意思決定のための正確なアトリビューションデータを取得 - コホートパフォーマンスとユーザー行動を時系列で分析 :::tip Adapty ユーザーアクイジションがどのように役立つか詳しく知りたい方は、[ミーティングを予約](https://calendly.com/tnurutdinov-adapty/30min)してください。 ::: ## Adapty UA を使う理由 \{#why-adapty-ua\} ユーザーアクイジションのパフォーマンス計測は簡単ではありません。データはプラットフォーム間に分散し、プライバシーの変化でアトリビューションが難しくなり、カスタムソリューションの構築には多大な時間がかかります。 Adapty UA は、単一のマーケティングダッシュボードに組み込みのアトリビューションと統合アナリティクスを提供します。広告費からインストール、サブスクリプション収益まで、すべてのアクイジション指標が自動的に集約されリアルタイムで更新されます。スプレッドシートでデータを照合したり、複数のツールを切り替えたりする必要はもうありません。データ管理ではなく、アプリの成長に集中できます。 ## 仕組み \{#how-it-works\} Adapty ユーザーアクイジションは、広告プラットフォーム、トラッキングリンク、アプリのデータを組み合わせ、アプリインストールとサブスクリプション収益を広告キャンペーンに紐づけます。 概要: - 広告プラットフォームはキャンペーン構造と広告費を提供 - Adapty UA で生成されたトラッキングリンクがウェブからアプリインストールへのキャンペーンコンテキストを運ぶ - Adapty SDK がアプリからインストールイベントと収益イベントを送信 アトリビューションの流れは以下のとおりです: 1. **Adapty UA でトラッキングリンクを生成し、広告キャンペーンに追加します。** リンクにはプラットフォーム、キャンペーン、広告セット、クリエイティブなどのキャンペーンパラメータが含まれています。 2. **ユーザーが広告をクリックし、アプリストアからアプリをインストールします。** ユーザーはトラッキングリンク経由でリダイレクトされ、App Store または Google Play からアプリをインストールします。 3. **アプリが Adapty にインストールイベントを送信します。** 初回起動時に、Adapty SDK がインストールイベントを送信します。Adapty はそのインストールに紐づくキャンペーンパラメータを抽出します。 4. **インストールがキャンペーンに紐づけられます。** トラッキングリンクのキャンペーンパラメータを使って、Adapty はそのインストールを生成元のキャンペーンに関連付けます。 5. **広告費と収益が連携されます。** Adapty はサポートされている広告プラットフォーム(現在は Meta Ads と TikTok for Business)から広告費データを取得し、サブスクリプションや購入イベントをアトリビュート済みのインストールに紐づけます。 その結果、Adapty はインストール数、収益、LTV、ROAS といったキャンペーンレベルの指標を統合アナリティクスダッシュボードで提供します。コホートの分析、パフォーマンスの時系列追跡、データドリブンな最適化の意思決定が、異なるソースのデータを手動で照合することなく実現できます。 :::tip トラッキングリンクにカスタムパラメータを含めることもでき、アプリがインストールイベントを処理する際に[ディファードディープリンク](ua-deferred-data)を扱ったりキャンペーンデータに応じた処理を行ったりできます。 ::: --- # File: user-acquisition --- --- title: "Adapty User Acquisitionを始める" description: "Adapty User Acquisitionに接続して広告費用とサブスクリプション収益を統合し、アプリ全体の経済状況を一か所で確認しましょう。" --- Adapty User Acquisitionは、ウェブからアプリへのキャンペーンにおいて広告費用とサブスクリプション収益を紐付け、アプリ全体の経済状況を一か所で把握できるようにします。 収益データをAdapty User Acquisitionで確認するには、まずAdaptyダッシュボードでインテグレーションを有効にする必要があります。APIキー、トークン、識別子などを渡す必要はありません。Adapty SDKを更新して設定するだけです。 :::important User Acquisitionは以下のバージョンで利用できます: - iOS、Android、Flutter SDK バージョン 3.9.1 以上 - React Native、Capacitor SDK バージョン 3.10.0 以上 - Unity SDK バージョン 3.12.0 以上 - Kotlin Multiplatform SDK バージョン 3.15.0 以上 ::: ## 始める前に \{#before-you-start\} 収益データとキャンペーンのパフォーマンスを紐付けるために、Adaptyで購入を追跡できるようにしましょう: - **すでにAdaptyでアプリ内課金を実装済みの場合**、この段階で追加の作業は不要です。 - **まだアプリ内課金を実装しておらず、Adaptyを使用したい場合**、[クイックスタートガイド](quickstart)の手順を完了して、購入処理をAdaptyに委任してください。 - **Adaptyなしですでにアプリ内課金を実装済みで、Adaptyへの移行を予定していない場合**、[オブザーバーモードでプラットフォーム向けAdapty SDKをインストール](implement-observer-mode)してください。この段階では、SDKをプロジェクトに追加し、オブザーバーモードを有効にして起動し、トランザクションを報告するだけで構いません。 この設定によってウェブからアプリへのアトリビューションが有効になります: - ユーザーがアプリをインストールすると、Adapty SDKはリンクパラメーターからインストール情報を取得し、Adapty UAがキャンペーン詳細を取得できるようになります。 - Adapty SDKはアプリ内のすべての収益関連イベントを把握し、それらをウェブキャンペーンにアトリビュートできます。 ## ステップ1. User Acquisitionインテグレーションを有効にする \{#step-1-enable-the-user-acquisition-integration\} 収益イベントをAdapty UAへ送信するには: 1. Adaptyダッシュボードで [Integrations > Adapty](https://app.adapty.io/integrations/user-acquisition) に移動します。 2. トグルをオンにします。 イベントが発火し始めると、各イベントについて以下の詳細を確認できます: - イベント名 - ステータス - 環境 - 日時 <img src="/assets/shared/img/toggle-ua.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### サポートされているイベント \{#supported-events\} デフォルトでは、Adaptyはユーザーアクイジションへ3つのグループのイベントを送信します: - トライアル - サブスクリプション - 問題 サポートされているイベントの全一覧は[こちら](events)で確認できます。 <img src="/assets/shared/img/events-ua.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## ステップ2. 広告プラットフォームを接続してトラッキングリンクを追加する \{#step-2-connect-your-ad-platform-and-add-tracking-links\} Adaptyはトラッキングリンクを使ってアプリのインストールとキャンペーンデータを紐付けます。 Adapty UAで計測したいすべての広告キャンペーンで、トラッキングリンクを遷移先URLとして使用する必要があります。 複数のプラットフォームで広告を配信する場合は、プラットフォームごとにトラッキングリンクを設定してください。 Adaptyが広告プラットフォームと連携する方法は2つあります: - **ネイティブインテグレーション(Meta Ads、TikTok Ads)。** Adaptyが広告プラットフォームに直接接続します。トラッキングリンクは自動的に生成され、キャンペーンパラメーターはリンクが使用される場所に応じて動的に設定されます。異なるキャンペーン、広告セット、クリエイティブで同じリンクを使用でき、Adaptyは正しいキャンペーンデータと広告費用を自動的に受け取ります。 - **トラッキングリンクのみ(その他すべての広告プラットフォーム)。** Adaptyは広告プラットフォームに接続しません。トラッキングリンクは手動で作成し、すべてのキャンペーンパラメーターはリンク作成時に明示的に定義する必要があります。これらのプラットフォームでは広告費用データは利用できません。 <Tabs> <TabItem value="meta" label="Meta Ads" default> Meta Ads用のトラッキングリンクを作成するには: 1. Adapty UAダッシュボードで [Integrations > Meta](https://app.adapty.io/ua/integrations/facebook/accounts) に移動し、**Continue with Facebook** をクリックします。 2. Facebookアカウントでサインインし、**Continue** をクリックします。 3. 要求された権限を確認し、**Save** をクリックします。 4. **Web campaigns** タブに切り替え、**Create campaign** をクリックします。アプリを選択し、**Save** をクリックします。 5. **General** タブで **iOS** および/または **Android** セクションを展開し、App StoreおよびまたはGoogle PlayのアプリケーションURLを貼り付けます。その後、**Save** をクリックします。 6. **one link**または各プラットフォーム専用リンクの **Click link** フィールドの値をコピーします。次に、Meta Ads Managerで広告を開き、このリンクを遷移先URLとして貼り付けます。 :::important **Website URL** フィールドには `https://api-ua.adapty.io/api/v1/attribution/click` を貼り付けてください。残りのリンクは **Tracking** セクションの **URL parameters** フィールドに貼り付けます。これにより、Meta広告の審査が通りやすくなります。詳細は[Meta Ads Managerでの広告設定に関する推奨事項](meta-create-campaign)をご覧ください。 ::: 7. Meta Adsで広告を配信すると、そのデータがAdapty UAダッシュボードで分析できるようになります。 </TabItem> <TabItem value="tiktok" label="TikTok for Business"> TikTok for Business用のトラッキングリンクを作成するには: 1. Adapty UAダッシュボードで [Integrations > TikTok Ads](https://app.adapty.io/ua/integrations/tiktok/accounts) に移動し、**Continue with TikTok** をクリックします。 2. TikTokアカウントでサインインし、**Continue** をクリックします。 3. 要求された権限を確認し、**Save** をクリックします。 4. **Web campaigns** タブに切り替え、**Create campaign** をクリックします。アプリを選択し、**Save** をクリックします。 5. **General** タブで **iOS** および/または **Android** セクションを展開し、App StoreおよびまたはGoogle PlayのアプリケーションURLを貼り付けます。その後、**Save** をクリックします。 6. **one link**または各プラットフォーム専用リンクの **Click link** フィールドの値をコピーします。次に、TikTok Ads Managerで広告を作成する際、**Advanced Settings** セクションの **Tracking URL** フィールドにこの値を貼り付けます。これにより、AdaptyはTikTokの広告にインストールと購入を紐付けられます。[TikTok Adsでのキャンペーン設定ガイド](tiktok-create-campaign)もご参照ください。 7. TikTok for Businessで広告を配信すると、そのデータがAdapty UAダッシュボードで分析できるようになります。 </TabItem> <TabItem value="others" label="Other ad platforms"> その他の広告プラットフォーム向けのトラッキングリンクを作成するには: 1. Adapty UAダッシュボードのサイドバーメニューから **Tracking links** に移動し、**Create link** をクリックします。 2. リストからアプリを選択し、**Next** をクリックします。 3. 追跡したいキャンペーンと広告に合わせてリンクパラメーターを入力します。 4. デフォルトではOne Linkを作成します。これはユーザーのプラットフォームを自動検出し、クリックを追跡した後にApp StoreまたはGoogle Playへリダイレクトします。 プラットフォームごとに別々のリダイレクトURLを使用したい場合は、**One Link** チェックボックスの選択を外し、プラットフォーム専用のストアリンクを手動で入力してください。 5. **Create** をクリックします。 6. トラッキングリンクのページを開き、以下のいずれかのセクションから **Click link** をコピーします: - **One link** – クリックを追跡し、ユーザーを適切なストアへ自動リダイレクトするリンクです。 - **iOS link** または **Android link** — ストアごとに別々のリンクが必要な場合の、プラットフォーム専用バージョンです(任意)。 7. 広告プラットフォームに移動し、広告の遷移先URLとしてリンクを貼り付けます。 </TabItem> </Tabs> ## ステップ3. ウェブからアプリへのキャンペーンを開始して結果を確認する \{#step-3-launch-your-web-to-app-campaign-and-view-results\} キャンペーンが稼働し、ユーザーがアプリをインストールし始めると、Adaptyはインストールと収益をキャンペーンにアトリビュートし始めます。 [Adapty UAアナリティクスダッシュボード](ua-analytics)では、以下のようなキャンペーンレベルの指標を確認できます: - インストール数とコンバージョン数 - サブスクリプションと購入による収益 - 広告プラットフォーム、キャンペーン、広告セット、クリエイティブ別のパフォーマンス内訳 指標は、アプリからインストールおよび収益イベントを受信した時点で表示されます。広告費用データはネイティブインテグレーションを持つプラットフォームでのみ利用できます。 ## 詳しく学ぶ \{#learn-more\} Adapty User Acquisitionのアナリティクスと主要な広告プラットフォームでのキャンペーン運用に関する詳細なドキュメントをご覧ください: - [**Adapty UAのアナリティクス**](ua-analytics):アナリティクスダッシュボードの効果的な使い方を確認できます。 - [**Adapty UAの指標**](ua-metrics):ユーザーアクイジション分析に利用できる指標を確認できます。 - [**インテグレーション**](ua-integrations):Adapty UAがサポートする広告プラットフォームとインテグレーションを確認できます。 - [**Meta Ads Managerでの広告配信**](meta-create-campaign):Meta Ads Managerでのキャンペーン設定・配信方法を確認できます。 - [**TikTok for Businessでの広告配信**](tiktok-create-campaign):TikTok for Businessでのキャンペーン設定・配信方法を確認できます。 --- # File: ua-metrics --- --- title: "Adapty UA の指標" description: "Adapty UA で利用可能な指標について説明します。" --- Adapty User Acquisition は、キャンペーンのパフォーマンスとユーザー行動を測定するための包括的な**指標**を提供します。これらの指標は標準値として利用でき、一部の指標はユーザーグループの時系列分析用の**コホート指標**としても提供されます。 ## 標準指標 \{#standard-metrics\} | **指標** | 説明 | コホート | |-----------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------| | **Spend** | 広告への各ユーザータップのコストの合計。 | なし | | **Impressions** | 選択した期間内に広告が表示された回数。 | なし | | **Clicks** | レポート期間内にユーザーが広告をクリックした回数。 | なし | | **CPI** | **CPI(インストール単価)**はインストール1件あたりの支払い額。<br/>**計算式**: `Spend / Installs` | なし | | **CPC** | **CPC(クリック単価)**は広告1クリックあたりの支払い額。<br/>**計算式**: `Spend / Clicks` | なし | | **CPM** | **CPM(千回表示単価)**は広告1,000インプレッションあたりの支払い額。<br/>**計算式**: `Spend / (Impressions / 1000)` | なし | | **ICR** | **ICR(インストールコンバージョン率)**は広告クリックのうちインストールに至った割合。<br/>**計算式**: `(Installs / Clicks) × 100%` | なし | | **IPM** | **IPM(千回表示あたりインストール数)**は広告1,000インプレッションあたりのインストール数。<br/>**計算式**: `(Installs / Impressions) × 1000` | なし | | **CTR** | **CTR(クリック率)**はインプレッションのうちクリックに至った割合。<br/>**計算式**: `(Clicks / Impressions) × 100%` | なし | | **Inline link clicks** | 広告クリエイティブまたはアプリページのインラインリンクをユーザーがクリックした回数。 | なし | | **Cost per inline link click** | インラインリンク1クリックあたりの平均支払い額。<br/>**計算式**: `Spend / Inline Link Clicks` | なし | | **Inline link click CTR** | インプレッションのうちインラインリンクのクリックに至った割合。<br/>**計算式**: `(Inline Link Clicks / Impressions) × 100%` | なし | | **Installs** | レポート期間内にアプリをインストールしたユーザーの総数(再インストールを含む)。 | なし | | **Revenue** | 選択した期間内にこのキャンペーンに紐づく購入から発生した収益の合計(ストア手数料控除前)。 | あり | | **ROAS** | **ROAS(広告費用対効果)**は広告収益を広告費で割ってパーセンテージで表したもの。<br/>**計算式**: `(Revenue / Spend) × 100%(Spend > 0 の場合、それ以外は 0%)` | あり | | **ARPU** | **ARPU(ユーザーあたり平均収益)**はコホート内のユーザーあたり平均収益。<br/>**計算式**: `Revenue / Users` | あり | | **LTV** | **LTV(ライフタイムバリュー)**はユーザーのライフタイムにわたって帰属する平均収益。<br/>**計算式**: `Revenue / Installs` | なし | | **Cost per trial** | トライアル開始1件あたりの平均支払い額。<br/>**計算式**: `Spend / Count trial started` | なし | | **Cost per subscription** | サブスクリプションプロダクト購入1件あたりの平均支払い額。<br/>**計算式**: `Spend / Count subscription started` | なし | | **Count subscription events** | レポート期間内のサブスクリプション関連イベントをカウントする指標グループ。含まれる指標:<br/>- Count subscription started<br/>- Count subscription renewed<br/>- Count subscription renewal cancelled<br/>- Count subscription renewal reactivated<br/>- Count subscription expired<br/>- Count [subscription deferred](https://adapty.io/glossary/subscription-purchase-deferral/)<br/>- Count subscription refunded | あり | | **Count trial events** | レポート期間内のトライアル関連イベントをカウントする指標グループ。含まれる指標:<br/>- Count trial started<br/>- Count trial converted<br/>- Count trial expired<br/>- Count trial renewal reactivated | あり | | **Count billing issue detected** | レポート期間内に検出された請求問題の件数。 | あり | | **Count entered grace period** | 請求問題によりグレース期間に入ったサブスクリプションの件数。 | あり | | **Count non-subscription events** | レポート期間内の非サブスクリプション関連イベントをカウントする指標グループ。含まれる指標:<br/>- Count non-subscription purchased<br/>- Count non-subscription refunded | あり | | **Subscription events rate** | レポート期間内にアプリインストールに対するサブスクリプション関連イベントの割合を示す指標。含まれる指標:<br/>- Rate subscription started<br/>- Rate subscription renewed<br/>- Rate subscription renewal cancelled<br/>- Rate subscription renewal reactivated<br/>- Rate subscription expired<br/>- Rate [subscription deferred](https://adapty.io/glossary/subscription-purchase-deferral/)<br/>- Rate subscription refunded | あり | | **Trial events rate** | レポート期間内にアプリインストールに対するトライアル関連イベントの割合を示す指標。含まれる指標:<br/>- Rate trial started<br/>- Rate trial converted<br/>- Rate trial expired<br/>- Rate trial renewal reactivated | あり | | **Rate billing issue detected** | レポート期間内にアプリインストールに対する請求問題の割合。 | あり | | **Rate entered grace period** | レポート期間内にアプリインストールに対するグレース期間に入ったサブスクリプションの割合。 | あり | | **Non-subscription events rate** | レポート期間内にアプリインストールに対する非サブスクリプション関連イベントの割合を示す指標。含まれる指標:<br/>- Rate non-subscription purchased<br/>- Rate non-subscription refunded | あり | ## 予測指標 \{#predicted-metrics\} 予測指標は、アプリ自身の過去データからコホートの将来のパフォーマンスを予測します。D30、D60、D90、D180、D360など複数のコホート期間で利用でき、日数単位でカスタム期間を追加することも可能です。これらの値の計算方法については、[Adapty UA の予測指標](ua-predicted-metrics)を参照してください。 | **指標** | 説明 | コホート | |---------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------| | **pRevenue** | コホートが目標期間までに生み出すと予測される総収益。アプリの過去のコホートリテンションをモデル化したもの。 | あり | | **pROAS** | 同じ期間にわたる広告費用対効果の予測値。**計算式**: `(pRevenue / Spend) × 100%` | あり | | **pAdProfit** | 期間中の広告費控除後の予測収益。**計算式**: `pRevenue − Spend` | あり | | **pARPU** | 期間中のインストールあたり平均予測収益(予測 LTV)。**計算式**: `pRevenue / Installs` | あり | | **pARPPU** | 期間中の課金ユーザーあたり平均予測収益。**計算式**: `pRevenue / paying users at d{N}`(`d{N}` は選択した期間に対応) | あり | --- # File: ua-predicted-metrics --- --- title: "Adapty UAにおける予測指標" description: "Adapty UAでコホートの収益、ROAS、広告利益、LTVを予測する。" --- :::important この記事はAdapty User Acquisitionにおける予測についてのみ説明しています。コホート分析ページでの予測LTVと収益については、[コホートにおける予測](predicted-ltv-and-revenue)をご覧ください。 ::: Adapty UAは各コホートの将来の収益とユニットエコノミクスを予測するため、キャンペーンが成熟する前に比較できます。予測はアプリ自身の過去のコホートデータをもとに生成され、毎日更新されます。長いサブスクリプションサイクルをまだ完了していない直近のコホートの評価に特に有用です。 ## 予測指標 \{#predicted-metrics\} | **指標** | 説明 | |---------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **pRevenue** | コホートが目標期間までに生み出すと予測される総収益。アプリの過去のコホートリテンションからモデル化されます。 | | **pROAS** | 同じ期間における広告費用対効果の予測値。**計算式**: `(pRevenue / Spend) × 100%` | | **pAdProfit** | 期間内の広告費用を差し引いた予測収益。**計算式**: `pRevenue − Spend` | | **pARPU** | 期間内のインストール1件あたりの予測平均収益(予測LTV)。**計算式**: `pRevenue / Installs` | | **pARPPU** | 期間内の課金ユーザー1人あたりの予測平均収益。**計算式**: `pRevenue / paying users at d{N}`(`d{N}`は選択した期間に対応) | `pRevenue`が基本値です。他の4つの指標は、モデルを個別に実行するのではなく、支出・インストール数・課金ユーザー数といった実際のコホートデータを用いて`pRevenue`から算出されます。 予測指標はそれぞれ、D0、D3、D7、D30、D60、D90、D180、D360という複数のコホート期間で利用できます。日数を指定してカスタム期間を追加することも可能です。この期間は、コホートのインストール日から何日先まで値を予測するかを定義します。 ## 予測の計算方法 \{#how-predictions-are-calculated\} 予測は各アプリの過去のコホートをもとに構築されます。モデルはベースライン日以降に過去コホートの収益がどのように増加したかを計測し、同じ軌跡を使って現在のコホートの将来を予測します。 ### ベースライン日 \{#baseline-day\} 予測はコホートがベースライン日に達した後にのみ利用可能になります。ベースライン日とは、コホートの初期収益の90%が通常受け取られる最初の日です。初期収益にはサブスクリプション開始、トライアルのコンバージョン、買い切り購入が含まれます。更新(リニューアル)はこのしきい値にはカウントされません。 ベースライン日はアプリのトライアル期間とプロダクト構成によって異なります。 - **トライアルなしのアプリ**: ベースライン日は通常、インストール後数日以内に来ます。 - **短いトライアルのアプリ**: ベースライン日は通常、トライアルのコンバージョン直後になります。 - **長いトライアルのアプリ**: トライアル完了後に初めて初期収益のほとんどが発生するため、ベースライン日はインストールから1週間以上後になることがあります。 ### サブスクリプションタイプ別の予測 \{#projection-by-subscription-type\} ベースライン日において、コホートの初期収益は月次・年次・週次・四半期サブスクリプション、および買い切り購入の5つのカテゴリに分類されます。各カテゴリは過去のコホートから計測された軌跡を使って独立して予測されます。 モデルは、直近のコホートや、1取引あたりの収益が近く、プロダクト構成が似ているなど経済的に類似したコホートを重視します。したがって、予測はアプリ内で最も直近かつ最も類似したコホートの実際のパフォーマンスを反映したものになります。 ## 予測が利用可能になるタイミング \{#when-predictions-are-available\} 予測はコホートに十分なデータがある場合にのみ表示されます。値を生成できない場合、該当列にはエムダッシュ(`—`)が表示されます。 予測が利用できない一般的な理由: - **コホートがベースライン日に達していない**: 初期収益が安定するまで、モデルは先の予測を行えません。 - **アプリの過去データが不足している**: 関連するサブスクリプションタイプの過去のコホートが十分でない場合、モデルは信頼性の高いリテンション率を算出できません。 予測は最新のトランザクションデータをもとに毎日再計算されるため、同じコホートの値がより多くの収益が観測されるにつれて変化することがあります。 --- # File: ua-tracking-links --- --- title: "Adapty User Acquisitionのトラッキングリンク" description: "キャンペーンを追跡し、どこでも成果を測定しましょう。" --- トラッキングリンクを使うと、ユーザーの流入元を計測し、インストールを広告キャンペーンと紐づけることができます。 ユーザーが広告をクリックすると、Adaptyはそのクリックを記録し、後でSDKから送られてくるインストールイベントと照合します。これにより、どのチャネル、キャンペーン、広告セット、広告が[Analyticsページ](ua-analytics)で最も多くの収益をもたらしているかを確認できます。 作成できるトラッキングリンクは2種類あります。 - **One link** — ユーザーのプラットフォームを自動的に判別し、クリックを記録してApp StoreまたはGoogle Playにリダイレクトするユニバーサルリンクです。 - **ストア別リンク** — クリックを記録しつつ、ユーザーをApp StoreまたはGoogle Playに自動的にリダイレクトするプラットフォーム指定のリンクです。遅延ディープリンクのパラメーターを付加することもできます。 ## トラッキングリンクの作成 \{#create-tracking-links\} トラッキングリンクを作成するには: 1. Adapty UAダッシュボードのサイドバーメニューから **Tracking links** に移動し、**Create link** をクリックします。 2. リストからアプリを選択し、**Next** をクリックします。 3. 追跡したいキャンペーンや広告に合わせて、リンクのパラメーターを入力します。 | パラメーター | 説明 | |-------------------|-----------------------------------------------------------------------------------------------| | **Name** | トラッキングリンクの内部名称。 | | **Channel** | Meta、Reddit、TikTokなどのトラフィック流入元。アナリティクスでキャンペーンをグループ化するために使用します。 | | **Campaign ID** | 広告プラットフォーム上のキャンペーンの一意の識別子。 | | **Campaign name** | キャンペーンの表示名。 | | **Ad set ID** | 広告プラットフォーム上の広告セット(広告グループ)の一意の識別子。 | | **Ad set name** | 広告セットの名前。 | | **Ad ID** | 個々の広告クリエイティブの一意の識別子。 | | **Ad name** | 広告クリエイティブまたはバリエーションの名前。 | 4. デフォルトではOne Linkが作成されます。クリックを追跡した後、ユーザーのプラットフォームを自動判別してApp StoreまたはGoogle Playにリダイレクトします。 プラットフォームごとに別々のリダイレクトURLを使いたい場合は、**One Link** チェックボックスをオフにして、プラットフォーム別のストアリンクを手動で入力してください。 5. **Create** をクリックします。 6. トラッキングリンクのページを開き、以下のいずれかのセクションから **Click link** をコピーします: - **One link** — クリックを追跡し、ユーザーを適切なストアに自動リダイレクトするリンクです。 - **iOS link** または **Android link** — ストアごとに別々のリンクを使いたい場合のオプションです。 :::tip [遅延データの活用](ua-deferred-data)に対応するため、追加のリンクパラメーターを設定することもできます。たとえば、遅延ディープリンクを実装できます。 ::: 7. 広告プラットフォームに移動し、広告の遷移先URLとしてリンクを貼り付けます。 これにより、アプリのインストールが流入元の広告やキャンペーンと紐づけられ、**Analytics** ページでキャンペーンの効果を計測できるようになります。 --- # File: ua-deferred-data --- --- title: "Adapty ユーザー獲得における遅延ディープリンク" description: "Adapty ユーザー獲得でディープリンクを設定する" --- 遅延ディープリンクを使うと、ユーザーが広告をクリックしてアプリをインストールしたとき、カスタムデータをアプリに渡すことができます。たとえば、インストール後の初回起動時に、アプリ内の特定の画面へ直接誘導することができます。 仕組みは次のとおりです: 1. ユーザーが広告をクリックすると、Adapty がクリックデータを保存します。 2. Adapty がインストールイベントを検知すると、クリック時の遅延データを取得します。 3. ユーザーがアプリをインストールして初めて起動すると、Adapty が保存済みのデータを取り出し、アプリがカスタムパラメーターを受け取ります。これにより、アプリのコードでさまざまな値に応じた処理が可能になります。 Adapty がサポートする遅延データパラメーターは以下のとおりです: - `ios_deferred_data` - `android_deferred_data` - `deferred_data_sub[1-10]` 遅延データパラメーターを追加するには、キャンペーン設定のリンクに追記します: 1. **Integrations -> Meta/TikTok Ads** ページからキャンペーンを開くか、**Tracking links** ページからトラッキングリンクを開きます。キャンペーンで使用するクリックリンクをコピーしてください。 2. 広告プラットフォーム(Meta、TikTok、Google Ads など)で、広告の遷移先 URL フィールドにリンクを貼り付け、遅延データパラメーターを `&` で始まるクエリパラメーターとして末尾に追加します。たとえば、iOS ユーザーをインストール後に「Welcome」画面へ誘導したい場合は、`&ios_deferred_data=welcome` を追加します。最終的な遷移先 URL は次のようになります: ``` https://api-ua.adapty.io/api/v1/attribution/click?adpt_cid=__ADAPTY__ID__&ios_deferred_data=welcome&campaign_id=__CAMPAIGN_ID__&adset_id=__AID__&ad_id=__CID__&campaign_name=__CAMPAIGN_NAME__&adset_name=__AID_NAME__&ad_name=__CID_NAME__&redirect_url=__APP_LINK__ ``` 3. アプリのコードでパラメーターに応じた処理を実装します。遅延データパラメーターは `payload` パラメーター内に格納されており、`payload` はエスケープされた JSON です。そのため、アプリのコードで JSON をパースする必要があります。 たとえば、`ios_deferred_data` が `welcome` の場合のインストール処理は次のように実装できます: <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift showLineNumbers Adapty.delegate = self nonisolated func onInstallationDetailsSuccess(_ details: AdaptyInstallationDetails) { guard let payloadStr = details.payload, let data = payloadStr.data(using: .utf8), let payload = try? JSONSerialization.jsonObject(with: data) as? [String: Any], let deeplink = payload["ios_deferred_data"] as? String, deeplink == "welcome" else { return } DispatchQueue.main.async { print("Navigate to welcome screen") // navigate to your screen here } } ``` </TabItem> <TabItem value="android" label="Kotlin"> ```kotlin showLineNumbers Adapty.setOnInstallationDetailsListener(object : OnInstallationDetailsListener { override fun onInstallationDetailsSuccess(details: AdaptyInstallationDetails) { details.payload?.let { runCatching { val json = JSONObject(it) if (json.optString("android_deferred_data") == "welcome") { println("Navigate to welcome screen") // navigate here } }.onFailure(Throwable::printStackTrace) } } }) ``` </TabItem> <TabItem value="rn" label="React Native" default> ```typescript showLineNumbers adapty.addEventListener('onInstallationDetailsSuccess', details => { // Parse the payload JSON and navigate to welcome screen if needed try { if (details.payload) { const payload = JSON.parse(details.payload); if (payload.ios_deferred_data === 'welcome') { // Navigate to welcome screen // Replace with your app's navigation logic // For example, using React Navigation: // navigation.navigate('Welcome'); console.log('Navigate to welcome screen'); } } } catch (error) { console.error('Error parsing installation details payload:', error); } }); ``` </TabItem> <TabItem value="flutter" label="Flutter"> ```dart showLineNumbers Adapty().onUpdateInstallationDetailsSuccessStream.listen((details) { final payloadStr = details.payload; if (payloadStr == null) return; final payload = json.decode(payloadStr) as Map<String, dynamic>; if (payload['ios_deferred_data'] == 'welcome') { print('Navigate to welcome screen'); } }); ``` </TabItem> </Tabs> --- # File: ua-attribution-data --- --- title: "アプリでアトリビューションデータを受け取る" description: "Adapty がインストールをキャンペーンに紐付けた後、アプリでキャンペーンのアトリビューションデータにアクセスします。" --- Adapty がインストールをキャンペーンに紐付けると、`onInstallationDetailsSuccess` コールバックを通じてアプリにアトリビューションデータが返されます。このデータを活用して、インストールのきっかけとなったチャネルやキャンペーンに基づいたユーザー体験のパーソナライズが可能です。 アトリビューションデータは、`payload` フィールド内にネストされた `attribution` オブジェクトとして返されます。以下のフィールドが含まれます。 | フィールド | 説明 | |---|---| | `channel` | 獲得チャネル(例:`facebook`、`tiktok`、`google`、`organic`) | | `campaign_id` | キャンペーン識別子 | | `campaign_name` | キャンペーン名 | | `adset_id` | 広告セット / 広告グループの識別子 | | `adset_name` | 広告セット / 広告グループ名 | | `ad_id` | 広告 / クリエイティブの識別子 | | `ad_name` | 広告 / クリエイティブ名 | すべてのフィールドはオプションです。オーガニックインストールの場合や、アトリビューションが特定できなかった場合、`payload` フィールドには `attribution` オブジェクトが含まれません。 アプリでアトリビューションデータを読み取るには: <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift showLineNumbers Adapty.delegate = self nonisolated func onInstallationDetailsSuccess(_ details: AdaptyInstallationDetails) { guard let payloadDict = details.payload?.dictionary, let attribution = payloadDict["attribution"] as? [String: Any] else { return } let channel = attribution["channel"] as? String let campaignName = attribution["campaign_name"] as? String let adName = attribution["ad_name"] as? String print("Channel: \(channel ?? "organic")") } ``` </TabItem> <TabItem value="android" label="Kotlin"> ```kotlin showLineNumbers Adapty.setOnInstallationDetailsListener(object : OnInstallationDetailsListener { override fun onInstallationDetailsSuccess(details: AdaptyInstallationDetails) { val payloadStr = details.payload ?: return runCatching { val payload = JSONObject(payloadStr) val attribution = payload.optJSONObject("attribution") ?: return val channel = attribution.optString("channel") val campaignName = attribution.optString("campaign_name") val adName = attribution.optString("ad_name") println("Channel: $channel") }.onFailure(Throwable::printStackTrace) } }) ``` </TabItem> <TabItem value="rn" label="React Native"> ```typescript showLineNumbers adapty.addEventListener('onInstallationDetailsSuccess', details => { try { if (!details.payload) return; const payload = JSON.parse(details.payload); const attribution = payload.attribution; if (!attribution) return; const channel = attribution.channel; const campaignName = attribution.campaign_name; const adName = attribution.ad_name; console.log('Channel:', channel ?? 'organic'); } catch (error) { console.error('Error parsing payload:', error); } }); ``` </TabItem> <TabItem value="flutter" label="Flutter"> ```dart showLineNumbers Adapty().onUpdateInstallationDetailsSuccessStream.listen((details) { final payloadStr = details.payload; if (payloadStr == null) return; final payload = json.decode(payloadStr) as Map<String, dynamic>; final attribution = payload['attribution'] as Map<String, dynamic>?; if (attribution == null) return; final channel = attribution['channel'] as String?; final campaignName = attribution['campaign_name'] as String?; final adName = attribution['ad_name'] as String?; print('Channel: ${channel ?? 'organic'}'); }); ``` </TabItem> </Tabs> --- # File: ua-facebook --- --- title: "Meta AdsをAdapty UAと連携する" description: "Meta AdsをAdapty UAに接続して、Facebook、Instagram、Messenger、Audience Networkのキャンペーンパフォーマンスを追跡・最適化しましょう。" --- Adapty UAのMeta連携を使うと、Facebook、Instagram、Messenger、Audience Networkにまたがるキャンペーンパフォーマンスを追跡・最適化できます。 :::tip [Meta Ads Managerで広告を設定するガイド](meta-create-campaign)もご覧ください。 ::: ## ステップ1. Facebookアカウントを接続する \{#step-1-connect-your-facebook-account\} Meta AdsをAdapty UAに接続するには、左サイドバーから **Integrations > Meta** に移動します。接続方法は2つあります: - **Continue with Facebook**:OAuthで接続します。個人またはビジネスのFacebookアカウントでMeta Ads Managerにサインインしている場合はこちらを使用してください。 - **Add system token**:永続的なシステムユーザートークンで接続します。組織がMeta Businessのシステムユーザーを通じて広告アカウントを管理している場合はこちらを使用してください。 <Tabs> <TabItem value="oauth" label="Continue with Facebook"> :::important Facebookアカウントが、必要なキャンペーンとピクセルにアクセスできることを確認してください。 ::: 1. **Continue with Facebook** をクリックします。 2. Facebookアカウントでサインインし、**Continue** をクリックします。 3. リクエストされた権限を確認し、**Save** をクリックします。 </TabItem> <TabItem value="system" label="Add system token"> Meta Business Settingsで[システムユーザーアクセストークン](https://developers.facebook.com/documentation/ads-commerce/marketing-api/collaborative-ads/managed-partner-ads/api-guide/prerequisites/generate-access-token-system-user)を生成し、Adapty UAに追加します。 :::important 始める前に、Meta Businessポートフォリオに[システムユーザー](https://www.facebook.com/business/help/503306463479099)が必要です。追跡したい広告アカウントがそのユーザーに割り当て済みであること、またトークン生成時に選択するアプリがポートフォリオに追加済みであることを確認してください。 ::: **Meta Business Settingsでトークンを生成する:** 1. **Business Settings** に移動します。 2. **Users** の下で **System users** を選択します。 3. システムユーザーを選択し、**Generate new token** をクリックします。 4. ドロップダウンからアプリを選択します。 5. 権限リストで `ads_read` を有効にします。Adapty UAがキャンペーンと広告データを読み取るために必要な権限はこれだけです。 6. **Generate token** をクリックします。 7. トークンをコピーして安全な場所に保管します。Metaはトークンを一度しか表示しません。 :::note **Token expiration** 設定は、接続がどのくらい有効であるかを制御します。有効期限付きのトークンは、アトリビューションが停止しないよう期限が切れる前に再生成・再接続が必要です。有効期限なしのトークンはこの手間を省けますが、長期間有効な認証情報となります。安全に保管し、万が一漏洩した場合はすぐに失効させてください。 ::: **Adapty UAでトークンを追加する:** 1. **Add system token** をクリックします。 2. トークンを貼り付け、**Connect** をクリックします。 </TabItem> </Tabs> 完了すると、すべての広告アカウントがAdapty UAに追加されます。続けてキャンペーンを追加できます。 ## ステップ2. キャンペーンを追加する \{#step-2-add-campaigns\} Meta Ads User AcquisitionキャンペーンをAdaptyに追加し、Meta広告のパフォーマンスを追跡するには: 1. **Web campaigns** タブに切り替えて **Create campaign** をクリックします。アプリを選択して **Save** をクリックします。 2. **General** タブで **iOS** および/または **Android** セクションを展開し、App StoreやGoogle PlayのアプリケーションURLを貼り付けます。 3. **Click link** フィールドの値をコピーします。次にMeta Ads Managerで広告を開き、このリンクを貼り付けます。これにより、AdaptyはインストールとMeta上の広告を紐づけられるようになります。 4. コンバージョンイベントをMetaに送り返すため、Adapty UAのキャンペーンにMetaのピクセルを関連付けることもできます。**Pixel** ドロップダウンから既存のピクセルを選択してください。 ## ステップ3. イベントをマッピングする \{#step-3-map-events\} キャンペーン最適化のためにコンバージョンイベントをMetaに送り返すには、**Events names** セクションでイベントマッピングを設定する必要があります。これにより、ユーザーがアプリ内でアクションを行った際に、Adaptyがサブスクリプションイベントを自動的にMetaピクセルに送信できるようになります。 **Events names** セクションで、Meta Ads Managerで追跡したいイベントをオンにします。有効にした各イベントについて、ドロップダウンから対応するMetaイベントを選択するか、カスタムイベントを設定します。デフォルトでは、AdaptyのイベントはMetaの標準イベントにマッピングされます。 **Save** をクリックして、イベントマッピングの設定を適用します。 ## 追加設定 \{#additional-configuration\} ### 追加パラメーター \{#additional-parameters\} **Additional parameter** フィールドでは、Adapty外部での分析用にカスタムデータポイントを追加できます。特定のキャンペーンやユーザーデータを外部の分析ツールやアトリビューションパートナーに渡す必要がある場合に便利です。 **Additional parameter** フィールドに、アトリビューション追跡に含めたいカスタムデータを入力します。追加パラメーターはMetaに送信されるすべてのアトリビューションデータに含まれ、高度なキャンペーン分析・最適化に活用できます。 たとえば、同じキャンペーンの複数バリエーションを実行している場合、`variant=A` や `variant=B` を追加して異なるクリエイティブアプローチを区別できます。 :::important 追加パラメーターを設定すると、Meta Ads Managerに貼り付ける**クリックリンク**が変わります。すでにリンクをコピー済みで後からカスタムパラメーターを追加した場合は、カスタムパラメーターを含む最新のクリックリンクをコピーして貼り直してください。 ::: <br/> ### 設定 \{#settings\} **Settings** タブでは、AdapyがユーザーアクションをMeta Adsキャンペーンに紐づける方法を制御します。決定論的マッチングと確率的マッチングの両方における時間枠を設定できます。 設定するには、キャンペーン設定の **Settings** タブに移動します。ここで調整できる主な設定が2つあります: - **Deterministic matching window**:IDFA(iOS)やAdvertising ID(Android)などの正確なデバイス識別子を使って、高い精度でユーザーをキャンペーンに紐づけます。最大のアトリビューション精度を得るために168時間(7日間)に設定してください。これはデフォルトかつ推奨値です。ユーザーがMeta広告をクリックしてこの時間枠内にアプリをインストールすると、Adaptyはデバイス識別子を使ってインストールを特定の広告クリックに確実に紐づけられます。 - **Probabilistic matching window**:決定論的マッチングができない場合に、統計モデルとデバイスフィンガープリントを使ってユーザーを紐づけます。ほとんどのキャンペーンでは6時間に設定してください。これはデフォルト値であり、ほとんどのユースケースで適切に機能します。クリック数が多いキャンペーンでは1〜2時間に短縮することもできます。プライバシー設定などの理由で決定論的マッチングができないユーザーに対しては、Adaptyはこの短い時間枠内で確率的マッチングを使用します。 **Save** をクリックして設定を適用します。 ### 収益オーバーライド \{#revenue-override\} トライアルイベントを追跡しており、Metaがそれを収益として計上するようにしたい場合は、**Revenue override** セクションを使用します。このセクションは **Trial started** イベントが有効なときに表示されます。 各トライアルイベントの対象について、収益として報告するサブスクリプション価格の割合を設定します。たとえば30%に設定すると、Adaptyはトライアルイベントのコンバージョン値としてサブスクリプション価格の30%を送信します。 オーバーライドを追加するには: 1. **Events names** セクションで **Trial started** を有効にします。 2. **Revenue override** で **Add override** をクリックします。 3. 対象イベントを選択し、収益の割合(0〜100)を入力します。 4. **Save** をクリックします。 ### すべてのイベントを送信する \{#send-all-events\} デフォルトでは、AdapyはMetaキャンペーンにアトリビュートされたユーザーのイベントのみをピクセルに送信します。**Send all events** を有効にすると、オーガニックユーザーやアトリビュートされていないユーザーのイベントもピクセルに転送されます。 有効にすると、キャンペーンのアトリビューションに関わらず、すべてのインストールおよびトランザクションイベントがピクセルに送信されます。オーディエンスモデリングやキャンペーン最適化のためにMetaにより広範なコンバージョンデータを提供したい場合に使用してください。 このオプションを有効にするには、キャンペーン設定で **Send all events (forward organic/non-attributed events to this pixel)** を選択し、**Save** をクリックします。 --- # File: ua-tiktok --- --- title: "TikTok for BusinessをAdapty UAと連携する" description: "TikTok for BusinessをAdapty UAに接続して、TikTok Ads Managerでキャンペーンのパフォーマンスをトラッキングおよび最適化します。" --- Adapty UAのTikTok for Business連携を使うと、TikTokでキャンペーンのパフォーマンスをトラッキングおよび最適化できます。 :::tip [TikTok for Businessで広告を設定するガイド](tiktok-create-campaign)もご覧ください。 ::: ## ステップ1. TikTokアカウントを接続する \{#step-1-connect-your-tiktok-account\} 1. 左サイドバーから **Integrations > TikTok Ads** に移動し、**Continue with TikTok** をクリックします。 2. TikTokアカウントでサインインし、**Continue** をクリックします。 3. 要求される権限を確認し、**Save** をクリックします。 完了すると、すべての広告アカウントがAdapty UAに追加されます。続けてキャンペーンを追加できます。 ## ステップ2. キャンペーンを追加する \{#step-2-add-campaigns\} TikTok for BusinessのキャンペーンをAdapty User Acquisitionに追加し、TikTok広告のパフォーマンスをAdaptyでトラッキングするには: 1. **Web campaigns** タブに切り替えて **Create campaign** をクリックします。アプリを選択して **Save** をクリックします。 2. **General** タブで **iOS** または **Android**(あるいは両方)のセクションを展開し、App StoreまたはGoogle Play(あるいは両方)のアプリURLを貼り付けます。 3. **Click link** フィールドの値をコピーします。次に、TikTok Ads Managerで広告を作成する際、**Advanced Settings** セクションの **Tracking URL** フィールドにこの値を貼り付けます。これにより、Adaptyがインストールや購入をTikTok広告に紐付けられるようになります。 4. (任意)コンバージョンイベントをTikTokに送り返すために、TikTokのピクセルをAdapty UAのキャンペーンと関連付けることもできます。その場合は、**Pixel** ドロップダウンから既存のピクセルを選択してください。 ## ステップ3. イベントをマッピングする \{#step-3-map-events\} キャンペーン最適化のためにコンバージョンイベントをTikTokに送り返すには、**Events names** セクションでイベントマッピングを設定する必要があります。これにより、ユーザーがアプリ内でアクションを実行したときに、AdaptyがサブスクリプションイベントをTikTokピクセルに自動的に送信できるようになります。 **Events names** セクションで、TikTok Ads Managerでトラッキングしたいイベントをオンにします。有効にした各イベントについて、ドロップダウンから対応するTikTokイベントを選択するか、カスタムイベントを設定します。デフォルトでは、AdaptyのイベントはTikTokの標準イベントにマッピングされています。 **Save** をクリックしてイベントマッピングの設定を適用します。 ## 追加設定 \{#additional-configuration\} ### 追加パラメーター \{#additional-parameters\} **Additional parameter** フィールドでは、Adapty外部での分析用にカスタムデータポイントを追加できます。特定のキャンペーンやユーザーデータを外部の分析ツールやアトリビューションパートナーに渡す必要がある場合に便利です。 **Additional parameter** フィールドに、アトリビューショントラッキングに含めたいカスタムデータを入力します。追加パラメーターはTikTokに送信されるすべてのアトリビューションデータに含まれ、高度なキャンペーン分析や最適化に活用できます。 たとえば、同じキャンペーンの複数バリエーションを運用している場合、`variant=A` や `variant=B` を追加することで、異なるクリエイティブアプローチを区別できます。 :::important 追加パラメーターを設定すると、TikTok Ads Managerに貼り付ける **Click link** が変わります。すでにリンクをコピーして貼り付けた後にカスタムパラメーターを追加した場合は、カスタムパラメーターを含む最新のクリックリンクをコピーして再度貼り付けてください。 ::: <br/> ### 設定 \{#settings\} **Settings** タブでは、AdaptyがユーザーのアクションをTikTok広告キャンペーンに紐付ける方法を制御します。ここでは、確定的マッチングと確率的マッチングの両方のアトリビューションウィンドウを設定します。 設定するには、キャンペーン設定の **Settings** タブに移動します。ここで調整できる主な設定が2つあります: - **Deterministic matching window**:iOS上のIDFAやAndroid上のAdvertising IDなど、正確なデバイス識別子を使用して高精度でユーザーをキャンペーンに紐付けます。アトリビューション精度を最大化するために168時間(7日間)に設定することをお勧めします。これがデフォルト値です。ユーザーがTikTok広告をクリックし、このウィンドウ内にアプリをインストールした場合、Adaptyはデバイス識別子を使用してそのインストールを特定の広告クリックに確定的に紐付けます。 - **Probabilistic matching window**:確定的マッチングができない場合に、統計モデリングとデバイスフィンガープリンティングを使用してユーザーを照合します。ほとんどのキャンペーンでは6時間に設定してください。これがデフォルト値であり、多くのユースケースに適しています。クリック数が多いキャンペーンでは1〜2時間に短縮することもできます。確定的にマッチングできないユーザー(プライバシー設定などの要因による)の場合、Adaptyはこの短いウィンドウ内で確率的マッチングを使用します。 **Save** をクリックして設定を適用します。 ### 収益オーバーライド \{#revenue-override\} トライアルイベントをトラッキングしていて、TikTokにその収益をアトリビューションさせたい場合は、**Revenue override** セクションを使用します。このセクションは **Trial started** イベントが有効になっているときに表示されます。 各トライアルイベントのターゲットに対して、収益として報告するサブスクリプション価格の割合を設定します。たとえば30%に設定すると、Adaptyはトライアルイベントのコンバージョン値としてサブスクリプション価格の30%を送信します。 オーバーライドを追加するには: 1. **Events names** セクションで **Trial started** を有効にします。 2. **Revenue override** で **Add override** をクリックします。 3. ターゲットイベントを選択し、収益の割合(0〜100)を入力します。 4. **Save** をクリックします。 ### すべてのイベントを送信する \{#send-all-events\} デフォルトでは、AdaptyはTikTokキャンペーンにアトリビューションされたユーザーのイベントのみをピクセルに送信します。**Send all events** を有効にすると、オーガニックや未アトリビューションのユーザーのイベントもピクセルに転送されます。 有効にすると、キャンペーンのアトリビューションに関わらず、すべてのインストールおよびトランザクションイベントがピクセルに送信されます。これにより、TikTokにより広範なコンバージョンデータを提供し、オーディエンスモデリングやキャンペーン最適化に活用できます。 このオプションを有効にするには、キャンペーン設定で **Send all events (forward organic/non-attributed events to this pixel)** を選択し、**Save** をクリックします。 --- # File: ua-funnelfox --- --- title: "FunnelFox と Adapty UA を連携する" description: "FunnelFox の web2app ファネルを Adapty UA に接続し、Web タッチポイントから有料サブスクリプションまでの完全なアクセス経路を追跡します。" --- [FunnelFox](https://funnelfox.com) は web2app ファネルを構築するプラットフォームです。App Store を経由せずにユーザーを獲得・課金できるため、手数料やその他の制約を回避できます。 連携すると、FunnelFox はトランザクションイベントを Adapty UA に送信し、Web タッチポイントから有料サブスクライバーまでの完全なアトリビューションパスを確認できるようになります。 連携を設定するには、**Project ID** を使用して FunnelFox のプロジェクトを Adapty のアプリに 1 つ以上リンクします。 ## 仕組み \{#how-it-works\} ユーザーが FunnelFox ファネルで購入を完了すると、FunnelFox はトランザクションイベントを Adapty UA に送信します。Adapty は **Project ID** を使用して、そのトランザクションがどのアプリに属するかを特定します。イベントはその後保存され、UA アナリティクスに表示されます。 各トランザクションには次の情報が含まれます: - **サブスクリプションライフサイクルイベント**: 開始、更新、キャンセル、トライアル転換、返金など - **アトリビューションデータ**: キャンペーン、広告セット、広告の識別子;UTM パラメーター;プラットフォームのクリック ID(fbclid、ttclid、gclid) - **ファネルと実験データ**: FunnelFox のファネル名と実験名(A/B テストのバリアントを比較するために使用) Adapty はトランザクション内のクリック ID から**チャネル**(Facebook、TikTok、Google、またはオーガニック)を自動的に判定します。手動で設定する必要はありません。 :::note FunnelFox のトランザクションは、Web 購入にはアプリのインストールイベントがないため、コホート日としてインストール日ではなく**初回課金日**を使用します。 ::: ## 連携を設定する \{#configure-integration\} ### ステップ 1. FunnelFox で Project ID を取得する \{#step-1-get-your-project-id-in-funnelfox\} 1. FunnelFox ダッシュボードの左サイドバーで **Settings** をクリックします。 2. **Project info** セクションで **ID** の値をコピーします。 ### ステップ 2. Adapty UA でプロジェクトを追加する \{#step-2-add-the-project-in-adapty-ua\} 1. Adapty UA で [**Integrations > FunnelFox**](https://app.adapty.io/ua/integrations/funnelfox) に移動します。 2. FunnelFox からコピーした Project ID を貼り付けます。 3. **Save** をクリックします。 追加の FunnelFox プロジェクトを接続するには、**Add project** をクリックし、プロジェクトごとに両方のステップを繰り返してください。 --- # File: ua-custom-s3 --- --- title: "Custom S3" description: "ユーザー獲得データをカスタム S3 互換ストレージにエクスポートして、高度な分析とレポートに活用できます。" --- Adapty UA のカスタム S3 互換ストレージとの連携により、ユーザー獲得キャンペーンデータを自分専用の S3 互換ストレージに安全に保存できます。キャンペーンのパフォーマンスデータ、アトリビューションデータ、ユーザー獲得イベントを .csv ファイルとしてカスタム S3 バケットに保存できます。 この連携を設定するには、S3 互換ストレージのコンソールと Adapty UA ダッシュボードでいくつかの手順を行うだけです。 :::note Adapty UA はデータを毎日 **24時間ごと**、UTC 4:00 に送信します。 各ファイルには、UTC の前日(カレンダー上の 1 日分)に作成されたイベントのデータが含まれます。たとえば、3 月 8 日の UTC 4:00 に自動エクスポートされるファイルには、3 月 7 日の UTC 00:00:00 〜 23:59:59 に作成されたすべてのイベントが含まれます。 ::: ## Custom S3 連携の設定 \{#set-up-custom-s3-integration\} データの受信を開始するには、Adapty UA で連携を設定します。 1. [**Integrations** -> **Custom S3**](https://app.adapty.io/ua/integrations/custom-s3) に移動します。 2. **Export install events to custom S3** トグルをオンにします。 3. カスタム S3 ストレージと Adapty UA プロファイルを接続するために必要なフィールドを入力します。 | フィールド | 説明 | |:----------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Access Key ID** | S3 互換ストレージサービスへのユーザーまたはアプリケーションのアクセスを認証するための一意の識別子です。ストレージプロバイダーのコンソールで確認できます。 | | **Secret Access Key** | Access Key ID と組み合わせて、S3 互換ストレージサービスへのアクセスを認証するためのプライベートキーです。ストレージプロバイダーのコンソールで確認できます。 | | **S3 Bucket Name** | ストレージ環境内の特定の S3 バケットを識別するグローバルに一意の名前です。S3 バケットは、ファイルや画像などのデータオブジェクトをクラウドに保存・取得できるシンプルなストレージサービスです。 | | **Region**(省略可) | Management Console からリージョンを取得してください。 | | **Folder Inside the Bucket**(省略可) | 選択した S3 バケット内に作成したいフォルダーの名前です。S3 はオブジェクトキープレフィックス(フォルダー名に相当)を使ってフォルダーを擬似的に表現していることに注意してください。 | | **Custom Endpoint URL** | S3 互換ストレージサービスのエンドポイント URL です。ストレージプロバイダー(MinIO、DigitalOcean Spaces、Wasabi など)から提供されます。 | :::note S3 バケット名フィールドにネストされたディレクトリを指定することもできます(例:`adapty-ua-events/com.sample-app`)。 ::: ## 手動データエクスポート \{#manual-data-export\} カスタム S3 ストレージへの自動イベントデータエクスポートに加えて、Adapty UA では手動でのファイルエクスポート機能も提供しています。この機能を使用すると、ユーザー獲得データの日付を指定して、S3 バケットに手動でエクスポートできます。これにより、エクスポートするデータとタイミングをより細かく制御できます。 ## テーブル構造 \{#table-structure\} Custom S3 連携では、Adapty UA はインストールイベントの履歴データを格納するテーブルを提供します。このテーブルには、ユーザープロファイル、収益・手取り額、元のストアなど、さまざまなデータポイントに関する情報が含まれています。 :::warning この構造は今後拡張される可能性があります。弊社や連携先のサードパーティが新しいデータを追加することがあります。このデータを処理するコードは、構造全体に依存せず、特定のフィールドのみを参照するよう、堅牢に設計してください。 ::: イベントのテーブル構造は以下のとおりです。 | カラム | 説明 | |--------------------------|-------------------------------------------| | `adapty_profile_id` | Adapty プロファイルの一意の識別子 | | `install_id` | インストールの一意の識別子 | | `created_at` | レコード作成タイムスタンプ(ISO 8601) | | `installed_at` | アプリインストールタイムスタンプ(ISO 8601) | | `store` | アプリストア(`ios`、`android`) | | `country` | ユーザーの国コード(ISO 3166-1 alpha-2) | | `ip_address` | クライアントの IP アドレス | | `idfa` | iOS の広告識別子(IDFA) | | `idfv` | iOS のベンダー識別子(IDFV) | | `gaid` | Google 広告 ID(Android) | | `android_id` | Android デバイス ID | | `app_set_id` | Android App Set ID | | `bundle_id` | アプリのバンドル識別子(例:`com.example.app`) | | `device_brand` | デバイスのブランド(例:`Apple`、`Samsung`) | | `device_model` | デバイスのモデル(例:`iPhone15,2`) | | `os_version` | OS のメジャーバージョン | | `app_version` | Adapty SDK が報告するアプリバージョン | | `sdk_version` | Adapty SDK のバージョン | | `channel` | アトリビューションチャネル | | `campaign_id` | キャンペーン識別子 | | `campaign_name` | キャンペーン名 | | `adset_id` | 広告セット識別子 | | `adset_name` | 広告セット名 | | `ad_id` | 広告識別子 | | `ad_name` | 広告名 | | `keyword_id` | キーワード識別子 | | `keyword_name` | キーワード名 | | `asa_org_id` | Apple Search Ads の組織 ID | | `asa_keyword_match_type` | ASA キーワードマッチタイプ(`Exact`、`Broad`) | | `asa_attribution` | ASA アトリビューションデータ(JSON 文字列) | | `asa_conversion_type` | ASA コンバージョンタイプ | | `asa_country_or_region` | ASA の国またはリージョン | | `asa_creative_set_name` | ASA クリエイティブセット名 | | `fbclid` | Facebook クリック ID | | `ttclid` | TikTok クリック ID | | `utm_source` | UTM ソースパラメーター | | `utm_medium` | UTM メディアパラメーター | | `utm_campaign` | UTM キャンペーンパラメーター | | `utm_term` | UTM タームパラメーター | | `utm_content` | UTM コンテンツパラメーター | --- # File: ua-amazon-s3 --- --- title: "Amazon S3" description: "ユーザー獲得データを S3 にエクスポートして、高度な分析とレポートを実現します。" --- Adapty UA の Amazon S3 インテグレーションを使用すると、ユーザー獲得キャンペーンデータを一か所に安全に保存できます。キャンペーンのパフォーマンスデータ、アトリビューションデータ、ユーザー獲得イベントを .csv ファイルとして Amazon S3 バケットに保存できます。 このインテグレーションを設定するには、AWS コンソールと Adapty UA ダッシュボードでいくつかの簡単な手順を行う必要があります。 :::note Adapty UA は毎日 UTC 4:00 に **24h** ごとにデータを送信します。 各ファイルには、UTC での前の暦日に作成されたイベントのデータが含まれます。たとえば、3 月 8 日の UTC 4:00 に自動的にエクスポートされたデータには、3 月 7 日の UTC 00:00:00 から 23:59:59 までに作成されたすべてのイベントが含まれます。 ::: ## Amazon S3 インテグレーションのセットアップ方法 \{#how-to-set-up-amazon-s3-integration\} データの受信を開始するには、以下の認証情報が必要です: 1. アクセスキー ID 2. シークレットアクセスキー 3. S3 バケット名 4. S3 バケット内のフォルダ名 :::note ネストされたディレクトリ Amazon S3 バケット名フィールドにネストされたディレクトリを指定できます。例:adapty-ua-events/com.sample-app ::: ### ステップ 1. Amazon S3 認証情報の作成 \{#step-1-create-amazon-s3-credentials\} このガイドでは、AWS コンソールで必要な認証情報を作成する方法を説明します。 #### 1.1. アクセスポリシーの作成 \{#11-create-access-policy\} 1. AWS コンソールの [IAM ポリシーダッシュボード](https://us-east-1.console.aws.amazon.com/iamv2/home?region=us-east-1#/policies) に移動します 2. **Create Policy** オプションを選択します <img src="/assets/shared/img/7af075c-CleanShot_2023-03-21_at_10.52.002x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. ポリシーエディターで以下の JSON を貼り付け、`adapty-s3-integration-test` をご自身のバケット名に変更します: ```json showLineNumbers title="Json" { "Version": "2012-10-17", "Statement": [ { "Sid": "AllowListObjectsInBucket", "Effect": "Allow", "Action": "s3:ListBucket", "Resource": "arn:aws:s3:::adapty-s3-integration-test" }, { "Sid": "AllowAllObjectActions", "Effect": "Allow", "Action": "s3:*Object", "Resource": [ "arn:aws:s3:::adapty-s3-integration-test/*", "arn:aws:s3:::adapty-s3-integration-test" ] }, { "Sid": "AllowBucketLocation", "Effect": "Allow", "Action": "s3:GetBucketLocation", "Resource": "arn:aws:s3:::adapty-s3-integration-test" } ] } ``` <img src="/assets/shared/img/d4e474a-CleanShot_2023-03-21_at_10.56.212x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. ポリシーの設定が完了したら、タグを追加することもできます(省略可能)。その後、**Next** をクリックして最終ステップに進みます 5. このステップでポリシーに名前を付け、**Create policy** ボタンをクリックして作成を完了します <img src="/assets/shared/img/7dcb02f-CleanShot_2023-03-21_at_11.03.372x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> #### 1.2. IAM ユーザーの作成 \{#12-create-iam-user\} Adapty UA が生データレポートをバケットにアップロードできるようにするには、特定のバケットへの書き込みアクセス権を持つユーザーのアクセスキー ID とシークレットアクセスキーを提供する必要があります。 1. IAM コンソールに移動し、[ユーザーセクション](https://console.aws.amazon.com/iamv2/home#/users) を選択します 2. **Add users** ボタンをクリックします <img src="/assets/shared/img/bb612c8-CleanShot_2023-03-21_at_11.12.392x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. ユーザーに名前を付け、**Access key – Programmatic access** を選択して、権限の設定に進みます <img src="/assets/shared/img/467ee4d-j6aoX.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. 次のステップで **Add user to group** オプションを選択し、**Create group** ボタンをクリックします <img src="/assets/shared/img/bfd0e80-CleanShot_2023-03-21_at_11.24.592x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. ユーザーグループに名前を付け、先ほど作成したポリシーを選択します 6. ポリシーを選択したら、**Create group** ボタンをクリックしてプロセスを完了します <img src="/assets/shared/img/df29c12-CleanShot_2023-03-21_at_11.28.052x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 7. グループを正常に作成したら、**それを選択**して次のステップに進みます <img src="/assets/shared/img/1f3722e-CleanShot_2023-03-21_at_11.36.192x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 8. このセクションの最終ステップですので、**Create User** ボタンをクリックして進みます <img src="/assets/shared/img/ea43722-CleanShot_2023-03-21_at_11.40.462x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 9. 最後に、**認証情報を .csv 形式でダウンロード**するか、ダッシュボードから直接コピーして貼り付けることができます <img src="/assets/shared/img/bcf35e1-S3created.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### ステップ 2. Adapty UA でのインテグレーション設定 \{#step-2-configure-integration-in-adapty-ua\} 1. [**Integrations** -> **Amazon S3**](https://app.adapty.io/ua/integrations/s3) に移動します 2. **Export install events to Amazon S3** トグルをオンにします 3. 以下のフィールドに入力して、Amazon S3 と Adapty UA プロファイルの接続を設定します: | フィールド | 説明 | |:-----------------------------| :----------------------------------------------------------- | | **Access Key ID** | AWS サービスへのユーザーまたはアプリケーションのアクセスを認証するための一意の識別子です。この ID はダウンロードした [csv ファイル](ua-amazon-s3#step-1-create-amazon-s3-credentials) で確認できます。 | | **Secret Access Key** | アクセスキー ID と組み合わせて AWS サービスへのアクセスを認証するためのプライベートキーです。このキーはダウンロードした [csv ファイル](ua-amazon-s3#step-1-create-amazon-s3-credentials) で確認できます。 | | **S3 Bucket Name** | AWS クラウド内の特定の S3 バケットを識別するグローバルに一意の名前です。S3 バケットは、ファイルや画像などのデータオブジェクトをクラウドに保存・取得できるシンプルなストレージサービスです。 | | **Folder Inside the Bucker** | 選択した S3 バケット内に作成したいフォルダの名前です。S3 はオブジェクトキープレフィックス(実質的にフォルダ名)を使用してフォルダをシミュレートしていることにご注意ください。 | | **Region**(省略可能) | AWS マネジメントコンソールの IAM ユーザーアカウントでリージョンを確認できます。 | ## 手動データエクスポート \{#manual-data-export\} Amazon S3 への自動イベントデータエクスポートに加えて、Adapty UA では手動ファイルエクスポート機能も提供しています。この機能を使用すると、ユーザー獲得データの特定の日付を選択して、S3 バケットに手動でエクスポートできます。これにより、エクスポートするデータとそのタイミングをより細かく制御できます。 ## テーブル構造 \{#table-structure\} AWS S3 インテグレーションでは、Adapty UA はインストールイベントの履歴データを保存するテーブルを提供します。このテーブルには、ユーザープロファイル、収益と取り分、オリジンストアなどに関する情報が含まれています。 :::warning この構造は、私たちや連携する第三者から新しいデータが追加されるにつれて、今後拡張される可能性があります。データを処理するコードは特定のフィールドに依存するようにし、構造全体に依存しないよう注意してください。 ::: イベントのテーブル構造は以下のとおりです: | カラム | 説明 | |--------------------------|-------------------------------------------| | `adapty_profile_id` | Adapty プロファイルの一意の識別子 | | `install_id` | インストールの一意の識別子 | | `created_at` | レコード作成タイムスタンプ(ISO 8601) | | `installed_at` | アプリインストールタイムスタンプ(ISO 8601) | | `store` | アプリストア(`ios`、`android`) | | `country` | ユーザーの国コード(ISO 3166-1 alpha-2) | | `ip_address` | クライアント IP アドレス | | `idfa` | iOS 広告識別子(Identifier for Advertisers) | | `idfv` | iOS ベンダー識別子(Identifier for Vendors) | | `gaid` | Google 広告 ID(Android) | | `android_id` | Android デバイス ID | | `app_set_id` | Android App Set ID | | `channel` | アトリビューションチャネル | | `campaign_id` | キャンペーン識別子 | | `campaign_name` | キャンペーン名 | | `adset_id` | 広告セット識別子 | | `adset_name` | 広告セット名 | | `ad_id` | 広告識別子 | | `ad_name` | 広告名 | | `keyword_id` | キーワード識別子 | | `keyword_name` | キーワード名 | | `asa_org_id` | Apple Search Ads 組織 ID | | `asa_keyword_match_type` | ASA キーワードマッチタイプ(`Exact`、`Broad`) | | `asa_attribution` | ASA アトリビューションデータ(JSON 文字列) | | `asa_conversion_type` | ASA コンバージョンタイプ | | `asa_country_or_region` | ASA の国またはリージョン | | `asa_creative_set_name` | ASA クリエイティブセット名 | | `fbclid` | Facebook クリック ID | | `ttclid` | TikTok クリック ID | | `utm_source` | UTM ソースパラメータ | | `utm_medium` | UTM メディアパラメータ | | `utm_campaign` | UTM キャンペーンパラメータ | | `utm_term` | UTM タームパラメータ | | `utm_content` | UTM コンテンツパラメータ | --- # File: ua-google-cloud-storage --- --- title: "Google Cloud Storage" description: "Adapty UA とGoogle Cloud Storage を連携して、ユーザー獲得データを安全に保存する方法を解説します。" --- Adapty UA と Google Cloud Storage の連携により、ユーザー獲得キャンペーンデータを1か所に安全に保存できます。キャンペーンのパフォーマンスデータ、アトリビューションデータ、ユーザー獲得イベントを .csv ファイルとして Google Cloud Storage バケットに保存できます。 この連携を設定するには、Google Cloud Console と Adapty UA ダッシュボードでいくつかの簡単な手順を実行する必要があります。 :::note スケジュール Adapty UA は、毎日 UTC 4:00 に Google Cloud Storage へデータを送信します。 各ファイルには、UTC で前日の丸1日分(00:00:00〜23:59:59)に作成されたイベントのデータが含まれます。たとえば、3月8日の UTC 4:00 に自動エクスポートされるデータには、3月7日の UTC 00:00:00〜23:59:59 に作成されたすべてのイベントが含まれます。 ::: ## Google Cloud Storage 連携の設定方法 \{#how-to-set-up-google-cloud-storage-integration\} ### ステップ 1. Google Cloud Storage の認証情報を作成する \{#step-1-create-google-cloud-storage-credentials\} このガイドでは、Google Cloud Platform Console で必要な認証情報を作成する手順を説明します。 Adapty UA が指定したバケットに生データレポートをアップロードするには、サービスアカウントのキーと、対応するバケットへの書き込みアクセス権が必要です。サービスアカウントのキーを提供し、バケットへの書き込みアクセスを許可することで、Adapty UA がプラットフォームからストレージ環境へ生データレポートを安全かつ効率的に転送できるようになります。 :::warning サービスアカウントの HMAC キー認証のみをサポートしています。Google Cloud Storage への適切なアクセスを有効にするため、サービスアカウントの HMAC キーに「Storage Object Viewer」「Storage Legacy Bucket Writer」「Storage Object Creator」のロールが付与されていることを確認してください。 ::: #### 2.1. サービスアカウントの作成 \{#21-create-service-account\} 1. Google Cloud アカウントの [IAM](https://console.cloud.google.com/projectselector2/iam-admin/serviceaccounts) セクションに移動し、対象のプロジェクトを選択するか、新しいプロジェクトを作成します <img src="/assets/shared/img/30a81ef-CleanShot_2023-03-17_at_15.22.142x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. 次に、「+ CREATE SERVICE ACCOUNT」ボタンをクリックして、Adapty UA 用の新しいサービスアカウントを作成します <img src="/assets/shared/img/98f8ebf-CleanShot_2023-03-17_at_15.40.062x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. アクセス権は後の手順で付与するため、最初のステップのフィールドに必要事項を入力します。このページの詳細については、[こちら](https://docs.cloud.google.com/iam/docs/service-accounts-create)のドキュメントをご覧ください <img src="/assets/shared/img/2190c50-CleanShot_2023-03-17_at_15.48.552x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. [プライベート JSON キー](https://docs.cloud.google.com/iam/docs/keys-create-delete)を作成してダウンロードするには、「KEYS」セクションに移動し、「ADD KEY」ボタンをクリックします <img src="/assets/shared/img/8a45468-CleanShot_2023-03-17_at_15.58.092x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. 「DETAILS」セクションで、作成したサービスアカウントに紐づくメールアドレスを確認してコピーします。この情報は、アカウントを認可してバケットへの書き込みを許可するための後続手順で必要になります <img src="/assets/shared/img/6ccd0f0-CleanShot_2023-03-17_at_16.03.162x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> #### 2.2. バケットの権限を設定する \{#22-configure-bucket-permissions\} 6. Google Cloud Storage の [Buckets](https://console.cloud.google.com/storage/browser) ページに移動し、既存のバケットを選択するか、Adapty UA のユーザー獲得データレポートを保存するための新しいバケットを作成します 7. 「PERMISSIONS」セクションに移動し、[GRANT ACCESS](https://docs.cloud.google.com/identity/docs/how-to?hl=en) オプションを選択します <img src="/assets/shared/img/3cdd937-CleanShot_2023-03-17_at_16.14.232x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 8. 「PERMISSIONS」セクションで、手順5で取得したサービスアカウントのメールアドレスを入力し、「Storage Object Creator」ロールを選択します 9. 最後に、「SAVE」をクリックして変更を適用します <img src="/assets/shared/img/62801f4-CleanShot_2023-03-17_at_16.17.312x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 10. バケット名は後で使用するため、メモしておいてください 11. これらの手順を完了すると、Google Cloud Console での必要な設定は完了です。最後のステップは、バケット名の入力と、Adapty UA で使用する JSON ファイルのダウンロードです <img src="/assets/shared/img/c967e16-CleanShot_2023-03-17_at_16.23.332x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### ステップ 2. Adapty UA で連携を設定する \{#step-2-configure-integration-in-adapty-ua\} 1. [**Integrations** -> **Google Cloud Storage**](https://app.adapty.io/ua/integrations/google-cloud-storage) に移動します 2. **Export install events to Google Cloud Storage** トグルをオンにします 3. Google Cloud Storage と Adapty UA の接続を確立するために、必須フィールドを入力します。 | フィールド | 説明 | |:------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Google Cloud service account key file** | ダウンロードしたプライベート [JSON キーファイル](ua-google-cloud-storage#step-1-create-google-cloud-storage-credentials)。 | | **Google Cloud bucket name** | データを保存する Google Cloud Storage のバケット名。Google Cloud Storage 環境内で一意である必要があり、スペースを含めることはできません。 | | **Folder inside the bucket** | バケット内にデータを保存するフォルダの名前。バケット内で一意である必要があり、データの整理に利用できます。このフィールドは任意です。 | ## 手動データエクスポート \{#manual-data-export\} Google Cloud Storage への自動イベントデータエクスポートに加えて、Adapty UA は手動ファイルエクスポート機能も提供しています。この機能を使用すると、ユーザー獲得データの特定の日付を選択し、GCS バケットへ手動でエクスポートできます。エクスポートするデータとタイミングをより細かく制御できます。 ## テーブル構造 \{#table-structure\} Google Cloud Storage 連携では、Adapty UA はインストールイベントの履歴データを保存するテーブルを提供します。このテーブルには、ユーザープロファイル、収益と手取り額、配信元ストアなどのデータが含まれています。 :::warning この構造は、弊社または弊社が連携しているサードパーティによって新しいデータが追加されるにつれて、将来的に拡張される可能性があります。処理コードは、構造全体ではなく特定のフィールドに依存するよう、十分に堅牢に設計してください。 ::: イベントのテーブル構造は以下のとおりです。 | カラム | 説明 | |--------------------------|-------------------------------------------| | `adapty_profile_id` | Adapty プロファイルの一意識別子 | | `install_id` | インストールの一意識別子 | | `created_at` | レコード作成タイムスタンプ(ISO 8601) | | `installed_at` | アプリインストールのタイムスタンプ(ISO 8601) | | `store` | アプリストア(`ios`、`android`) | | `country` | ユーザーの国コード(ISO 3166-1 alpha-2) | | `ip_address` | クライアント IP アドレス | | `idfa` | iOS 広告識別子(IDFA) | | `idfv` | iOS ベンダー識別子(IDFV) | | `gaid` | Google 広告 ID(Android) | | `android_id` | Android デバイス ID | | `app_set_id` | Android App Set ID | | `channel` | アトリビューションチャネル | | `campaign_id` | キャンペーン識別子 | | `campaign_name` | キャンペーン名 | | `adset_id` | 広告セット識別子 | | `adset_name` | 広告セット名 | | `ad_id` | 広告識別子 | | `ad_name` | 広告名 | | `keyword_id` | キーワード識別子 | | `keyword_name` | キーワード名 | | `asa_org_id` | Apple Search Ads 組織 ID | | `asa_keyword_match_type` | ASA キーワードマッチタイプ(`Exact`、`Broad`) | | `asa_attribution` | ASA アトリビューションデータ(JSON 文字列) | | `asa_conversion_type` | ASA コンバージョンタイプ | | `asa_country_or_region` | ASA の国またはリージョン | | `asa_creative_set_name` | ASA クリエイティブセット名 | | `fbclid` | Facebook クリック ID | | `ttclid` | TikTok クリック ID | | `utm_source` | UTM ソースパラメータ | | `utm_medium` | UTM メディアパラメータ | | `utm_campaign` | UTM キャンペーンパラメータ | | `utm_term` | UTM タームパラメータ | | `utm_content` | UTM コンテンツパラメータ | --- # File: adapty-mail --- --- title: "Adapty Mail" description: "AI-generated email campaigns that turn trial users into paid subscribers." --- <CustomDocCardList ids={['mail-get-started', 'mail-brand', 'mail-collect-emails', 'mail-send-data-via-api', 'mail-sending-domain', 'mail-create-campaign', 'mail-analytics']} /> Adapty Mail turns your Adapty user data into AI-generated email sequences that convert trial users into paid subscribers. It uses the profile data already in your Adapty project to build, send, and attribute campaigns — no separate email platform required. ## Why Adapty Mail? Sending targeted email campaigns requires copy, design, sending infrastructure, and revenue attribution. Each of these is a separate problem to solve. Adapty Mail handles all of it. Your brand profile is built from your store URL and any other sources you add, and a complete email sequence is generated from it in under 2 minutes — sent from your own domain with personalized checkout links and purchase attribution. ## How it works 1. **Collect emails**: Your app passes user emails and `customer_user_id` values to Adapty via SDK. Adapty Mail uses this data to identify recipients and attribute revenue to the specific email that drove each purchase. You can also send this data from your server with the [Adapty Mail API](mail-send-data-via-api). 2. **Build a web paywall**: The checkout page every email links to. 3. **Generate a sequence**: AI uses your brand profile to produce 1–15 emails — copy, design, hero images, and personalized checkout links matched to your app's category and brand voice. 4. **Launch a flow**: Pick a trigger (never purchased, renewal cancelled, billing issue, subscription expired, or refunded) and a segment, then attach your campaign. Emails start sending automatically, and revenue from email-driven purchases is attributed back to the specific email that drove the conversion. ## Requirements To use Adapty Mail, you need: - An Adapty account - Email collection set up in your app — see [Collect user emails](mail-collect-emails) - `customer_user_id` configured in your Adapty SDK - A domain you control with access to its DNS settings - A web payment provider (Stripe, Paddle, or PayPal) ## Get started Follow the [Get started with Adapty Mail](mail-get-started) guide to complete setup and launch your first campaign. --- # File: mail-get-started --- --- title: "Adapty Mailを始める" description: "Adapty Mailをセットアップして、最初のメールフローを起動する方法を説明します。" --- このガイドでは、Adapty Mailをセットアップして最初のメールフローを起動する方法を説明します。 :::note 独自のサーバーからAdapty SDKを使わずにAdapty Mailにデータを送ることもできます。ユーザーのメールアドレスや購入情報をバックエンドで管理している場合、または別のソースからサブスクライバーをインポートする場合は、[Adapty Mail APIでメールとトランザクションを送信する](mail-send-data-via-api)をご覧ください。 ::: セットアップは6つのパートで構成されています: 1. [Adapty SDKを設定する](#1-configure-your-adapty-sdk) 2. [送信ドメインを設定する](#2-set-up-your-sending-domain) 3. [Webペイウォールを作成する](#3-create-a-web-paywall) 4. [AIでキャンペーンを生成する](#4-generate-a-campaign-with-ai) 5. [フローを起動する](#5-launch-a-flow) 6. [送信を有効にする](#6-enable-sending) :::tip AdaptyからAdapty Mailに登録した場合、**ブランドプロファイル**はプロジェクトのストアURLから自動的に作成されます。**Brand**をいつでも開いて確認・修正できます — [Brand](mail-brand)をご覧ください。スタンドアロンで登録した場合は、キャンペーンやWebペイウォールを生成する前に同じページでブランドを設定してください。 ::: ## 始める前に \{#before-you-start\} 開始前に以下を確認してください: - **DNSアクセス**: ルートドメインにレコードを追加できること。 - **Web決済プロバイダー**: サブスクリプションプロダクトが設定済みのStripe、Paddle、またはPayPalアカウントを持っていること。 ## 1. Adapty SDKを設定する \{#1-configure-your-adapty-sdk\} :::important Adapty Mailは**スタンドアロンプロダクト**です。ペイウォール、サブスクリプション、アナリティクスをAdaptyで管理していなくても使用できます — スタック全体の移行は必須ではありません。 正確な収益データを取得するための最小構成は、Adapty SDKをオブザーバーモードでインストールし、App Serverサーバー通知を有効にすることです。 ::: Adapty Mailがアプリから必要とするのは、購入データ(各コンバージョンを誘導したメールに収益を紐付けるため)、安定したユーザー識別子、そしてユーザーのメールアドレスの3つです。 1. **Adaptyで収益をトラッキングする。** 最初のステップは、アプリ内課金がすでに実装されているかどうかによって異なります: - **Adaptyでアプリ内課金をすでに実装している場合**は、この段階で追加の作業は不要です。 - **Adapty以外でアプリ内課金をすでに実装していてAdaptyへの移行を予定していない場合**は、お使いのプラットフォーム向けAdapty SDKをオブザーバーモードでインストールしてください。この段階では、SDKをプロジェクトに追加し、オブザーバーモードを有効にして起動し、トランザクションをレポートするだけで構いません。プラットフォームガイド: [iOS](implement-observer-mode)、[Android](implement-observer-mode-android)、[React Native](implement-observer-mode-react-native)、[Flutter](implement-observer-mode-flutter)、[Unity](implement-observer-mode-unity)、[Kotlin Multiplatform](implement-observer-mode-kmp)、[Capacitor](implement-observer-mode-capacitor)。 - **アプリ内課金をまだ実装しておらず、Adaptyを使いたい場合**は、[クイックスタートガイド](quickstart)の手順を完了して、購入処理をAdaptyに委譲してください。 次に、[AdaptyでApp Storeサーバー通知を有効にする](enable-app-store-server-notifications)ことで、App Storeから収益関連の更新を直接受け取れるようにします。 2. **ユーザー識別を設定する。** バックエンドのユーザーID、Firebase UID、または類似の安定したIDを渡してください。`Adapty.identify()`を呼び出すか、SDK起動時に`.activate()`に`customerUserId`を渡す方法で設定します。`customer_user_id`は、Adapty Mailがキャンペーン、クリック、購入を正しいプロファイルに紐付けるために使用されます。 プラットフォームガイド: [iOS](identifying-users)、[Android](android-identifying-users)、[React Native](react-native-identifying-users)、[Flutter](flutter-identifying-users)、[Unity](unity-identifying-users)、[Kotlin Multiplatform](kmp-identifying-users)、[Capacitor](capacitor-identifying-users)。 3. **ユーザーのメールアドレスを収集する。** アプリ内でユーザーがメールアドレスを提供したら(たとえばサインアップ時やチェックアウト時)、emailアトリビュートを指定して`updateProfile`を呼び出し、Adaptyに渡してください。キャンペーンのすべての受信者にはこの値が必要です。 プラットフォームガイド: [iOS](setting-user-attributes)、[Android](android-setting-user-attributes)、[React Native](react-native-setting-user-attributes)、[Flutter](flutter-setting-user-attributes)、[Unity](unity-setting-user-attributes)、[Kotlin Multiplatform](kmp-setting-user-attributes)、[Capacitor](capacitor-setting-user-attributes)。 アプリでまだメールアドレスを収集していない場合は、[メールアドレス収集の戦略](mail-collect-emails#email-collection-strategies)をご覧ください。 ## 2. 送信ドメインを設定する \{#2-set-up-your-sending-domain\} Adapty Mailはあなた自身のドメインから送信します。DNSレコードを一度追加すれば、すべてのキャンペーンで同じ確認済みドメインが使用されます。 1. Adapty Mailで、**Settings → Email Domains**に移動します。 2. ルートドメイン(例: `yourapp.com`)を入力して、**Preview**をクリックします。受け付けられるのはApexドメインのみです — `app.yourapp.com`のようなサブドメインは入力時に拒否されます。 3. Adaptyが2つの送信サブドメイン(`mail.yourapp.com`と`email.yourapp.com`)を生成します。**Confirm**をクリックして、必要なDNSレコードを確認します。 4. ドメインレジストラで、表示される10件のDNSレコード(サブドメインごとに5件)を追加します: - サブドメインごとに3件のCNAMEレコード(DKIM) - サブドメインごとに1件のMXレコード(Mail-From) - サブドメインごとに1件のTXTレコード(SPF、`v=spf1 include:amazonses.com ~all`) 5. 任意で、ルートドメインにDMARC TXTレコードを追加します(推奨)。 6. **Settings → Email Domains**に戻り、**Check Verification**をクリックします。 確認のタイミングについての概要: - **自動ポーリング**: 最初のチェックは送信から約5分後に実行されます。レコードが見つかるまで、間隔は最大1時間ごとに延びていきます。 - **手動チェック**: **Check Verification**をいつでもクリックして即時チェックを実行できます。 - **DNS伝搬**: 通常は数分で完了しますが、まれに最大48時間かかることがあります。 - **確認ウィンドウ**: 7日間。期限が切れても、DNSレコードはそのまま残ります — **Settings → Email Domains**でドメインを再入力すると、新しいウィンドウが開始されます。 各レコードタイプとドメインウォームアップの詳細については、[送信ドメインの設定](mail-sending-domain)をご覧ください。 ## 3. Webペイウォールを作成する \{#3-create-a-web-paywall\} すべてのメールはWebペイウォールにリンクしています — CTAをクリックしたユーザーが訪れるチェックアウトページです。2つの選択肢があります: - **AIで生成する**: バンドルされたWebペイウォールビルダーがアプリ向けに自動生成します。 - **独自のホスト済みペイウォールを使用する**: すでにホストしているペイウォールを接続します。 開始するには、Adapty Mailで**Web Paywalls → Create**に移動します。 ### オプションA: AIで生成する \{#option-a-generate-with-ai\} ページにはインラインボタン付きの**Prerequisites**チェックリストが表示されます — 順番に進めてから戻って生成してください。チェックリストには、ペイウォールビルダーへのログイン、Stripeの接続、プロダクトの追加、結果の確認が含まれます。詳細なウォークスルーは[チェックアウトの設定](mail-checkout)をご覧ください。 すべての前提条件が緑になったら、**Generate**をクリックして生成ダイアログを開きます: - **Environment**: **Production**または**Sandbox**を選択します。SandboxはStripeのテストモードのプロダクトを使用するため、開発環境やローカル環境のデフォルトとして安全です。 - **Plans**: 最大**3つのStripeプラン**を選択します(各プランはプロダクト+価格)。これらが生成されたペイウォールでユーザーに提示されるオファーです。 **Generate**をクリックしてビルドを実行します。完了したら、エディターを開いて確認・公開してください。 :::important ペイウォールはメールのチェックアウトリンクのトラフィックを受け付けるために、公開されている必要があります。未公開のペイウォールは、ユーザーがメールのチェックアウトリンクをクリックするとエラーを返します。 ::: ### オプションB: 独自のホスト済みペイウォールを使用する \{#option-b-use-your-own-hosted-paywall\} 1. **Enter URL manually**を選択します。 2. ホスト済みペイウォールのURLを貼り付けます。URLにはクエリパラメーターとして`{email}`と`{external_profile_id}`のプレースホルダーを含める必要があります — Adapty Mailが受信者ごとにこれらを埋め込むことで、チェックアウトページが訪問者を識別できるようになります。例: ``` https://example.com/paywall?email={email}&profile={external_profile_id} ``` 3. 保存して公開します。 チェックアウトファネルの構造とパーソナライゼーションの仕組みについては、[チェックアウトの設定](mail-checkout)をご覧ください。 ## 4. AIでキャンペーンを生成する \{#4-generate-a-campaign-with-ai\} AIがメールシーケンス全体を作成します — コピー、デザイン、ヒーロー画像、パーソナライズされたチェックアウトリンクまで、すべてあなたのブランドに合わせて調整されます。 1. Adapty Mailで**Campaigns**に移動し、**Create**をクリックします。 2. キャンペーン名を設定します。 3. **Web paywall**ドロップダウンで、前のステップで追加したWebペイウォールを選択します。 4. **Generate emails**をクリックします。 5. 生成ダイアログに入力します — トーン、言語、任意のカスタムプロンプト(最大2,000文字)、メールの件数(1〜15、デフォルトは4)。各フィールドの説明は[キャンペーンの作成](mail-create-campaign)をご覧ください。 6. **Generate**をクリックします。生成には通常数分かかります。完了できない場合は5分後にタイムアウトします — その場合は再試行してください。 7. 各メールをプレビューします。プレビューヘッダーには**テーマトグル**(Auto、Light、Dark)があり、プレビューの表示方法を制御します — 生成されたコンテンツはどのモードでも同一です。個別のメールを再生成したり、コピーを編集したり、HTMLエディターを開いて細かく調整したりできます。 8. **Create**をクリックしてキャンペーンを保存します。 キャンペーンは**下書き**として保存され、まだ送信されません — キャンペーンはフローに紐付けられた時点で初めて有効になります(次のステップ)。キャンペーンエディターには「公開」アクションは別途ありません。 ## 5. フローを起動する \{#5-launch-a-flow\} フローは**トリガー**(サブスクリプションの期限切れなどのイベント)と**セグメント**を組み合わせ、選択した**キャンペーン**をそのセグメントに送信します。Adapty Mailには5つの固定トリガーがあり、それぞれ専用のフロービューを持っています。 1. Adapty Mailで**Flows**に移動し、設定したいトリガーを開きます: - **Never purchased** — サインアップしたがまだ購入していないユーザー。 - **Renewal cancelled** — 自動更新をオフにしたが、まだアクティブなサブスクリプションを持つユーザー。 - **Billing issue** — 支払い失敗、カード拒否や期限切れ、またはグレース期間中のユーザー。 - **Expired** — サブスクリプションが失効してアクセスが失われたユーザー。 - **Refunded** — 購入後に返金を申請したユーザー。 各トリガーの目的とトーンのガイダンスについては、[フロー](mail-flows)をご覧ください。 2. **Create**をクリックしてダイアログを開きます。 3. ダイアログで: - **Segment**を選択します(例:**All Users**でこのトリガーに該当するすべてのユーザーをターゲットにする、またはプロファイルアトリビュートに基づいて新しいセグメントを作成する)。 - コンテンツタイプは**Campaign**のままにします(A/B Testオプションは[A/B テスト](mail-ab-testing)で説明しています)。 - ステップ4で保存した**Campaign**を選択します。 4. **Save**をクリックします。 フローはすぐに有効になります — 別途起動ステップはありません。この時点から、セグメントに一致するユーザーはトリガーイベントが発生した時点でキャンペーンを受け取り始めます。 :::note 同じトリガーに複数のセグメント → キャンペーンの行を追加できます。優先順位の高い順に実行されます。**All Users**行を使用する場合は、より具体的なセグメントにマッチしないすべてのユーザーをキャッチできるよう、最後(最低優先度)の行にする必要があります。 ::: ## 6. 送信を有効にする \{#6-enable-sending\} この時点でキャンペーンは設定されていますが、まだ実際には送信されていません — サブスクリプションイベントをAdapty Mailに同期する**Adaptyインテグレーション**がまだオフの状態です。これをオンにすることが最後のステップです。イベントが流れ始め、セグメントがマッチし始め、メールが送信され始めます。 このステップはステップ5が完了した後にのみ実行できます。フローを起動する前は、**Settings → Integrations**の**Enable**ボタンが無効になっており、「*Set up at least one flow before enabling Adapty integration.*」というツールチップが表示されます。 1. Adapty Mailで、**Settings → Integrations**に移動します。 2. **Enable Adapty integration**(または、以前のセットアップからインテグレーションが既に存在する場合は**Enable**)をクリックします。 有効にすると、Adaptyはすべてのサブスクリプションイベント(新規サブスクリプション、更新、トライアル、コンバージョン、返金、支払い問題)をAdapty Mailに送信します。これらのイベントがセグメントのメンバーシップ、キャンペーンのルーティング、ユーザーがコンバートしたときにシーケンスを一時停止するストップ条件を駆動します。 :::note Settingsの**Adaptyインテグレーション**トグルは、Adapty MailにサインインさせたAdaptyパートナーワークスペースとは*異なります*。パートナーワークスペースはアカウントを作成し、(Adapty経由で登録した場合は)ブランドを作成したものです。ここのインテグレーショントグルはイベント同期を制御します — プロジェクトごとにオンにする必要があります。 ::: ## トラブルシューティング \{#troubleshooting\} | 問題 | 解決策 | | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------ | | DNS確認が進まない | レコードが正確に一致しているか確認します — 末尾のドット、正しいCNAMEターゲット。5〜10分待ってから**Check Verification**をもう一度クリックします | | 確認ウィンドウが期限切れ | レコードはそのまま残ります。**Settings → Email Domains**でドメインを再入力して新しいウィンドウを開始してください | | 生成に失敗またはタイムアウト | インターネット接続を確認して再試行してください。問題が続く場合はAdaptyサポートにお問い合わせください | ## 詳細情報 \{#learn-more\} - **[ユーザーメールアドレスの収集](mail-collect-emails)**: アプリでまだ収集していない場合のメールカバレッジ取得戦略。 - **[送信ドメインの設定](mail-sending-domain)**: DNSレコードの詳細、ウォームアップ階層、トラブルシューティング。 - **[チェックアウトの設定](mail-checkout)**: チェックアウトファネルの構造とパーソナライゼーション。 - **[キャンペーンアナリティクス](mail-analytics)**: 配信、エンゲージメント、収益のトラッキング。 - **[A/B テスト](mail-ab-testing)**: 複数のシーケンスバージョンのテスト。 --- # File: mail-collect-emails --- --- title: "Adapty Mailのユーザーメール収集" description: "ユーザーメールと安定した識別子をAdaptyに渡して、キャンペーンがユーザーに届くようにします。" --- Adapty Mailがメールを配信するには、各ユーザーに対して安定した `customer_user_id` とメールアドレスが必要です。キャンペーンを開始する前に、アプリのコードで両方を設定しておきましょう。 ## ユーザーメールの収集 \{#collect-user-emails\} 各ユーザーについて、Adaptyに渡す必要がある値は2つです。ユーザーを識別する安定した `customer_user_id` と、メールアドレスそのものです。識別が先決です。識別なしでは、Adaptyにはメールを紐付けるプロファイルがありません。 1. **ユーザーを識別する。** バックエンドのユーザーID、Firebase UID などの安定したIDを渡します。SDKの起動時に `.activate()` の `customerUserId` として渡すか、後から(例えばログイン時に)`Adapty.identify()` を呼び出す方法があります。いずれの場合も、ペイウォールを表示する前にIDを設定する必要があります。 プラットフォームガイド: [iOS](identifying-users)、[Android](android-identifying-users)、[React Native](react-native-identifying-users)、[Flutter](flutter-identifying-users)、[Unity](unity-identifying-users)、[Kotlin Multiplatform](kmp-identifying-users)、[Capacitor](capacitor-identifying-users)。 2. **メールアドレスを渡す。** ユーザーがメールアドレスを提供したら、すぐに `updateProfile` の `email` パラメーターを使ってAdaptyに送信します。 プラットフォームガイド: [iOS](setting-user-attributes)、[Android](android-setting-user-attributes)、[React Native](react-native-setting-user-attributes)、[Flutter](flutter-setting-user-attributes)、[Unity](unity-setting-user-attributes)、[Kotlin Multiplatform](kmp-setting-user-attributes)、[Capacitor](capacitor-setting-user-attributes)。 :::important - `customer_user_id` は常に**安定した**値を渡してください。匿名の識別子は使用しないでください。ユーザーがアプリをアンインストールして再インストールした場合、AdaptyはこのIDを使って再インストールを既存のプロファイルに紐付け、購入を正しいユーザーに帰属させます。 - メールアドレスをAdaptyに収集・送信する前に、ユーザーから明示的な同意を取得してください。対象市場におけるGDPR、CAN-SPAMおよび類似の規制への準拠はお客様の責任となります。 ::: <Details> <summary>メール収集のカバレッジを確認する</summary> 収集を実装したら、Adaptyでカバレッジを確認しましょう。 1. **Customers → Profiles** に移動します。 2. メールアドレスが設定されているプロファイルでフィルタリングします。 最初のキャンペーンを開始する前に、アクティブユーザーの少なくとも30〜50%のメールカバレッジを目標にしてください。100%になるまで待つ必要はありません。30%に達したらすぐに開始しましょう。後でメールアドレスを提供したユーザーは、条件を満たした時点でアクティブなキャンペーンに自動的に登録されます。 </Details> ## メール収集の戦略 \{#email-collection-strategies\} 多くのアプリはデフォルトではメールを収集しません。アプリの現状に合ったアプローチを選んでください。 | 戦略 | 最適なケース | 仕組み | | ---------------------------------- | -------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | | **既存の認証** | ログイン機能のあるアプリ | すでにメールアドレスを持っているので、ユーザーが認証した後にAdaptyへ渡すだけです。どこで読み取るかは以下の認証方法リファレンスを参照してください。 | | **ペイウォール前のメールゲート** | 認証なしのアプリ(健康・ウェルネス・占星術・フォトエディターなど) | オンボーディングとペイウォールの間にメール入力画面を1つ追加します。ユーザーがすでに時間を投資しているため、コンバージョンは通常70〜90%に達します。 | | **Webペイウォールビルダーのチェックアウト** | SDKの作業を最小限に抑え、Webでメールを収集する場合 | Webペイウォールビルダーの最初の画面でメールアドレスを収集し、Adaptyに渡します。アプリ内ゲートが稼働する前にキャンペーンをクリックしたユーザーに有効です。 | | **オンボーディングのステップ** | クイズ形式のオンボーディング(フィットネス・栄養・教育) | オンボーディングの2〜3ステップ目にメール入力を配置します。価値の提供として訴求し(「パーソナライズされたプランをメールでお送りします」など)、スキップ可能にしないようにしましょう。 | | **Adapty Mail API** | AdaptyのSDKを使わずにサーバーからメールを送信する場合 | Adapty Mail APIの [プロファイルを保存](api-mail/operations/saveProfile) エンドポイントにプロファイルを送信します。詳細は [Adapty Mail APIを使ったメールとトランザクションの送信](mail-send-data-via-api) を参照してください。 | ## 制限事項 \{#limitations\} - **匿名ユーザー**: 安定した `customer_user_id` を持たないユーザーはキャンペーンを受け取ることができません。アカウント作成時やログイン時に識別することで、その後にメールアドレスを提供すればAdaptyのプロファイルと紐付けられます。 - **メールアドレスのないユーザー**: メールアドレスのないプロファイルはキャンペーン配信から除外され、キャンペーンの分析にも表示されません。メールアドレスを提供した時点で、以降のキャンペーンの対象となります。 --- # File: mail-send-data-via-api --- --- title: "Adapty Mail APIでメールとトランザクションを送信する" description: "Adapty SDKを使わずに、サーバーから直接Adapty Mailにユーザープロファイルとトランザクションを送信します。" --- Adapty Mail APIを使うと、Adapty SDKを経由せずに、サーバーから直接Adapty Mailにユーザープロファイルとトランザクションを送信できます。以下のような場合に活用してください: - Adapty Mailにまだベースがない状態でサブスクライバーを追加したい場合 - 他のアプリのサブスクライバーベースを再利用したい場合 - バックエンドをソースオブトラスとして、サーバー間でAdapty Mailにデータを送りたい場合 :::note **APIとSDK、どちらを使う?** ほとんどのアプリは、メールや購入情報を自動収集するAdapty SDKを通じてAdapty Mailにデータを送信します。アプリにAdapty SDKがない場合、データがすでにサーバー上にある場合、または別のソースからサブスクライバーをインポートする場合にAPIを選択してください。 ::: ## 始める前に \{#before-you-start\} :::warning データを送信する前に、Adapty Mailのセットアップを完了させてください。具体的には、キャンペーン、セグメント(必要な場合)、ウェブペイウォール、そして起動済みのフローが必要です。Adapty Mailは、このセットアップ完了後に作成されたプロファイルにのみメールを送信します。それより前に送信したプロファイルはメールを受信しません。まず[Adapty Mailをはじめる](mail-get-started)に従ってセットアップを完了させてから、こちらに戻ってください。 ::: APIキーとベースURLも必要です: - **シークレットAPIキー**: Adapty Mailの **Settings** に移動し、シークレットAPIキーをコピーします。キーはプロジェクト固有であるため、APIはどのプロジェクトのデータかを識別できます。 - **ベースURL**: すべてのリクエストは `https://api-mail.adapty.io` に送信します。 - **認証**: **Authorization** ヘッダーに `Bearer {your_secret_api_key}` の形式でキーを送信します。 :::important メールを収集してAdapty Mailに送信する前に、明示的な同意を取得してください。GDPR、CAN-SPAM、および各市場の関連法規への準拠はお客様の責任となります。 ::: ## ユーザープロファイルを送信する \{#send-user-profiles\} プロファイルには、ユーザーのメールアドレスと属性が含まれます。プロファイルを作成または更新するには、`/api/v1/profile/save/` にPOSTリクエストを送信します。 以下の3つのフィールドが必須です: - アプリまたはバックエンドが管理する安定した `external_profile_id` - Adapty Mailがキャンペーンを配信する `email` - ユーザー作成日時を示す `external_created_at`(セグメントで使用可能) :::important `external_profile_id` には必ず安定した値を使用し、匿名値やインストールごとの値は使わないでください。Adapty Mailはこれを使用して、メール、クリック、購入を1つのプロファイルに紐付けます。 ::: ```bash curl --request POST \ --url 'https://api-mail.adapty.io/api/v1/profile/save/' \ --header 'Authorization: Bearer {your_secret_api_key}' \ --header 'Content-Type: application/json' \ --data '{ "external_profile_id": "user_12345", "external_created_at": "2026-06-01T10:30:00Z", "email": "jane@example.com", "country": "US", "custom_attributes": { "plan": "trial" } }' ``` 利用可能なすべてのフィールドについては、[プロファイルを保存する](api-mail/operations/saveProfile)のリファレンスを参照してください。 ## トランザクションイベントを送信する \{#send-transaction-events\} :::note **一度も購入していない**フローでユーザーにリーチするには、メールアドレスを持つプロファイルがあれば十分です。それ以外のすべてのフローでは、トランザクションイベントも必要です。 ::: **一度も購入していない**フローを除くすべてのフローは、購入履歴によって動作します。購入、更新、キャンセルを処理する際にトランザクションイベントを送信することで、Adapty Mailはプロファイルを適切なフローに振り分けられます。トランザクションイベントは収益アトリビューションにも活用されます。**一度も購入していない**キャンペーンのみを実施する場合は省略できます。 トランザクションを記録するには、`/api/v1/profile/transaction-event/save/` にPOSTリクエストを送信します。プロファイルの送信時と同じ `external_profile_id` を使用することで、Adapty Mailがトランザクションを正しいユーザーに紐付けられます。 ```bash curl --request POST \ --url 'https://api-mail.adapty.io/api/v1/profile/transaction-event/save/' \ --header 'Authorization: Bearer {your_secret_api_key}' \ --header 'Content-Type: application/json' \ --data '{ "event_type": "subscription_started", "event_id": "evt_abc123", "event_datetime": "2026-06-10T14:20:05Z", "external_profile_id": "user_12345", "store": "app_store", "store_product_id": "premium_monthly", "store_transaction_id": "1000000123456789", "store_original_transaction_id": "1000000123456789", "purchased_at": "2026-06-10T14:20:00Z", "originally_purchased_at": "2026-06-10T14:20:00Z", "price_usd": "9.99" }' ``` 利用可能なすべてのフィールドについては、[トランザクションイベントを保存する](api-mail/operations/saveTransactionEvent)のリファレンスを参照してください。 ### イベントをフローにマッピングする \{#map-your-events-to-flows\} 発生した内容に合った `event_type` を送信してください。Adapty Mailはイベント履歴からプロファイルの状態を導き出し、対応するフローにルーティングします。 | `event_type` | 送信するタイミング | フロー | | --- | --- | --- | | `subscription_started` | ユーザーが新しいサブスクリプションを開始したとき | アクティブ — リエンゲージメントフローなし | | `subscription_renewed` | サブスクリプションが自動更新されたとき | アクティブ — リエンゲージメントフローなし | | `subscription_renewal_reactivated` | ユーザーが自動更新を再度有効にしたとき | アクティブ — リエンゲージメントフローなし | | `non_subscription_purchase` | ユーザーが買い切り購入をしたとき | アクティブ — リエンゲージメントフローなし | | `subscription_renewal_cancelled` | ユーザーが自動更新をオフにしたとき(有効期限まではアクティブ) | 更新キャンセル | | `billing_issue_detected` | 更新の支払いが失敗したとき | 請求問題 | | `entered_grace_period` | 支払いが失敗したがユーザーがグレース期間中のとき | 請求問題 | | `subscription_expired` | サブスクリプションが失効しアクセスが終了したとき | 期限切れ | | `subscription_refunded` | サブスクリプションの購入が返金されたとき | 返金済み | | `non_subscription_purchase_refunded` | 買い切り購入が返金されたとき | 返金済み | --- # File: mail-brand --- --- title: "Adapty Mailのブランド" description: "メール生成やウェブペイウォールを支えるブランドプロファイルを確認・改善しましょう。" --- **ブランド**とは、Adapty Mailがアプリの公開情報(App StoreまたはGoogle Playのリスティング、ランディングページ、利用規約・プライバシーページ、ソーシャルプロフィール)から構築する統合プロファイルです。メールのコピー、トーン、ビジュアル、ウェブペイウォールのコンテンツ、デモに活用されます。プロジェクトごとにブランドは1つで、すべての下流機能が同じプロファイルを参照します。 ブランドは、Adapty Mailのサイドバーにある **Brand** からアクセスできます。 - **AdaptyからAdapty Mailに登録した場合**: AdaptyプロジェクトのストアURLからブランドが自動的に作成されます。Brandページにはプロファイル全体が表示され、確認・改善をすぐに始められます。 - **スタンドアロンで登録した場合**: Brandページはセットアップ画面で開きます。詳しくは[ゼロからセットアップする](#set-up-from-scratch)をご覧ください。 ## ブランドプロファイルの内容 \{#whats-in-a-brand-profile\} ブランドには13のセクションがあります。Adapty Mailはこれらをメールおよびウェブペイウォール生成に直接使用します。 - **Identity**: アプリ名、短い説明、タグライン。 - **Visual identity**: カラー(プライマリ、バックグラウンド、セカンダリ、アクセント、テキスト、CTA)、タイポグラフィ、スタイルノート、ロゴURL。 - **Audience**: デモグラフィクス、言語、マーケット。 - **Features**: 各機能には名前、提供するベネフィット、オプションの説明があります。 - **Insights**: ユニークバリュープロポジション、観察事項、よくある反論と対応策のペア、タグ。 - **Brand voice**: トーン、フォーマリティレベル、語彙、感情的なレジスター。 - **Voice samples**: サンプルヘッドライン、サンプルCTA、メール生成時に使用されるトーンプリセット。 - **Social proof**: ユーザー数、評価、評価数、プレスメンション、主要指標。 - **Social links**: Twitter、Instagram、TikTok、YouTube、Facebook、LinkedIn。 - **Legal links**: 利用規約URL、プライバシーURL、サポートメール。 - **Reviews**: ストアソースから抽出したユーザーレビュー(内容、投稿者、評価、ソース)。 - **Pain points**: レビューやソーシャルシグナルに基づいた課題のステートメント。 - **FAQs**: メールコンテンツおよびウェブペイウォールセクションで使用される質問と回答。 ## セクションを手動で編集する \{#edit-a-section-manually\} ブランドビューの各セクションには **Edit** ボタンがあります。クリックするとそのセクションのインラインエディターが開きます。 1. 変更したいセクションの **Edit** をクリックします。 2. フィールドをその場で更新します。Adapty Mailは未保存の変更をドラフトとして追跡します。 3. ページ上部のドラフトバナーの **Save** をクリックして適用します。変更を破棄するには **Discard** をクリックします。 同時に開けるセクションは1つだけです。2つ目のセクションを開こうとすると、最初のセクションで完了またはキャンセルを求めるプロンプトが表示されます。 :::important ソースが処理中の間は編集が一時停止されます。処理中のソースが進行中の変更を上書きする可能性があるためです。処理が開始されると開いているエディターは自動的に閉じられ、処理が完了するまでドラフトバナーの **Save** ボタンは無効のままです。 ::: ## AIで改善する \{#refine-with-ai\} 右下の **Refine with AI** ボタンをクリックすると、ブランドの横にチャットパネルが開きます。自然な言葉で変更内容を説明すると、AIが改善案のドラフトを提示します。保存するか却下するかを選べます。 1. **Refine with AI** をクリックします。 2. 変更内容を説明します。チャットはブランド編集のみを対象としており、一般的な質問への回答やブランドプロファイル外のコピーの書き直しは行いません。 3. メインビューで提案されたドラフトを確認します。Adapty Mailは変更されたセクションをハイライト表示します。 4. ドラフトバナーの **Save** をクリックして適用するか、**Discard** をクリックして保存済みのブランドを維持します。 活用例のプロンプト: - 「トーンをもっと遊び心あるものにして。」 - 「オフラインモード機能を追加して。」 - 「ユニークバリュープロポジションを強化して。」 - 「オーディエンスの説明をUSマーケット向けに書き直して。」 ## ソースを追加する \{#add-more-sources\} ストアソースがプロファイルの基盤となります。追加のソースタイプは特定のセクションを補完します。ランディングページはビジュアルアイデンティティとコピーを改善し、利用規約・プライバシーページはリーガルリンクを改善し、ソーシャルプロフィールはボイスサンプルとソーシャルプルーフを改善します。 ブランドビューの **Sources** パネルには、すべてのソースとその下の **Add** フォームが表示されます。タイプを選び、URLを貼り付けて **Add** をクリックします。 - **App Store**: `https://apps.apple.com/...` - **Google Play**: `https://play.google.com/store/apps/details?id=...` - **Landing page**: マーケティングサイト(例: `https://yourapp.com`)。 - **Terms / Privacy**: 利用規約またはプライバシーページへの直接リンク。 - **Social profile**: Twitter、Instagram、TikTok、YouTube、Facebook、またはLinkedFBのURL。 ソースはタイプごとに1つだけです。そのタイプのソースが処理中または完了済みの場合、セレクターは無効になります。ソースを置き換えるには、ブランドを削除して再オンボーディングが必要です。個別のソースは削除できません。 ## ゼロからセットアップする \{#set-up-from-scratch\} プロジェクトにまだブランドがない場合(スタンドアロンのAdapty Mail登録の場合に一般的)、**Brand** ページはセットアップ画面で開きます。ストアソース(App StoreまたはGoogle Play)が基盤となり、他のソースタイプは後から追加できます。 1. ストア(**App Store** または **Google Play**)を選び、リスティングURLを貼り付けます。 2. **Build my brand** をクリックします。Adapty Mailがページを取得し、レビューを解析し、ブランドボイスを推定します。処理は通常1分以内に完了します。 3. 処理が完了すると、13のセクションすべてが入力された状態でブランドビューが開きます。 ソースが失敗した場合(無効なURL、アクセスできないページ、パーサーエラー)、画面にエラーメッセージと **Try again** ボタンが表示されます。URLを修正して再送信してください。 ## ブランドの使用場所 \{#where-the-brand-is-used\} ブランドは、アプリのサウンドとビジュアルを把握する必要があるすべての下流機能で使用されます。 - **メール生成**: コピー、トーン、ビジュアル、送信者ブロック、ヒーロー画像はすべてブランドから読み取られます。詳しくは[キャンペーンの作成](mail-create-campaign)をご覧ください。 - **ウェブペイウォールビルダー**: ブランドはペイウォール生成の前提条件です。`brand_saved` がない場合、生成はブロックされます。詳しくは[チェックアウトのセットアップ](mail-checkout)をご覧ください。 - **オンボーディング**: オンボーディングチェックリストの **Set up brand** ステップは、ブランドが存在すると完了に切り替わります。 ## ブランドを削除する \{#delete-a-brand\} **Delete brand** アクションは、ブランドビュー下部の **Danger zone** にあります。 1. Danger zoneセクションの **Delete** をクリックします。 2. ダイアログで確認します。 削除するとブランドプロファイルとすべてのソースが削除されます。元に戻す方法はありません。復元するには、スタート画面でApp StoreまたはGoogle PlayのURLを貼り付けて、ゼロからオンボーディングしてください。 :::warning 既存のキャンペーンは生成時のブランドスナップショットを保持しますが、新しいキャンペーンやペイウォール生成はブランドを再オンボーディングするまでブロックされます。 ::: ## 制限事項 \{#limitations\} - **プロジェクトごとに1つのブランド**: 各Adapty Mailプロジェクトには1つのブランドがあります。別のアプリをターゲットにするには、新しいプロジェクトを作成してください。 - **タイプごとに1つのソース**: ブランドはApp Store、Google Play、ランディングページ、利用規約・プライバシー、ソーシャルプロフィールのソースをそれぞれ1つずつ持てます。 - **ソースの個別削除不可**: 個別のソースはUIから削除できません。ソースを置き換える必要がある場合は **Delete brand** を使用してください。 - **処理中は編集が一時停止**: ソースが `pending` または `processing` 状態の間は、セクション編集、リファインチャットの保存、ブランド削除がすべてブロックされます。 - **失敗したソースはリストに残る**: `failed` 状態のソースはエラーメッセージとともにパネルに表示され続けます。同じタイプを再度送信して再試行してください。新しいスケジュールが成功すると、失敗したエントリは置き換えられます。 --- # File: mail-sending-domain --- --- title: "Adapty Mailの送信ドメインを設定する" description: "DNSレコードの追加、ドメインの確認、ウォームアップの仕組みを理解して、Adapty Mailがあなたの代わりにメールを送信できるようにします。" --- Adapty Mailは共有アドレスではなく、あなた自身のドメインからキャンペーンを送信します。そのため、送信者レピュテーションはあなたの管理下に置かれます。設定は一度行うだけで、すべてのキャンペーンに同じ確認済みドメインが使用されます。最小限の手順については、[Adapty Mailを始める](mail-get-started#2-set-up-your-sending-domain)のドメインセクションをご覧ください。この記事では、完全なセットアップ手順、確認の仕組み、および自動ウォームアップの動作について説明します。 ## 要件 \{#requirements\} - **Apexドメイン**: ルートドメイン(例:`yourapp.com`)を入力してください。サブドメインは使用できません。`app.yourapp.com`のような入力は検証時に拒否されます。 - **有効なNSレコード**: ドメインが解決できる必要があります。Adapty Mailはセットアップ中にDNSルックアップを実行し、有効なNSレコードがないドメインは拒否します。 - **Adaptyプロジェクトごとに1ドメイン**: ドメインは複数のプロジェクト間で共有できません。そのドメインがすでに別のプロジェクト(あなたのものか他の人のもの)に登録されている場合、セットアップは失敗します。 ## 送信ドメインを設定する \{#set-up-your-sending-domain\} セットアップウィザードには3つの画面があります:ドメインの入力、生成されたサブドメインの確認、DNSレコードの追加です。これらはすべて **Settings → Email Domains** にあります。 1. **ドメインを入力する。** **Domain** フィールドにApexドメインを入力し、**Preview** をクリックします。Adapty Mailは形式を検証し(ASCII、2つのラベル、先頭または末尾にハイフンなし、2文字以上のTLD)、DNSが解決できるか確認します。 2. **サブドメインを確認する。** Adapty Mailは固定プレフィックスを持つ2つの送信サブドメインを生成します — `mail.yourapp.com` と `email.yourapp.com` — それぞれが独自のSESアイデンティティを持ちます。また、各サブドメインの下にMail-Fromサブドメインも作成されます(`hello.mail.yourapp.com` と `hello.email.yourapp.com`)。内容を確認して **Confirm** をクリックします。 3. **DNSレコードを追加する。** 最後の画面には追加が必要なすべてのレコードが表示されます — 合計10件、送信サブドメインごとに5件、ルートにオプションのDMARCレコード1件です。**Download CSV** でリスト全体をエクスポートするか、レジストラに1件ずつコピーしてください。レコードを追加したら **Done** をクリックします。 <Details> <summary>DNSレコードリファレンス</summary> 各送信サブドメイン(`mail.yourapp.com` と `email.yourapp.com`)に対して、以下を追加します: **DKIM — CNAMEレコード3件。** メールが転送中に改ざんされていないことを証明する暗号署名。 | フィールド | 形式 | | ----- | ----------------------------------- | | タイプ | CNAME | | 名前 | `{token}._domainkey.{subdomain}` | | 値 | `{token}.dkim.amazonses.com` | **Mail-From — MXレコード1件。** バウンスを処理します。 | フィールド | 形式 | | -------- | -------------------------------------------------------- | | タイプ | MX | | 名前 | `hello.{subdomain}`(例:`hello.mail.yourapp.com`) | | 優先度 | `10` | | 値 | `feedback-smtp.{region}.amazonses.com` | **SPF — TXTレコード1件。** Adaptyがあなたの代わりに送信することを認証します。 | フィールド | 形式 | | ----- | -------------------------------------- | | タイプ | TXT | | 名前 | `hello.{subdomain}` | | 値 | `"v=spf1 include:amazonses.com ~all"` | ルートドメインにはオプションのDMARCレコードを追加します: | フィールド | 形式 | | ----- | --------------------- | | タイプ | TXT | | 名前 | `_dmarc.{domain}` | | 値 | `v=DMARC1; p=reject` | トークン、リージョン、その他の値はセットアップ時にAWS SESから提供されます。このリファレンスではなく、必ずAdapty MailのDNSレコード画面からコピーしてください。 </Details> ## 確認の仕組み \{#how-verification-works\} DNSレコードを追加すると、Adapty MailはDNSを自動的にポーリングします。手動でチェックをトリガーすることもできます。 - **自動ポーリング**: 送信後5分でポーリングが開始され、その後は各ラウンドごとに間隔が倍になります — 10分、20分、40分 — その後60分で上限に達します。レコードが見つかるか7日間のウィンドウが閉じるまで継続されます。 - **手動チェック**: **Check Verification** をクリックして即時チェックを強制します。手動チェックの間には60秒のクールダウンがあります — 素早く実行しすぎると *「Verification check is on cooldown.」* と返されます。 - **ステータスの状態**: 各サブドメインのDKIMとMail-Fromは独立して **Pending**、**Success**、**Failed** として追跡されます。4つのステータスすべてが **Success** になった場合にのみ、ドメインは完全に確認済みとみなされます。 - **7日間の期限**: 7日以内に確認が完了しない場合、アイデンティティは **Failed** とマークされます。DNSレコードはレジストラに残ります — **Settings → Email Domains** でドメインを再入力して新しいウィンドウを開始してください。 - **確認後**: 後でDNSレコードを削除または変更した場合、AWS SESはいずれアイデンティティをダウングレードします。送信を続ける限り、レコードはそのままにしておいてください。 - **DNS伝播**: 通常は数分で完了しますが、まれに最大48時間かかる場合があります。 ## ドメインウォームアップ \{#domain-warm-up\} 新しいドメインはGmailやYahooなどのメールプロバイダーに対してレピュテーションがないため、新しいドメインから大量に送信するとスパムに分類されるリスクがあります。Adapty Mailは14段階のティアにわたって1日あたりの送信上限を段階的に引き上げることで、自動的にウォームアップを処理します。設定は不要です。 ### ティアの仕組み \{#how-tiers-work\} ドメインは **Tier 1**(1日200件)から始まり、配信到達性の指標が良好な状態を維持すると自動的に進級します。バウンス率が上昇したり苦情率が増加したりすると、進級が一時停止され、レピュテーションが回復するまで逆行することもあります。 | ティア | 1日あたりの上限 | | ---- | ----------- | | 1 | 200 | | 2 | 400 | | 3 | 800 | | 4 | 1,500 | | 5 | 2,500 | | 6 | 4,000 | | 7 | 6,000 | | 8 | 8,000 | | 9 | 10,000 | | 10 | 13,000 | | 11 | 16,000 | | 12 | 20,000 | | 13 | 25,000 | | 14 | 30,000 | 現在のティアと1日あたりの上限は **Settings → Email Domains** で確認できます。 ### オーディエンスサイズによる開始時の影響 \{#impact-on-launch-by-audience-size\} | オーディエンスサイズ | 開始時の影響 | | ---------------- | ----------------------------------- | | 200人未満 | 1日目にオーディエンス全員に到達 | | 200〜2,000人 | 配信が数日間にわたって分散 | | 2,000人以上 | 配信が1〜2週間にわたって分散 | :::tip DNS確認が完了したらすぐに最初のキャンペーンを開始しましょう。送信を早く始めるほど、ドメインのティアが早く上がり、1日あたりの最大送信数に早く到達できます。 ::: ## 制限事項 \{#limitations\} - **プロジェクトごとに1ドメイン**: Adaptyプロジェクトごとに送信ドメインは1つだけ使用できます。別のドメインに切り替えるにはサポートに連絡してください — ダッシュボードに「ドメイン変更」の操作はありません。 - **プロジェクト間の一意性**: 別のプロジェクトにすでに登録されているドメインは再利用できません。 *「Domain is already registered to another project」* と表示された場合は、別のドメインを選択するかサポートにお問い合わせください。 - **確認済みドメインは削除不可**: いずれかのサブドメインが **Success** に達すると、ダッシュボードでの削除がブロックされます。保留中のドメインは削除できますが、レジストラからDNSレコードを手動で削除する必要があります。 - **固定サブドメインプレフィックス**: `mail.`、`email.`、および `hello.` のMail-Fromプレフィックスはハードコードされており、カスタマイズできません。これらのサブドメインがDNSですでに使用されている場合、セットアップが競合します。 - **Apexドメインのみ**: サブドメイン入力、末尾のドット、シングルラベルのホスト名は拒否されます。 - **国際化ドメイン非対応**: PunycodeとIDNはサポートされていません。ドメインはASCIIのみである必要があります。 ## トラブルシューティング \{#troubleshooting\} | 問題 | 解決策 | | ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------- | | "Enter a valid domain (e.g. example.com)" | 入力を確認してください:Apexのみ、ASCIIのみ、2文字以上のTLD、先頭または末尾にハイフンなし。 | | "Domain does not have valid DNS records" | Apexドメイン自体が解決できる必要があります。再試行前にNSレコードが有効であることを確認してください。 | | "Domain is already registered to another project" | 別のドメインを選択するか、登録が間違いだと思われる場合はサポートにお問い合わせください。 | | "Verification check is on cooldown" | 手動チェックの間は60秒待ってください。自動ポーリングはバックグラウンドで継続されています。 | | 確認がPendingのまま止まっている | DNSレコードが正確に一致しているか確認してください — 末尾のドットなし、正しいCNAMEターゲット。DNSの伝播には最大48時間かかる場合があります。 | | "Cannot delete domain: one or more identities have been successfully verified" | 確認済みドメインはダッシュボードから削除できません。サポートにお問い合わせください。 | | メールがスパムに振り分けられる | DMARCレコードが公開されているか確認してください。新しいドメインはウォームアップ期間が必要です — [ドメインウォームアップ](#domain-warm-up)をご確認ください。 | | バウンス率が高い | オーディエンスリストに有効なオプトイン済みのアドレスが含まれているか確認してください。バウンスはティアの進級を遅らせるか停止させます。 | --- # File: mail-checkout --- --- title: "Adapty Mail のチェックアウトを設定する" description: "ウェブペイウォールを構築して決済プロバイダーを接続し、メールキャンペーンにパーソナライズされたウェブチェックアウトを追加しましょう。" --- Adapty Mail が送信するメールには、受信者ごとに固有のチェックアウトリンクが含まれています。リンクをクリックすると、プロファイルで受信者を識別し、オファーを表示して決済を処理するウェブチェックアウトファネルに誘導されます。チェックアウトファネルは Adapty Mail 内の **Web Paywalls** に存在し、付属の**ウェブペイウォールビルダー**で編集します。 ## 要件 \{#requirements\} - サブスクリプションプロダクトが設定済みのウェブ決済プロバイダー。**Generate with AI** は Stripe のみに対応しており、ビルダー内で接続します。**Use your own hosted paywall** は、決済がユーザー側で処理されるため、Stripe、Paddle、PayPal、その他のプロバイダーに対応しています。 ウェブペイウォールビルダー用に別アカウントを用意する必要はありません。Adapty Mail に付属しており、初回ログイン時にワークスペースが自動的にプロビジョニングされ、Adapty の認証情報でエディターにサインインできます。これは、メインの Adapty ダッシュボードのペイウォールページで設定したウェブペイウォールとは独立しています — Adapty Mail のウェブペイウォールは別エンティティとして、Adapty Mail 内で完結して管理されます。 ## チェックアウトファネルを設定する \{#set-up-your-checkout-funnel\} Adapty Mail で **Web Paywalls → Create** に移動します。2 つの方法があります: - **Generate with AI**:Adapty Mail 付属のウェブペイウォールビルダーがファネルを自動生成します。Stripe のみ対応 — Paddle または PayPal を使用する場合は次のオプションを選択してください。 - **Use your own hosted paywall**:すでにホスティングしているペイウォールを接続し、任意の決済プロバイダーを使用できます。 ### Generate with AI \{#generate-with-ai\} 作成ページの上部に **Prerequisites** パネルが表示され、各前提条件(ブランドの準備状況、ビルダーへのログイン、Stripe の接続、プロダクト、最終確認・公開ステップ)を案内するインラインアクションボタンが並んでいます。順番に進めると、各ステップが完了するたびにパネルが更新されます。 前提条件がすべて緑色になったら、**Generate** をクリックして生成ダイアログを開きます。2 つの選択肢があります: - **Environment**:**Production** または **Sandbox** を選択します。Sandbox は Stripe のテストモードプロダクトを使用し、開発・ローカル環境での安全なデフォルトです — アカウントは本番環境から分離されているため、テスト取引がライブデータに影響することはありません。 - **Plans**:最大 **3 つの Stripe プラン**を選択します。各プランはプロダクトと価格の組み合わせです。ペイウォールはこれらをチェックアウト時のオファーとして表示します。3 つ未満を選択した場合、ペイウォールは選択したプランのみを表示します。 **Generate** をクリックしてビルドを実行します。完了したら、ビルダーのエディターを開いて結果を確認し、公開します。その後、**Save** をクリックします。 :::important ペイウォールはチェックアウトトラフィックを処理する前に公開されている必要があります。未公開のペイウォールは、ユーザーがメールのチェックアウトリンクをクリックするとエラーを返します。 ::: ビルダー内の決済プロバイダーの詳細(Stripe アカウント、テストモードとライブモード、プロダクト設定)については、[ウェブペイウォールの設定](web-paywall-configuration)を参照してください。 ### Use your own hosted paywall \{#use-your-own-hosted-paywall\} 1. 作成ページで **Enter URL manually** を選択します。 2. ホスティングしているペイウォールの URL を貼り付けます。クエリパラメーターとして `{email}` と `{external_profile_id}` プレースホルダーを含める必要があります — Adapty Mail が受信者ごとにこれらを埋め込むことで、ページが訪問者を識別できます。例: ``` https://example.com/paywall?email={email}&profile={external_profile_id} ``` 3. 保存します。 この方法は任意の決済プロバイダーで動作します — Adapty Mail はリダイレクトとパラメーター置換のみを担当し、決済とパーソナライズはすべてユーザー側で処理されます。 ## チェックアウトの外観 \{#what-the-checkout-looks-like\} ユーザーがチェックアウトリンクをクリックすると、**メインコンバージョンページ**に誘導されます。決済を試みると、**Payment success** または **Payment failed** のいずれか一方が表示されます。 **メインコンバージョンページ** フルページのセールスプレゼンテーションです。AI が各セクションのコピーと画像を生成します: | セクション | AI が生成する内容 | |---|---| | Headline | 太字のベネフィット訴求型ヘッドライン | | Subheadline | 補足的な価値提案 | | Offer badge | 緊急性バッジ(架空の価格なし — 曖昧なプロモーション表現を使用) | | CTA button | アクション指向のテキスト、2〜5 語 | | Benefits | 3〜6 個の絵文字+テキストのベネフィットカード | | Features | タイトルとサブタイトル付きの 3〜8 個の機能説明 | | Plans | プラン選択タイトルとオファータイマーテキスト | | Social proof | コミュニティ証明テキストと 3〜5 件のリアルなユーザーレビュー | | FAQ | 3〜6 件のよくある質問と回答 | | Guarantee | 返金保証または満足保証テキスト | **Payment success** 次のステップを示す祝福メッセージと AI 生成画像。 **Payment failed** ユーザーに再試行を促すフレンドリーなメッセージ。チェックアウトの状態は保持されます。 ## パーソナライズの仕組み \{#how-personalization-works\} すべてのメールには、受信者の `customer_user_id` とメールアドレスがパラメーターとして埋め込まれた固有のチェックアウト URL が含まれています: ``` https://your-funnel.com/?cid={{customer_user_id}}&email={{email}} ``` Adapty は各メール送信時にこれらの URL を自動的に生成します — ウェブペイウォールビルダーでの設定は不要です。ユーザーがクリックすると、ビルダーがパラメーターを読み取って識別します。購入が完了すると、Adapty はその収益をコンバージョンを促したメールに紐付けます。このデータは[キャンペーン分析](mail-analytics)に表示されます。 ## トラブルシューティング \{#troubleshooting\} | 問題 | 解決策 | |---|---| | チェックアウトリンクが開かない | ペイウォールがウェブペイウォールビルダーで公開されていることを確認する | | チェックアウト時にユーザーが識別されない | メール送信前に正しいユーザー ID で `Adapty.identify()` が呼び出されていることを確認する | | 購入がメールに紐付かない | チェックアウト URL に `cid` パラメーターが含まれているか確認する — パラメーターが欠落している場合はサポートに連絡する | --- # File: mail-email-campaigns --- --- title: "Email campaigns in Adapty Mail" description: "Design multi-email sequences, pick the right tone, and target the right users." --- A campaign in Adapty Mail is a complete multi-email sequence — copy, design, hero images, and delays — generated for your app in one pass. A campaign on its own doesn't send: it saves as a **draft** and starts delivering only once you attach it to a [flow](mail-create-flow), which binds it to a trigger and audience. Use the guides below to create campaigns, pick the right tone, and target the right users. <CustomDocCardList ids={['mail-create-campaign', 'mail-suppression']} /> --- # File: mail-create-campaign --- --- title: "Adapty Mail でキャンペーンを作成する" description: "アプリのストアメタデータから完全なメールシーケンスを生成し、フローに紐付ける前に内容を確認・調整します。" --- Adapty Mail は、アプリのストアメタデータからメールシーケンス全体(コピー、デザイン、ヒーロー画像、件名、送信間隔)を自動生成します。コピーライティングやデザイン作業は不要です。キャンペーンはドラフトとして保存され、[フロー](mail-create-flow)に紐付けた時点ではじめて配信が開始されます。 ## 始める前に \{#before-you-start\} - **保存済みのウェブペイウォール**: すべてのキャンペーンはウェブペイウォールにリンクする必要があります。ウェブペイウォールがないとバックエンドがキャンペーンを拒否します。まだ作成していない場合は、[ウェブペイウォールを作成する](mail-get-started#3-create-a-web-paywall)をご覧ください。 - **ブランドプロファイル**: AI はブランドプロファイルを使って、シーケンス全体のコピー、トーン、ビジュアルを調整します。まだ設定していない場合は、Adapty Mail の **Brand** から設定してください — [Brand](mail-brand)をご参照ください。 ## 1. シーケンスを生成する \{#1-generate-the-sequence\} 1. Adapty Mail で **Campaigns** に移動し、**Create** をクリックします。 2. キャンペーン名を設定します。 3. **Web paywall** ドロップダウンで、メールのリンク先となるウェブペイウォールを選択します。 4. **Generate emails** をクリックします。 5. 生成ダイアログに入力します: - **Tone**: リストから選択します。選択肢はアプリのカテゴリに応じて生成されるため、別のアプリでは異なる選択肢が表示されます。選択したトーンは、すべてのメールの件名・見出し・本文・CTAに反映されます。レイアウトやヒーロー画像には影響しません。 - **Language**: メールの言語を選択します。 - **Custom prompt**(任意): 最大2,000文字の自由記述欄です。プロモーション情報、特別なイベント、オーディエンスの特性、必ず含めたいポイント、プリセットでは表現しきれないトーンの細かい指示などを記入できます。 - **Number of emails**: デフォルトでは、AI がベストプラクティスとアプリのコンテキストに基づいて件数を決定します。手動で設定する場合は **Set number manually** をクリックし、値(**1〜15**、デフォルト **4**)を選択します。 **Generate** をクリックすると、そのキャンペーンのトーンが固定されます。別のトーンを試したい場合は新しいキャンペーンを作成してください — 生成のたびに異なる選択肢が表示されることがあります。 6. **Generate** をクリックします。生成には通常数分かかります。完了できない場合、バックエンドは5分後にタイムアウトします — その際は再試行してください。 ## 2. 確認と調整 \{#2-review-and-refine\} 生成が完了すると、シーケンス全体がプレビューとして表示されます。各メールで確認できる内容は以下のとおりです: - **件名のバリエーション**: メールごとに3つの件名の候補があります。Adapty Mail は配信時にそれらをテストし、最もパフォーマンスの高いものを送り続けます — [A/B テスト](mail-ab-testing)をご参照ください。 - **見出し、本文、CTA**: メインのコンテンツブロックです。 - **ヒーロー画像**: メールのコンテンツとブランドに合わせて生成された画像です。 - **レイアウトと送信間隔**: メールの構成と、前のメールからの送信間隔です。 プレビューのヘッダーには **Theme toggle**(Auto、Light、Dark)があります — プレビューペイン右上のアイコンボタンです。これはプレビューの表示方法のみを制御するもので、生成されたコンテンツはどのモードでも同一です。再生成せずに各カラースキームでの見た目を確認するために使用できます。 以下の操作が可能です: - **個別メールの再生成**: AI が1通のメールのコピーとヒーロー画像を書き直します。位置、タイミング、全体のデザインシステム(色、タイポグラフィ、ダークモード)はそのまま維持され、対象のメールのみが変更されます。 - **HTML の直接編集**: HTML コードエディタを開いて、AI が意図どおりに生成できなかった部分を細かく制御できます。 :::note メールは自動的に適応されます。マルチカラムのデザインは620px未満の画面では1カラムに折り畳まれ、すべてのレイアウトはGmail(ウェブおよびモバイル)、Apple Mail(macOSおよびiOS)、Outlookデスクトップ、Yahoo Mail、Samsung Mail でライトモードとダークモードの両方においてテスト済みです。 ::: ## 3. ドラフトとして保存する \{#3-save-as-a-draft\} **Create** をクリックしてキャンペーンをドラフトとして保存します。この時点ではメールはまだ送信されません — キャンペーンエディタには「公開」や「開始」の操作はありません。 キャンペーンのステータスは、ライブフローへの紐付け状況を示します: - **draft**: どのフローにも紐付けられていない状態。 - **live**: フローに紐付けられており、現在ユーザーをルーティング中。 - **inactive**: 紐付けられていたが、フローの A/B テストが終了した状態。 - **archived**: ダッシュボードから削除された状態。 :::important ドラフトのキャンペーンは単独では送信されません。メールの配信を開始するには、以下のいずれかが必要です: - キャンペーンを[フロー](mail-create-flow)に直接紐付ける、または - [A/B テスト](mail-ab-testing)に組み込み、その A/B テストをフローに紐付ける。 どちらかが完了するまで、キャンペーンは `draft` のままとなり、受信者には届きません。 ::: --- # File: mail-suppression --- --- title: "Adapty Mailの購読解除とサプレッション" description: "Adapty Mailがユーザーへの送信を停止する仕組み — 購読解除、SESバウンス、苦情、ストップ条件について。" --- Adapty Mailは、2つの異なる条件でユーザーへの送信を停止します。 - **サプレッション**: ユーザーがこのプロジェクト内の将来のすべての送信から除外されます(購読解除、バウンス、苦情、拒否、またはスロットル)。 - **ストップ条件**: ユーザーがコンバージョンしたため、現在のシーケンスがキャンセルされます。サプレッションではなく、他のキャンペーンの対象として残ります。 どちらの仕組みもプロジェクト単位で機能します。あるAdaptyプロジェクトでのサプレッションは、別のプロジェクトには影響しません。 ## 購読解除 \{#unsubscribe\} Adapty Mailが送信するすべてのメールのフッターには、購読解除リンクが含まれています。 1. ユーザーがリンクをクリックします。Adapty Mailが確認ページを開きます。 2. ユーザーが確認します。バックエンドがプロファイルに `suppression_reason = 'unsubscribe'` を設定し、残りのシーケンスをキャンセルして、プロジェクト内の将来の送信からそのプロファイルを除外します。 購読解除URLのトークンには `profile_id` と `scheduled_email_id` がエンコードされているため、ログイン不要で利用できます。 :::note Adapty Mailは、`List-Unsubscribe-Post: List-Unsubscribe=One-Click` と合わせて `List-Unsubscribe: <URL>, <mailto:>` ヘッダーも送信します。GmailとYahooはバルク送信者にこれを要求しています(RFC 8058)。このヘッダーに対応しているメールクライアントでは、受信トレイから直接ワンクリックで購読解除できるボタンが表示されます — 確認ページは不要です。 ::: ## 自動サプレッション \{#automatic-suppression\} Adapty MailはSNS経由でAWS SESの配信イベントを監視し、以下のいずれかのイベントが発生した際に即座にユーザーをサプレッションします。 | イベント | 理由コード | 意味 | | --------- | ----------- | ------------------------------------------------------------------------------- | | バウンス | `bounce` | メールアドレスが無効、メールボックスが満杯、またはドメインが存在しない。 | | 苦情 | `complaint` | ユーザーがメールをスパムとしてマークした。 | | 拒否 | `reject` | SESが送信前にメッセージを拒否した。 | | スロットル | `throttle` | 送信レートがドメインの安全制限を超えた。 | どのイベントでも結果は同じです。ユーザーがサプレッションリストに追加され、残りのシーケンスがキャンセルされ、プロジェクト内の将来の送信から除外されます。 :::important Adapty Mailはハードバウンスとソフトバウンスを**区別しません**。メールボックスが満杯のような一時的な状態によるバウンスも含め、あらゆるバウンスが即座にユーザーをサプレッションします。リトライウィンドウはありません。 ::: ## ストップ条件 \{#stop-condition\} ユーザーがシーケンスの途中でコンバージョンした場合、Adapty Mailは残りのメールを `stop_condition` 理由でキャンセルします。コンバージョンとは、サブスクリプションの状態が**Subscribed**に、または買い切り購入の状態が**Purchased**に達することを意味します。 ストップ条件はサプレッションとは異なります。 - **サプレッション**: プロジェクト内の将来のすべての送信からユーザーを除外します。 - **ストップ条件**: 現在のシーケンスのみをキャンセルします。ユーザーは他のキャンペーンの対象として残ります — たとえば、アクティブなサブスクライバーを対象とした更新やウィンバックフローなどです。 ストップ条件によるキャンセルは、キャンペーン分析においてサプレッションと並んで表示されます。 ## サプレッションの管理 \{#managing-suppression\} Adapty Mailには、サプレッションされたユーザーを確認・削除するためのダッシュボードUIはありません。プロファイルのサプレッションを解除する場合(たとえば、テストメールを誤ってスパムとしてマークした場合など)は、Adaptyサポートにお問い合わせください。 ## コンプライアンスのためにAdapty Mailが対応する内容 \{#what-adapty-mail-handles-for-compliance\} Adapty Mailには以下が含まれています。 - **購読解除リンク**: すべてのメールフッターに含まれ、ユーザーが確認した際に即座に処理されます。 - **List-Unsubscribeヘッダー**: 受信トレイからのワンクリック購読解除のためにすべてのメールで送信されます(RFC 8058)。 - **自動サプレッション**: SESのバウンス、苦情、拒否、スロットルイベント時にトリガーされます。 お客様が責任を負う部分: - **物理的な郵送先住所**: CAN-SPAMではメールフッターへの記載が必要です。Adapty Mailは自動挿入しません — キャンペーンデザインで追加してください。 - **明示的なオプトイン同意**: ユーザーのメールアドレスをAdaptyに渡す前に取得してください。[ユーザーメールの収集](mail-collect-emails)を参照してください。 - **GDPRの削除リクエスト**: Adapty Mailには「データ削除」エンドポイントがありません。ユーザーが削除権を行使した場合は、Adaptyサポートと連携してください。 --- # File: mail-flows --- --- title: "Flows in Adapty Mail" description: "How flows route campaigns to the right users at the right moment — triggers, segments, and priority rules." --- <CustomDocCardList ids={['mail-create-flow']} /> A **flow** turns a saved campaign into scheduled deliveries. It binds a trigger event (a user's subscription state) to a segment (which users qualify) and the campaign they receive. Adapty Mail evaluates every flow whenever a matching event fires — no polling, no cron, no manual launch. ## Triggers Adapty Mail ships with five fixed triggers, each with its own flow view under **Flows**: - **Never purchased**: Users who signed up but haven't made a purchase yet. Goal: activation and first conversion. Trial users aren't here — starting a trial counts as an active subscription. - **Renewal cancelled**: Users who turned off auto-renewal but still have an active subscription. Covers both paid subscribers and trial users who cancelled before conversion. Strongest window to save them — they still have access. Split paid and trial audiences via segment filters if messaging needs to differ. - **Billing issue**: Payment failed — declined or expired card, or grace period after a missed renewal. Goal: urgent, helpful recovery, not a sales push. Recover them quickly — they already wanted to pay. - **Expired**: Subscription has lapsed and access is gone. Covers both paid expirations and trials that ran out without converting. Goal: win them back. Segment filters can tailor copy for trial-expired and paid-expired audiences. - **Refunded**: Users who requested a refund after purchase. Goal: understand what went wrong and offer a better-fit option. Tone should stay humble and curious, not a hard resell. Triggers are not configurable — you can't create custom triggers or extend the list. ## The All Users segment Adapty Mail ships with a built-in **All Users** segment that has no filters — every user in the project qualifies. It's most useful in flows as a catch-all row, serving anyone not matched by a more specific segment above it. All Users can't be edited or deleted. See [Segments](mail-segments) for the full rundown. ## Priority Each trigger view holds a list of **segment → campaign** (or segment → A/B test) rows, ordered by priority. When a user hits the trigger, Adapty Mail: 1. Walks the rows top to bottom. 2. Sends the campaign in the first row whose segment matches. 3. Stops. Later rows are not evaluated for that user. Order matters. A broad segment placed above a narrower one swallows every user who would otherwise match the narrower row. To reorder, drag the handle on the left of any row — the backend reassigns priority numbers 1, 2, 3… based on the saved order. :::important The **All Users** row, if present, must be last (lowest priority). The backend rejects saves where All Users isn't in the final slot — it would otherwise swallow every user before more specific segments get a chance to match. ::: ## Content types A row can deliver either a single campaign or an A/B test: - **Campaign**: Sends one campaign to everyone who matches the segment. - **A/B Test**: Wraps two or more campaigns with configurable weights, routes incoming users across them randomly, and tracks per-variant metrics. See [A/B testing](mail-ab-testing). ## Lifecycle Flow rows have no draft state. A row is live the moment you save it — from that point on, users who hit the trigger and match the segment are routed to its campaign. - **Create a row**: Starts delivering immediately on save. - **Edit a row**: The change applies to users who hit the trigger from then on. Users already mid-sequence continue with the previous configuration. - **Delete a row**: New users stop entering the sequence. Users already mid-sequence may continue receiving their scheduled emails — there's no automatic cancellation. A/B test rows follow their own lifecycle (**draft → live → finished**) controlled separately from the row itself. See [A/B testing](mail-ab-testing). --- # File: mail-create-flow --- --- title: "Adapty Mailでフローの行を作成・管理する" description: "フロー内の行を追加、並び替え、編集、削除して、キャンペーンをユーザーにルーティングする方法を説明します。" --- 各[フロー](mail-flows)は、固定されたトリガービュー内に**セグメント → キャンペーン**の行を優先順位付きで並べたリストです。このガイドでは、これらの行の追加・並び替え・編集・削除方法を説明します。トリガー、優先順位、コンテンツタイプの概念については、[フロー](mail-flows)を参照してください。 ## 行を追加する \{#add-a-row\} 1. Adapty Mailで**Flows**に移動し、設定したいトリガーを開きます。 2. **Create**をクリックしてダイアログを開きます。 3. ダイアログで以下を設定します: - **Segment**:セグメントを選択するか、全ユーザーに適用する場合は**All Users**を選択します。 - **Content type**:単一のキャンペーンを送る場合は**Campaign**、複数を比較する場合は**A/B Test**を選択します — [A/Bテスト](mail-ab-testing)を参照してください。 - **Campaign**:送信するキャンペーンを選択します。 4. **Save**をクリックします。 行はすぐに有効になります。トリガーが発火してセグメントに一致したユーザーは、その時点からキャンペーンを受け取り始めます。 ## 行を並び替える \{#reorder-rows\} 行の左側にあるハンドルをドラッグして優先順位を変更します。Adapty Mailは保存された順序に基づいて`priority: 1, 2, 3…`を自動的に割り当てます。 **All Users**の行は必ず最後のスロットに置く必要があります — 別の行の上にドラッグしようとすると、保存時にブロックされます。 ## 行を編集する \{#edit-a-row\} 行の**Change content**をクリックすると、現在の値が入力済みの状態でダイアログが再度開きます。セグメント、コンテンツタイプ、キャンペーンを変更し、**Save**をクリックして適用します。 A/Bテストを使用している行は、テストが**draft**状態の間のみ編集できます。テストが開始されると、終了するまでコンテンツはロックされます。 ## 行を削除する \{#delete-a-row\} 行のアクションメニューを開いて**Delete**をクリックします。確認ダイアログは表示されず、行はすぐに削除されます。 - **キャンペーンの行**:いつでも削除できます。 - **ライブ中のA/Bテストがある行**:削除できません。先に**Finish A/B test**でテストを終了してから、行を削除してください。 :::note 行を削除すると、新しいユーザーがシーケンスに入れなくなります。すでにシーケンスの途中にいるユーザーは、スケジュールされたメールを引き続き受信する場合があります — 自動的なキャンセルは行われません。 ::: --- # File: mail-segments --- --- title: "Adapty Mail のセグメント" description: "プロファイルと購入データに基づいて再利用可能なオーディエンスのスライスを作成し、フローや A/B テストのターゲティングに活用します。" --- **セグメント**は再利用可能なオーディエンスのスライスです。**Segments** で一度定義すれば、フローや A/B テストから参照できます。セグメントはスナップショットではなくフィルターの定義です。フロートリガーが発火した際にオンデマンドで評価されるため、メンバーシップは常に最新のプロファイルデータを反映します。 ## セグメントを作成する \{#create-a-segment\} 1. Adapty Mail で **Segments** に移動し、**+ Create** をクリックします。タイトルが **New Segment** の作成ページが開きます。 2. セグメントの **Name**(必須)とオプションの **Description** を入力します。 3. **Filters** の下で、追加したい[ルール](#available-filter-fields)ごとに **Add filter** をクリックします。各フィルターは **Filter 1**、**Filter 2** のように番号付きの折りたたみカードになります。 4. 各フィルターで、フィールドを選択し、オペレーターを選択して、比較する値を入力します。 5. セグメントを保存します。 :::important フィルターは **AND** で結合されます。セグメントに含まれるには、ユーザーがすべてのフィルターを満たす必要があります。OR ロジックやネストされたグループはサポートされていません。各フィールドはセグメントごとに 1 回しか使用できません。同じフィールドを複数の値で比較したい場合は、ロジックを別のセグメントに分割してください。 ::: ## 利用可能なフィルターフィールド \{#available-filter-fields\} | グループ | フィールド | タイプ | | -------------- | ------------------------- | ------- | | プロファイル | Email | 文字列 | | プロファイル | Age | 整数 | | プロファイル | Country | 文字列 | | プロファイル | External profile ID | 文字列 | | プロファイル | Created at | 日付 | | 購入状態 | Total revenue (USD) | 小数 | | 購入状態 | Subscription state | 列挙型 | | 購入状態 | Subscription purchased at | 日付 | | 購入状態 | Subscription expires at | 日付 | | 購入状態 | One-time purchase state | 列挙型 | | 購入状態 | One-time purchased at | 日付 | **Subscription state の値**: Never purchased、Subscribed、Auto-renew off、Billing issue、Grace period、Expired、Refunded。 **One-time purchase state の値**: Never purchased、Purchased、Refunded。 フィールドタイプごとに利用可能なオペレーター: - **文字列**: equals、not equals、is set、is not set。 - **数値**: equals、not equals、less than、greater than、less than or equal、greater than or equal、between、is set、is not set。 - **日付**: equals、not equals、before、after、on or before、on or after、between、is set、is not set。 ## All Users システムセグメント \{#the-all-users-system-segment\} Adapty Mail には、フィルターなしの組み込み **All Users** セグメントが搭載されており、プロジェクト内のすべてのユーザーが対象となります。編集や削除はできません。フローで使用する場合、キャッチオールの最下行として機能します(優先度ルールについては[フロー](mail-flows)を参照してください)。 ## ライフサイクル \{#lifecycle\} セグメントの状態は、その使用状況から算出されます: - **Draft**: 作成済みだが、フローや A/B テストに紐付けられていない。 - **Live**: アクティブなフローまたは A/B テストに紐付けられている。 - **Inactive**: 紐付けられていたが、A/B テストが終了またはフローの行が削除された。 - **Archived**: ソフト削除され、メインリストから非表示になっている。 Segments ページのツールバーには状態フィルターがあり、これらの状態でリストを絞り込めます。 ## セグメントの編集と削除 \{#edit-and-delete-a-segment\} - **名前と説明**: 常に編集可能。 - **Draft セグメントのフィルター**: 完全に編集可能。 - **Live セグメントのフィルター**: ロック済み。セグメントがアクティブなフロー行または A/B テストから参照されると、フィルターは読み取り専用になります。名前や説明の更新のみ可能です。ターゲティングを変更するには、新しいセグメントを作成してフロー行を入れ替えてください。 - **削除**: セグメントをソフト削除します。Live セグメントは削除できません。先にフローから削除するか(または A/B テストを終了させる)必要があります。 ## 制限事項 \{#limitations\} - **OR ロジック・ネスト非対応**: フィルターは AND のみで結合されます。 - **セグメントごとに 1 フィールド**: 同じフィールドに対して 2 つのフィルター(例: 国の条件を 2 つ)を設定することはできません。 - **サイズプレビューなし**: エディターでは、現在フィルターに一致するユーザー数は表示されません。 - **Live になるとフィルターはロック**: アクティブなセグメントは名前と説明以外は読み取り専用です。 --- # File: mail-ab-testing --- --- title: "Adapty Mail の A/B テスト" description: "フローに A/B テストを追加して、複数のメールキャンペーン全体を比較します。" --- Adapty Mail の A/B テストは、2 つ以上のメールキャンペーン全体を比較します。各バリアントは独立した完全なキャンペーンです。ユーザーが[フロー](mail-flows)内のテストのセグメントに一致すると、Adapty Mail は設定されたウェイトに基づいていずれかのバリアントにルーティングし、バリアントごとの配信数・エンゲージメント・収益を追跡します。 ## バリアントとは \{#what-a-variation-is\} 各バリアントは完全なキャンペーンです。コピー、ヒーロー画像、トーン、シーケンスの長さ、メール間の送信タイミングなど、キャンペーンで変更できるものならすべて異なる設定にできます。A/B テスト自体にこれらの設定項目が直接あるわけではなく、それぞれのキャンペーンを個別に作成してバリアントとして追加します。 ## A/B テストを作成する \{#create-an-ab-test\} 1. まず **Campaigns** でキャンペーンを作成します。各バリアントにそれぞれのキャンペーンが必要です。 2. Adapty Mail で **A/B Tests** に移動し、**Create** をクリックします。 3. 各キャンペーンをバリアントとして追加し、ウェイトを設定します。ウェイトの合計は **100%** になる必要があります。 4. テストを適用するユーザーを制御するためのセグメントを割り当てます。 5. 保存します。 テストは **draft(下書き)** として保存され、この時点ではまだ何も送信されません。公開するにはフローに追加する必要があります。 ## フローから起動する \{#launch-from-a-flow\} A/B テストは A/B Tests ページからは起動できません。起動と終了はどちらもフローの行内で行います。 1. Adapty Mail で **Flows** に移動し、テストを実行したいトリガーを開きます。 2. 新しい行の **Create** をクリックします。ダイアログで **Content type** を **A/B Test** に設定し、保存したテストを選んで **Save** をクリックします。 3. 行上で **Launch A/B test** をクリックします。 テストのステータスが **draft** から **live** に移行し、セグメントに一致する新規ユーザーへのバリアントルーティングが始まります。フローの行について詳しくは[フローを作成する](mail-create-flow)を参照してください。 ## ルーティングの仕組み \{#how-routing-works\} ユーザーがフローのトリガーに到達し、A/B テストのセグメントに一致すると、Adapty Mail は**加重ランダム**選択を使ってバリアントを決定します。各バリアントのウェイトが抽選のシェアを決めます。ルーティングはユーザー単位で決定論的ではありません。 ## 結果を確認する \{#read-results\} A/B Tests ページでは、各バリアントの生の集計数値と導出されたレートが表示されます: - **Delivery**(配信): Sends(送信数)、Deliveries(到達数)、Bounces(バウンス数) - **Engagement**(エンゲージメント): Opens(開封数)、Clicks(クリック数)、Unsubs(配信停止数) - **Revenue**(収益): Purchases(購入数)、Revenue(収益) 各指標の計測方法や収益のアトリビューションについては、[キャンペーン分析](mail-analytics)を参照してください。 ## テストを終了する \{#finish-the-test\} 起動と同様に、終了も A/B Tests ページではなくフローの行から行います。 1. テストが実行中のフローの行を開きます。 2. **Finish A/B test** をクリックします。 3. **Finish A/B test** ダイアログで、**Replace with campaign** ドロップダウンから勝者キャンペーンを選択します。空のままにするとセグメントをフローから完全に削除します。 4. 確認します。 :::note いずれかのバリアント(勝者・敗者問わず)のシーケンス途中にいるユーザーは、引き続きスケジュールされたメールを受け取ります。勝者に切り替わることはありません。 ::: ## ライフサイクル \{#lifecycle\} A/B テストは 4 つのステータスを経由します: - **Draft**(下書き): 作成済み、まだライブのフロー行に追加されていない。 - **Live**(公開中): 追加・起動済みで、入力ユーザーをルーティング中。 - **Finished**(終了): **Finish A/B test** によって停止済み。 - **Archived**(アーカイブ): リストからソフト削除済み。 --- # File: mail-analytics --- --- title: "Adapty Mailのアナリティクス" description: "キャンペーン、セグメント、A/Bバリアント、メッセージ、トリガーごとにキャンペーンパフォーマンスを分析し、配信・エンゲージメント・収益を一覧で確認できます。" --- **Analytics** ページでは、キャンペーン・セグメント・A/B バリアント・メッセージ・トリガーの5つの軸でキャンペーンのパフォーマンスを確認できます。配信指標と各メールに紐づく収益を並べて表示するので、バリアントの比較、優秀なセグメントの特定、収益が集中している箇所の把握が簡単に行えます。 ページ上部にチャート、下部にブレークダウンテーブルが表示されます。任意の行をクリックすると、その個別エンティティの詳細に移動します。 ## 期間を選択する \{#pick-a-time-range\} ページ上部のツールバーで、表示期間とバケット単位を設定します。 - **Date range**:プリセット(直近 7 / 14 / 30 / 90 日、今月、先月、直近 12 ヶ月、年初来)または **Custom range** ピッカー。デフォルトは直近 30 日間です。 - **Granularity**:**Daily**(日次)、**Weekly**(週次)、**Monthly**(月次)のバケット。期間が広がると自動的に粗くなります — 92 日を超えると **Daily** が **Weekly** に切り替わり、366 日を超えると両方が **Monthly** に切り替わります。 - **Chart style**:**Line**、**Area**、または **Bar**。 「range too wide」の警告が表示された場合は、期間を短くするか、粒度を粗くするか、フィルターを適用してください。 ## グループ化・ブレークダウン・フィルター \{#group-break-down-filter\} ツールバーの下にある3つのコントロールで、チャートとテーブルの表示内容を調整します。 - **Group by**:データセットを行に分割する軸。**Campaigns**、**Segments**、**A/B variants**、**Triggers** が選択できます。**No grouping** を選択すると、すべてのデータが1つの集計 **All** 行にまとまります。 - **Breakdown**:各行をサブ行に分割するための第2の軸。**Group by** と **Breakdown** を両方設定すると、テーブルの各行を展開してサブグループを確認できます。**Messages** を含む任意の軸を指定できますが、**Group by** に設定済みの軸は選択できません。 - **Add filter**:特定のキャンペーン、セグメント、A/B バリアント、またはトリガーにデータを絞り込みます。フィルターはチャートとテーブルの両方に適用されます。 :::note **Messages** はブレークダウンとして利用できますが、トップレベルの **Group by** やフィルターとしては使用できません。個別のメッセージを分析するには、**Messages** ブレークダウンを設定して **Campaigns** でグループ化し、キャンペーン行を展開するか、ドリルダウンからメッセージを開いてください。 ::: ## チャートを読む \{#read-the-chart\} チャートには、選択した指標が指定期間にわたって描画されます。 - **Metric category**:**Email actions**(Sent、Delivered、Opened、Clicked、Bounced、Unsubscribed、Converted)と **Revenue** を切り替えられます。 - **Metric pills**:プロットする指標を選択します。集計モード(グループ化なし)では、複数の指標を同じチャートに表示できます。グループ化が有効な場合、チャートには1つの指標のみが表示され、グループごとに1本のラインが描かれるため、グループを視覚的に区別しやすくなります。 - **Legend**:グループ化が有効な場合、右側の凡例にすべてのグループが一覧表示され、各系列の表示/非表示を切り替えられます。 指標テーブルの表示チェックボックスでも、チャートに表示される行を制御できます。 ## 指標テーブルを読む \{#read-the-metrics-table\} チャートの下に、グループごとに1行ずつ表示される指標テーブルがあります。テーブル上部のサマリー行には、全行の集計値が表示されます。 - **ソート可能な列**:列ヘッダーをクリックすると、Name、Sent、Delivered、Delivery rate、Opened、Open rate、Clicked、Click rate、Converted、Revenue、Bounced、Unsubscribed でソートできます。 - **表示チェックボックス**:その行をチャートに表示するかどうかを切り替えます。 - **行の展開**:**Breakdown** が設定されている場合、各行の左側にあるシェブロンをクリックするとサブグループが表示されます。 - **ドリルダウンを開く**:行の名前をクリックすると、そのエンティティの詳細ビューが開きます。 ドリルダウンには以下が表示されます。 - メインページと同じチャートおよび指標セレクター(1つのエンティティに絞り込まれた状態)。 - 下部に8つのサマリーカード:**Sent**、**Delivered**(配信率付き)、**Opened**(開封率付き)、**Clicked**(クリック率付き)、**Bounced**、**Unsubscribed**、**Converted**、**Revenue**。 期間と粒度はメインページの設定が引き継がれます。パンくずリストの **Back** をクリックして戻ることができます。 ## 計測される内容 \{#whats-tracked\} Analytics ページ、ドリルダウン、後述のインラインビューのいずれも、各行に同一の生カウントが表示されます。 - **Sent**:SES に送信されたメール数。 - **Delivered**:SES で確認されたインボックスへの配信数。 - **Bounced**:SES が報告したバウンス数。ハードバウンスとソフトバウンスは区別されず、どちらも 1 件の **Bounced** としてカウントされます。 - **Opened**:ピクセルの読み込み数。Apple Mail プライバシー保護は iOS 15 以降で画像をプリフェッチするため、この数値が水増しされます — 強いシグナルとしてはクリックや収益を参照してください。 - **Clicked**:メール本文内のリンクのクリック数。 - **Unsubscribed**:フッターリンクまたは `List-Unsubscribe` ヘッダーからの購読解除数。 - **Converted**:指定期間内に帰属購入があったグループ内のユニークプロファイル数。コンバージョンは購入日でバケット化されます — 3月のクリックに続く4月の購入は4月にカウントされます。1つのプロファイルが複数回購入しても1回としてカウントされます。 - **Revenue**:サブスクリプション開始、更新、買い切り購入に帰属する収益の合計(USD)。 ## 派生レート \{#derived-rates\} 各レートは上記の生カウントから算出されます。 | レート | 計算式 | | ------------- | -------------------- | | Delivery rate | Delivered / Sent | | Open rate | Opened / Delivered | | Click rate | Clicked / Delivered | ドリルダウンでも、サマリーカードの横に同じ3つのレートが表示されます。 ## 収益アトリビューション \{#revenue-attribution\} 収益は追跡リンクの**ラストクリック**で帰属付けされます。 1. 受信者がメール内のリンクをクリックすると、Adapty Mail は短期ストアにそのプロファイルに対する `scheduled_email_id` を保存します。 2. その後、既存のアトリビューションがない購入イベントが到着した場合、Adapty Mail はトランザクションに保存済みの `scheduled_email_id` をバックフィルします — ただし購入タイムスタンプがクリック後であることが条件です。 3. 追跡クリックが先行しない購入はアトリビューションなしのままになります。 追跡されるパラメーターは `scheduled_email_id` です。チェックアウト URL には `{email}` および `{external_profile_id}` プレースホルダーを介して受信者の識別情報も含まれており、ウェブペイウォールでフローをパーソナライズできます — これはアトリビューションとは別の仕組みです。詳しくは[チェックアウトの設定](mail-checkout)を参照してください。 ## フローと A/B テストのインラインアナリティクス \{#inline-analytics-in-flows-and-ab-tests\} 同じ指標がインラインでも表示されます。 - **Flows ページ**:トリガービューの各セグメント行に、配信・エンゲージメント・収益のカウントが表示されます。 - **A/B Tests ページ**:バリエーションが同じ指標セットで並んで表示されるため、バリアントの直接比較に便利です。 キャンペーン間の比較や特定エンティティへのドリルダウンには Analytics ページを使用し、特定のフロー行や A/B テストで作業している場合はインラインビューを使用してください。上記の指標の定義、派生レート、アトリビューションルールは3つのビューすべてで同じように適用されます。 ## 制限事項 \{#limitations\} - **ソフトバウンスとハードバウンスの区別なし**:一時的か恒久的かに関わらず、すべてのバウンスが1つの **Bounced** カウントに集約されます。 - **リアルタイムではなく結果整合性**:カウントはイベントテーブルから集計されます。最新のイベントは通常数分以内に反映されますが、ストリーミングの保証はありません。 - **期間サイズの上限あり**:非常に広い期間と細かい粒度を組み合わせると、チャートのセル上限を超える場合があります。ページに「range too wide」の警告が表示されたら、期間を短くするか、粒度を粗くするか、フィルターを適用してください。 --- # File: configuration --- --- title: "サードパーティ連携の設定" description: "Adaptyの設定を最適化してサブスクリプション管理を改善する方法を学びましょう。" --- Adaptyの連携機能を使えば、サブスクリプションイベントや購入データをお好みのプラットフォームやワークフローにスムーズに送信できます。ユーザー行動の分析、カスタマーエンゲージメント戦略の構築、マーケティングチーム向けのプロダクトアナリティクスの強化など、Adaptyはアプリ内課金イベントを選択した連携先に簡単に転送します。 Adaptyはトライアル、コンバージョン、更新、解約といったアプリ内課金およびサブスクリプションの[イベント](events)を自動的に追跡し、設定した連携先に送信します。これにより、ユーザーの現在のステージに応じたアプローチや、アプリ内の収益関連アクティビティの分析が可能になります。 ## 連携の設定 \{#integration-settings\} <img src="/assets/shared/img/20bf659-CleanShot_2023-08-22_at_13.26.562x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 連携には、この連携を通じて送信されるすべてのイベントに影響する以下の設定オプションがあります: | 設定 | 説明 | |:--------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Reporting Proceeds** | 収益値の表示方法を選択します。App StoreおよびPlay Storeの手数料を差し引いた後の金額、または差し引く前の金額(グロス)を選択できます。「Send sales as proceeds」チェックボックスをオンにすると、App Store / Play Storeの手数料を差し引いた後のプロシーズとして売上が表示されます。 | | **Send Trial Price** | チェックすると、Trial Startedイベントのサブスクリプション価格をAdaptyが送信します。 | | **Exclude Historical Events** | ユーザーがAdapty SDKを含むアプリをインストールする前に発生したイベントを除外するオプションです。イベントの重複を防ぎ、正確なレポートを確保します。たとえば、ユーザーが1月10日に月額サブスクリプションを開始し、3月6日にAdapty SDKを含むアプリに更新した場合、Adaptyは3月6日より前のイベントを省略し、それ以降のイベントのみを保持します。 | | **Report User's Currency** | 売上をユーザーの通貨で報告するか、米ドルで報告するかを選択します。 | | **Send User Attributes** | 言語設定などのユーザー固有の属性を送信したい場合で、かつOneSignalプランが10タグ以上をサポートしている場合に選択します。このオプションを有効にすると、デフォルトの10タグを超える追加情報を含めることができます。タグの上限を超えるとエラーが発生する場合があります。 | | **Send Attributions** | アトリビューション情報(例:AppsFlyerのアトリビューション)を送信して関連する詳細を受け取るには、このオプションを有効にします。 | | **Send Play Store purchase token** | 必要に応じて購入を再検証するためのPlay Storeトークンを受け取るには、このオプションを有効にします。イベントに`play_store_purchase_token`パラメータが追加されます。 | | **Delay events with future datetime** | **AppsFlyerおよびカスタムWebhookのみ**: 有効にすると、更新イベントとトライアルコンバージョンイベントが実際に発生した日付に送信されます。無効(デフォルト)の場合、これらのイベントは検出された時点で即座に送信されます(日付が未来であっても同様です)。 | | **Data residency** | **MixpanelおよびAmplitudeのみ**: イベントが処理・保存される場所を決定するデータレジデンシーを選択します。 | ## イベントの設定 \{#configure-the-events\} 認証情報の下に、Adaptyから選択した連携プラットフォームに送信できる3つのグループのイベントがあります。必要なものをオンにしてください。 イベント名のカスタマイズは一部の連携で利用可能ですが、他の連携ではイベント名が固定されており変更できません。また、[Airbridge](airbridge#configure-events-and-tags)などの一部の連携では、1つのAdaptyイベントに複数のイベント名を関連付けることもできます。Adaptyが提供するイベントの全リストは[こちら](events)でご確認いただけます。 <img src="/assets/shared/img/c79f5cd-screencapture-app-adapty-io-integrations-pushwoosh-2023-08-22-13_31_07.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Adaptyのデフォルトのイベント名を使用することをお勧めしますが、特定の要件に合わせてイベント名を自由にカスタマイズすることも可能です。 --- # File: events --- --- title: "サードパーティ連携に送信するイベント" description: "Adaptyのアナリティクスツールを使って、主要なサブスクリプションイベントを追跡しましょう。" --- Apple と Google は、[App Store Server Notifications](enable-app-store-server-notifications) と [Real-time Developer Notifications (RTDN)](enable-real-time-developer-notifications-rtdn) を通じてサブスクリプションイベントをサーバーに直接送信します。そのため、モバイルアプリがリアルタイムにアナリティクスシステムへイベントを送信することは難しい場合があります。たとえば、ユーザーがサブスクリプションを開始してもアプリを再度開かなかった場合、サーバーがなければ開発者はサブスクリプションのステータス更新を受け取れません。 Adapty はこのギャップを埋めるため、サブスクリプションデータを収集して人間が読みやすいイベントに変換します。これらの連携イベントは JSON 形式で送信されます。すべてのイベントは同じ構造を持ちますが、イベントの種類・ストア・設定内容によってフィールドが異なります。各イベントに含まれる正確なフィールドは、それぞれの連携ページで確認できます。 イベントが正常に処理されたかどうか、あるいは問題が発生したかどうかを判断する方法については、[イベントステータス](event-statuses)ページをご覧ください。 ## イベントの種類 \{#event-types\} ほとんどのイベントは、有効化されているすべての連携に作成・送信されます。ただし、**Access level updated** イベントは、[webhook 連携](webhook)が設定されていてこのイベントが有効になっている場合にのみ発火します。このイベントは [Event Feed](https://app.adapty.io/event-feed) に表示され、webhook にも送信されますが、他の連携には共有されません。 webhook 連携が設定されていない場合、またはこのイベントタイプが有効になっていない場合、**Access level updated** イベントは作成されず、[Event Feed](https://app.adapty.io/event-feed) にも表示されません。 | イベント名 | 説明 | |:-----------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | subscription_started | トライアル期間なしで有料サブスクリプションを開始したとき(つまり即座に課金されたとき)にトリガーされます。 | | subscription_renewed | サブスクリプションが更新され、ユーザーに課金されたときに発生します。このイベントはトライアルあり・なしを問わず、2回目以降の請求から記録されます。 | | subscription_renewal_cancelled | ユーザーがサブスクリプションの自動更新をオフにしました。有料サブスクリプション期間が終了するまでプレミアム機能へのアクセスは継続されます。 | | subscription_renewal_reactivated | ユーザーがサブスクリプションの自動更新を再度有効にしたときにトリガーされます。 | | subscription_expired | キャンセルされたサブスクリプションが完全に終了したときにトリガーされます。たとえば、12月12日にサブスクリプションをキャンセルしても12月31日まで有効な場合、イベントは12月31日に記録されます。 | | subscription_paused | ユーザーが[サブスクリプションの一時停止](https://developer.android.com/google/play/billing/lifecycle/subscriptions#pause)を有効にしたときに発生します(Android のみ)。 | | subscription_deferred | サブスクリプションの購入が[延期](https://adapty.io/glossary/subscription-purchase-deferral/)され、ユーザーが支払いを先送りしながらプレミアム機能へのアクセスを維持できる場合にトリガーされます。この機能は Google Play Developer API を通じて利用可能で、無料トライアルや支払いが困難なユーザーへの対応に活用できます。 | | non_subscription_purchase | 永続アクセスやゲーム内コインなどの消耗型アイテムといった、サブスクリプション以外のすべての購入。 | | trial_started | ユーザーがトライアルサブスクリプションを開始したときにトリガーされます。 | | trial_converted | トライアルが終了してユーザーに課金されたとき(初回購入)に発生します。たとえば、1月14日までトライアル期間があるにもかかわらず1月7日に課金された場合、イベントは1月7日に記録されます。 | | trial_renewal_cancelled | トライアル期間中にユーザーがサブスクリプションの自動更新をオフにしました。トライアルが終了するまでプレミアム機能へのアクセスは継続されますが、課金やサブスクリプションの開始は行われません。 | | trial_renewal_reactivated | トライアル期間中にユーザーがサブスクリプションの自動更新を再度有効にしたときに発生します。 | | trial_expired | サブスクリプションに転換されずにトライアルが終了したときにトリガーされます。 | | entered_grace_period | 支払い試行が失敗し、ユーザーがグレース期間(有効な場合)に入ったときに発生します。この期間中もユーザーはプレミアム機能にアクセスできます。 | | billing_issue_detected | 課金試行中に請求エラーが発生したとき(例:カード残高不足)にトリガーされます。 | | subscription_refunded | サブスクリプションが返金されたとき(例:Apple サポートによる返金)にトリガーされます。 | | non_subscription_purchase_refunded | サブスクリプション以外の購入が返金されたときにトリガーされます。 | | access_level_updated | ユーザーのアクセスレベルが更新されたときに発生します。 | 上記のイベントは、購入に関するユーザーの状態を完全にカバーしています。いくつかの例を見てみましょう。 ### 例 1 \{#example-1\} _ユーザーが4月1日に7日間のトライアル付き月次サブスクリプションを開始し、4日目に解約した。_ この場合、以下のイベントが送信されます: 1. `trial_started`:4月1日 2. `trial_renewal_cancelled`:4月4日 3. `trial_expired`:4月7日 ### 例 2 \{#example-2\} _ユーザーが4月1日に7日間のトライアル付き月次サブスクリプションを開始し、10日目に解約した。_ この場合、以下のイベントが送信されます: 1. `trial_started`:4月1日 2. `trial_converted`:4月7日 3. `subscription_renewal_cancelled`:4月10日 4. `subscription_expired`:5月1日 各シナリオでどのイベントが発火するかの詳細については、[イベントフロー](event-flows)をご確認ください。 --- # File: event-flows --- --- title: "イベントフロー" description: "Adaptyのサブスクリプションイベントフローの詳細スキームを確認しましょう。サブスクリプションイベントの生成方法やインテグレーションへの送信方法を学び、顧客ジャーニーの重要な瞬間を追跡するのに役立てましょう。" --- Adaptyでは、アプリ内での顧客のジャーニーを通じてさまざまなサブスクリプションイベントを受け取ります。これらのサブスクリプションフローは、ユーザーがサブスクリプションを開始・キャンセル・再有効化する際にAdaptyが生成するイベントを理解するための一般的なシナリオを示しています。 Appleはサブスクリプションの実際の開始・更新時間より数時間前に支払い処理を行います。以下のフローでは、図をわかりやすくするために、サブスクリプションの開始・更新と課金が同時に発生するように示しています。 また、同じアクションに関連するイベントは同時に発生するため、図に示した順序とは異なる順序で **Event Feed** に表示される場合があります。 ## サブスクリプションのライフサイクル \{#subscription-lifecycle\} ### 初回購入フロー \{#initial-purchase-flow\} このフローは、顧客がトライアルなしで初めてサブスクリプションを購入したときに発生します。この場合、以下のイベントが生成されます: - **Subscription started** - **Access level updated**:ユーザーへのアクセス付与 サブスクリプションの更新日が来ると、サブスクリプションが更新されます。この場合、以下のイベントが生成されます: - **Subscription renewal**:サブスクリプションの新しい期間の開始 - **Access level updated**:サブスクリプションの有効期限を更新し、さらに1期間のアクセスを延長 支払いが成功しない場合やユーザーが更新をキャンセルした場合については、それぞれ [請求問題の結果フロー](event-flows#billing-issue-outcome-flow) と [サブスクリプションキャンセルフロー](event-flows#subscription-cancellation-flow) をご参照ください。 <img src="/assets/shared/img_webhook_flows/Initial_Purchase_Flow.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### サブスクリプションキャンセルフロー \{#subscription-cancellation-flow\} ユーザーがサブスクリプションをキャンセルすると、以下のイベントが生成されます: - **Subscription renewal canceled**:現在の期間が終了するまでサブスクリプションが有効であり、その後ユーザーはアクセスを失うことを示す - **Access level updated**:アクセスの自動更新を無効化 サブスクリプションが終了すると、**Subscription expired (churned)** イベントがトリガーされ、サブスクリプションの終了を示します。 <img src="/assets/shared/img_webhook_flows/Subscription_Cancellation_Flow.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 返金が承認された場合、**Subscription expired (churned)** の代わりに以下のイベントが生成されます: - **Subscription refunded**:サブスクリプションを終了し、返金の詳細を提供 <img src="/assets/shared/img_webhook_flows/Subscription_Cancellation_Flow_with_a_Refund.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Stripeでは、残りの期間をスキップしてサブスクリプションを即時キャンセルすることができます。この場合、すべてのイベントが同時に生成されます: - **Subscription renewal cancelled** - **Subscription expired (churned)** - **Access Level updated**:ユーザーのアクセスを削除 返金が承認された場合、承認時に **Subscription refunded** イベントも発生します。 <img src="/assets/shared/img_webhook_flows/Subscription_Immediate_Cancellation_Flow.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### サブスクリプション再有効化フロー \{#subscription-reactivation-flow\} ユーザーがサブスクリプションをキャンセルして期限切れになり、その後同じサブスクリプションを再購入した場合、**Subscription renewed** イベントが生成されます。アクセスが途切れた場合でも、Adaptyは `vendor_original_transaction_id` によってリンクされた単一のトランザクションチェーンとして扱います。そのため、再購入は更新とみなされます。 **Access level updated** イベントは2回生成されます: - サブスクリプション終了時にユーザーのアクセスを取り消すとき - サブスクリプション再購入時にアクセスを付与するとき <img src="/assets/shared/img_webhook_flows/Subscription_Rejoin_Flow.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### サブスクリプション一時停止フロー(Androidのみ) \{#subscription-pause-flow-android-only\} このフローは、ユーザーがAndroidでサブスクリプションを一時停止し、後で再開する場合に適用されます。 サブスクリプションの一時停止には遅延効果があります。ユーザーが更新前にサブスクリプションを一時停止した場合、サブスクリプションは有効なままで、ユーザーは請求期間の残り期間中、有料アクセスを維持します。 1. ユーザーがサブスクリプションを一時停止すると、**Subscription paused (Android only)** イベントがトリガーされます。 2. サブスクリプション期間終了時に、Adaptyは **Access level updated** イベントをトリガーしてユーザーのアクセスを取り消します。 3. ユーザーがサブスクリプションを再開すると、以下のイベントがトリガーされます: - **Subscription renewed** - **Access level updated**:ユーザーのアクセスを復元 これらのサブスクリプションは、同じ **vendor_original_transaction_id** でリンクされた同一のトランザクションチェーンに属します。 <img src="/assets/shared/img_webhook_flows/Subscription_Paused_Flow.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## トライアルフロー \{#trial-flows\} アプリでトライアルを使用している場合、トライアル関連の追加イベントが発生します。 ### 変換成功のトライアルフロー \{#trial-with-successful-conversion-flow\} 最も一般的なフローは、ユーザーがトライアルを開始し、クレジットカードを登録して、トライアル期間終了時に通常のサブスクリプションへ正常に変換される場合です。この場合、トライアル開始時に以下のイベントが生成されます: - **Trial started**:トライアル開始を示す - **Access level updated**:アクセスを付与 通常のサブスクリプションが開始されると **Trial converted** イベントが生成されます。 <img src="/assets/shared/img_webhook_flows/Trial_Flow_with_Successful_Conversion.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### 変換失敗のトライアルフロー \{#trial-without-successful-conversion-flow\} ユーザーがトライアルをサブスクリプションに変換する前にキャンセルした場合、キャンセル時に以下のイベントが生成されます: - **Trial renewal cancelled**:トライアルからサブスクリプションへの自動変換を無効化 - **Access level updated**:アクセス更新を無効化 ユーザーはトライアル終了まで引き続きアクセスでき、トライアルの終了を示す **Trial expired** イベントが生成されます。 <img src="/assets/shared/img_webhook_flows/Trial_Flow_without_Successful_Conversion.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### 期限切れトライアル後のサブスクリプション再有効化フロー \{#subscription-reactivation-after-expired-trial-flow\} トライアルが(請求の問題またはキャンセルにより)期限切れになり、ユーザーが後でサブスクリプションを購入した場合、以下のイベントが生成されます: - **Access level updated**:ユーザーへのアクセス付与 - **Trial converted** トライアルとサブスクリプションの間に空白期間があっても、Adaptyは `vendor_original_transaction_id` を使って両者をリンクします。この変換は、ゼロ価格のトライアルから始まる継続的なトランザクションチェーンの一部として扱われます。そのため、**Subscription started** ではなく **Trial converted** イベントが生成されます。 <img src="/assets/shared/img_webhook_flows/Subscription_Reactivation_Flow_after_Expired_Trial.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## プロダクトの変更 \{#product-changes\} このセクションでは、アップグレード、ダウングレード、別グループのプロダクトの購入など、アクティブなサブスクリプションに加えられた変更について説明します。 ### 即時プロダクト変更フロー \{#immediate-product-change-flow\} ユーザーがプロダクトを変更した後、サブスクリプション終了前にシステムで即時変更が適用される場合があります(主にアップグレードまたはプロダクトの置き換えの場合)。この場合、プロダクト変更時に以下のイベントが生成されます: - アクセスレベルが変更され、2つの **Access level updated** イベントが生成されます: 1. 最初のプロダクトへのアクセスを削除 2. 2番目のプロダクトへのアクセスを付与 - 古いサブスクリプションが終了し、返金が行われます(**Subscription refunded** イベントが `cancellation_reason` = `upgraded` で生成されます)。**Subscription expired (churned)** イベントは生成されず、**Subscription refunded** イベントに置き換えられます。 - 新しいサブスクリプションが開始されます(新しいプロダクトの **Subscription started** イベントが生成されます)。 <img src="/assets/shared/img_webhook_flows/Immediate_Product_Change_Flow_Upgrade.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ユーザーがサブスクリプションをダウングレードした場合、最初のサブスクリプションは有料期間の終了まで継続し、終了時に新しい下位プランのサブスクリプションに置き換えられます。この場合、アクセスの自動更新を無効化する **Access level updated** イベントのみが即時に生成されます。その他のイベントはサブスクリプションが実際に置き換えられる時点で生成されます: - 別の **Access level updated** イベントが生成され、2番目のプロダクトへのアクセスを付与 - **Subscription expired (churned)** イベントが生成され、最初のプロダクトのサブスクリプションを終了 - **Subscription started** イベントが生成され、新しいプロダクトの新しいサブスクリプションを開始 <img src="/assets/shared/img_webhook_flows/Delayed_Product_Change_Downgrade.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### 遅延プロダクト変更フロー \{#delayed-product-change-flow\} サブスクリプション更新時にプロダクトを変更するバリアントもあります。このバリアントは前のケースと非常に似ており、古いプロダクトのアクセス自動更新を無効化する **Access level updated** イベントが1つ即時に生成されます。その他のイベントはユーザーがサブスクリプションを変更してシステムで反映される時点で生成されます: - 別の **Access level updated** イベントが生成され、2番目のプロダクトへのアクセスを付与 - **Subscription expired (churned)** イベントが生成され、最初のプロダクトのサブスクリプションを終了 - **Subscription started** イベントが生成され、新しいプロダクトの新しいサブスクリプションを開始 <img src="/assets/shared/img_webhook_flows/Product_Change_on_Renewal_Flow.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## 請求問題の結果フロー \{#billing-issue-outcome-flow\} トライアルの変換またはサブスクリプションの更新が請求問題により失敗した場合、次の動作はグレース期間が有効かどうかによって異なります。 グレース期間が設定されている場合、支払いが成功すればトライアルが変換されるかサブスクリプションが更新されます。失敗した場合、アプリストアはユーザーへの課金を繰り返し試み、それでも失敗するとアプリストアがトライアルまたはサブスクリプションを終了します。 したがって、請求問題が発生した時点でAdaptyに以下のイベントが生成されます: - **Billing issue detected** - **Entered grace period**(グレース期間が有効な場合) - **Access level updated**:グレース期間終了までのアクセスを提供 後で支払いが成功した場合、Adaptyは **Trial converted** または **Subscription renewed** イベントを記録し、ユーザーはアクセスを失いません。 最終的に支払いが失敗してアプリストアがサブスクリプションをキャンセルした場合、Adaptyは以下のイベントを生成します: - **Trial expired** または **Subscription expired (churned)**(`cancellation_reason: billing_error` 付き) - **Access level updated**:ユーザーのアクセスを取り消す <img src="/assets/shared/img_webhook_flows/Billing_Issue_Outcome_Flow_with_Grace_Period.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> グレース期間なしの場合、請求再試行期間(アプリストアがユーザーへの課金を繰り返し試みる期間)が即時に開始されます。 グレース期間終了まで支払いが成功しない場合のフローは同じで、アプリストアがサブスクリプションを自動終了したときに同じイベントが生成されます: - **Trial expired** または **Subscription expired (churned)**(`cancellation_reason` が `billing_error` のもの) - **Access level updated**:ユーザーのアクセスを取り消す <img src="/assets/shared/img_webhook_flows/Billing_Issue_Outcome_Flow_without_Grace_Period.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## ユーザーアカウント間での購入共有フロー \{#sharing-purchases-across-user-accounts-flows\} <InlineTooltip tooltip="カスタマーユーザーID">[iOS](identifying-users#set-customer-user-id-on-configuration)、[Android](android-identifying-users#setting-customer-user-id-on-configuration)、[React Native](react-native-identifying-users#setting-customer-user-id-on-configuration)、[Flutter](flutter-identifying-users#setting-customer-user-id-on-configuration)、[Unity](unity-identifying-users#setting-customer-user-id-on-configuration)</InlineTooltip> が、別の <InlineTooltip tooltip="カスタマーユーザーID">[iOS](identifying-users#set-customer-user-id-on-configuration)、[Android](android-identifying-users#setting-customer-user-id-on-configuration)、[React Native](react-native-identifying-users#setting-customer-user-id-on-configuration)、[Flutter](flutter-identifying-users#setting-customer-user-id-on-configuration)、[Unity](unity-identifying-users#setting-customer-user-id-on-configuration)</InlineTooltip> にすでに紐付いているサブスクリプションを復元または延長しようとした場合、Adaptyの **Sharing paid access between user accounts** 設定でアクセス管理方法が制御されます。選択したオプションによってフローが異なります。 :::note Apple Family Sharingのトランザクション(`in_app_ownership_type=FAMILY_SHARED`)の場合、**Access level updated** イベントのみが発火し、以下のプロダクト別サブスクリプションイベントは発生しません。完全なイベントマトリクスについては [Apple Family Sharing](apple-family-sharing) をご参照ください。 ::: :::note ユーザーが **Restore Purchases** をタップしても、同じプロファイルですでにアクセスがある場合、リストアは何も行わず、Webhookイベントは発生しません。このセクションのイベントは、プロファイル間でアクセスが実際に移行する場合にのみ発生します。 ::: 2番目のプロファイルが既存のサブスクリプションを要求したときにどのイベントが発生するかを一目で確認するには、以下のマトリクスを参照してください。その後のセクションでは、各フローの完全なJSONペイロードを示します。 | イベント | 有効(デフォルト) | 新しいユーザーにアクセスを移行 | 無効 | | --- | --- | --- | --- | | 新しいプロファイル:**Access level updated**(`is_active=true`) | 発生する | 発生する | 発生しない | | 古いプロファイル:**Access level updated**(`is_active=false`) | 発生しない — 両方のプロファイルがアクセスを保持 | 新しい識別済みデバイスがトランザクションを伝播したときに発生 | 発生しない — 元のプロファイルがアクセスを保持 | | 新しいイベントの `profiles_sharing_access_level` フィールド | アクセスレベルを共有している他のプロファイルを一覧表示 | `null` | 該当なし — イベントは発生しない | 移行されたサブスクリプションの更新、返金、期限切れは、現在アクセスレベルを保持しているプロファイルで `subscription_renewed`、`subscription_refunded`、`subscription_expired` イベントを引き続き発生させます。移行イベント自体は `subscription_started` イベントを発生させません。新しいトランザクションは記録されず、アトリビューションのみが変更されるためです。 モード別の詳細については、[実用的なリファレンス](sharing-paid-access-between-user-accounts#practical-reference)をご参照ください。 ### 新しいユーザーへのアクセス移行フロー \{#transfer-access-to-new-user-flow\} 推奨オプションは、新しいユーザーにアクセスレベルを移行することです。これにより、一貫したアナリティクスのために元のユーザーのトランザクション履歴が保持されます。生成される **Access level updated** イベントは2つのみです: 1. 最初のユーザーのアクセスを削除 2. 2番目のユーザーにアクセスを付与 <img src="/assets/shared/img_webhook_flows/Transfer_Access_to_New_User_Flow.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> このシナリオで生成されるイベントにおける、アクセスレベルの割り当てと移行に関連するフィールドの内訳は以下の通りです: - **ユーザーA:Access level updated(ユーザーAがアプリでサブスクリプションを購入したときに送信)** ```json showLineNumbers { "profile_id": "00000000-0000-0000-0000-000000000000", "customer_user_id": UserA, "event_properties": { "profile_has_access_level": true, }, "profiles_sharing_access_level": null } ``` - **ユーザーA:Access level updated(アプリが再インストールされてユーザーBがログインし、ユーザーAのアクセスが取り消されたときに送信)** ```json showLineNumbers { "profile_id": "00000000-0000-0000-0000-000000000000", "customer_user_id": UserA, "event_properties": { "profile_has_access_level": false, }, "profiles_sharing_access_level": null } ``` - **ユーザーB:Access level updated(ユーザーBがログインしてアクセスが付与されたときに送信)** ```json showLineNumbers { "profile_id": "00000000-0000-0000-0000-000000000001", "customer_user_id": UserB, "event_properties": { "profile_has_access_level": true, }, "profiles_sharing_access_level": null } ``` ### ユーザー間でのアクセス共有フロー \{#shared-access-between-users-flow\} このオプションでは、デバイスが同じApple/Google IDでサインインしている場合、複数のユーザーが同じアクセスレベルを共有できます。これは、ユーザーがアプリを再インストールして別のメールアドレスでログインした場合でも、以前の購入へのアクセスを維持できるため便利です。このオプションでは、複数の識別済みユーザーが同じアクセスレベルを共有できます。アクセスレベルを共有している間、すべてのトランザクションは完全なトランザクション履歴とアナリティクスを維持するために、元の <InlineTooltip tooltip="カスタマーユーザーID">[iOS](identifying-users#set-customer-user-id-on-configuration)、[Android](android-identifying-users#setting-customer-user-id-on-configuration)、[React Native](react-native-identifying-users#setting-customer-user-id-on-configuration)、[Flutter](flutter-identifying-users#setting-customer-user-id-on-configuration)、[Unity](unity-identifying-users#setting-customer-user-id-on-configuration)</InlineTooltip> の下に記録されます。 したがって、生成されるイベントは1つのみです:**Access level updated**(2番目のユーザーにアクセスを付与)。 <img src="/assets/shared/img_webhook_flows/Share_Access_Between_Users_Flow.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> このシナリオで生成されるイベントにおける、アクセスレベルの割り当てと共有に関連するフィールドの内訳は以下の通りです: **ユーザーB:Access level updated(ユーザーBがログインしてアクセスが付与されたときに送信)** ```json showLineNumbers { "profile_id": "00000000-0000-0000-0000-000000000000", "customer_user_id": UserA, "event_properties": { "profile_has_access_level": true, }, "profiles_sharing_access_level": [ { "profile_id": "00000000-0000-0000-0000-000000000001, "customer_user_id": UserB } ] } ``` ### ユーザー間でアクセスを共有しないフロー \{#access-not-shared-between-users-flow\} このオプションでは、最初にアクセスレベルを取得したユーザープロファイルのみが永続的にそれを保持します。購入を単一の <InlineTooltip tooltip="カスタマーユーザーID">[iOS](identifying-users#set-customer-user-id-on-configuration)、[Android](android-identifying-users#setting-customer-user-id-on-configuration)、[React Native](react-native-identifying-users#setting-customer-user-id-on-configuration)、[Flutter](flutter-identifying-users#setting-customer-user-id-on-configuration)、[Unity](unity-identifying-users#setting-customer-user-id-on-configuration)</InlineTooltip> に紐付ける必要がある場合に最適です。 <img src="/assets/shared/img_webhook_flows/Share_Access_Between_Users_Disabled_Flow.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> --- # File: event-statuses --- --- title: "インテグレーションイベントのステータス" description: "" --- Adapty は HTTP ステータスコードに基づいて配信可否を判定し、`200-399` の範囲外のレスポンスはすべて失敗として扱います。 インテグレーションイベントのステータスは、Adapty ダッシュボードの **Event List** で確認できます。特定のイベントタイプが特定のインテグレーションで有効になっているかどうかに関わらず、すべての有効なインテグレーションのステータスが表示されます。 - 黒: イベントが正常に送信されました。 - <span style={{ color: 'grey' }}>グレー:</span> このインテグレーションではイベントタイプが無効になっています。 - <span style={{ color: 'red' }}>赤:</span> インテグレーションに対応が必要な問題があります。 失敗したイベントの詳細を確認するには、インテグレーション名にカーソルを合わせると、具体的なエラー情報がツールチップで表示されます。 <img src="/assets/shared/img/event-status.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> **Event Feed** は、パフォーマンスを最適化するために過去2週間分のデータを表示します。この制限によりページの読み込み速度が向上し、ユーザーがイベントをスムーズに確認・分析できます。 --- # File: adjust --- --- title: "Adjust" description: "Adjustをアダプティに接続して、サブスクリプションのトラッキングと分析を改善します。" --- [Adjust](https://www.adjust.com/) は、マーケティングキャンペーンのデータを収集・提供する主要なMMP(モバイル計測パートナー)プラットフォームの一つです。企業はこれを活用してキャンペーンのパフォーマンスを把握できます。 Adaptyは、ストアからのサブスクリプションイベントを一か所で追跡できる完全なデータセットを提供します。Adaptyを使えば、ユーザーの行動を把握し、好みを理解した上で、ターゲットを絞った効果的なコミュニケーションが可能になります。このインテグレーションにより、Adjustでサブスクリプションイベントを追跡し、キャンペーンが生み出す収益を正確に分析できます。 AdaptiとAdjustのインテグレーションは、主に2つの方法で機能します。 1. **AdaptiがAdjustからアトリビューションデータを受け取る** Adjustインテグレーションを設定すると、AdaptiはAdjustからアトリビューションデータを受け取り始めます。このデータはユーザーのプロファイルページで簡単に確認できます。 <img src="/assets/shared/img/98769d9-CleanShot_2023-08-11_at_14.39.182x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. **AdaptiがサブスクリプションイベントをAdjustに送信する** Adaptyは、インテグレーションで設定したすべてのサブスクリプションイベントをAdjustに送信できます。これにより、Adjustのダッシュボードでこれらのイベントを追跡できます。このインテグレーションは、広告キャンペーンの効果測定に役立ちます。 ## インテグレーションの設定 \{#set-up-integration\} ### AdaptiをAdjustに接続する \{#connect-adapty-to-adjust\} 1. Adapty ダッシュボードを開き、[Integrations > Adjust](https://app.adapty.io/integrations/adjust) に移動します。 2. ページ上部のトグルをオンにします。 3. フィールドに入力し、アクセス認証情報を設定します。 <img src="/assets/shared/img/5064125-CleanShot_2023-08-11_at_14.43.382x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. AdjustプラットフォームでOAuth認証を有効にしている場合は、iOSおよびAndroidアプリのインテグレーション中に**OAuth Token**を提供することが必須です。 4. 次に、iOSおよびAndroidアプリの**app token**を入力します。Adjustのダッシュボードを開くと、登録済みのアプリが表示されます。 <img src="/assets/shared/img/adjust-apps.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> :::note iOSとAndroidで異なるAdjustアプリケーションを使用している場合があるため、Adaptyにはそれぞれ独立したセクションが用意されています。Adjustアプリが1つだけの場合は、同じ情報を両方に入力してください。 ::: 5. リストからアプリを選択し、**App Token**をコピーします。トークンをAdaptyダッシュボードの対応するフィールドに貼り付けます。 <img src="/assets/shared/img/adjust-token.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### イベントとタグの設定 \{#configure-events-and-tags\} Adjustは他のプラットフォームとは少し異なる仕組みで動作します。Adjustのダッシュボードでイベントを手動で作成し、イベントトークンを取得して、Adaptyの対応するイベントに貼り付ける必要があります。 最初のステップは、Adaptyに送信したいすべてのイベントのイベントトークンを確認することです。手順は以下のとおりです: 1. Adjustのダッシュボードでアプリを開き、**Events**タブに切り替えます。 <img src="/assets/shared/img/adjust-events.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 1. イベントトークンをコピーしてAdaptiに貼り付けます。認証情報の下には、AdaptiからAdjustに送信できるイベントが3つのグループに分かれて表示されます。Adaptyが提供するイベントの全リストは[こちら](events)で確認できます。 <img src="/assets/shared/img/adjust-event-token.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Adaptyはサーバー間インテグレーションを使用してサブスクリプションイベントをAdjustに送信するため、Adjustのダッシュボードですべてのサブスクリプションイベントを確認し、それらを広告獲得キャンペーンに関連付けることができます。 :::important 以下の点にご注意ください: - Adjustは58日以上前のイベントをサポートしていません。58日を超えるイベントはAdaptiからAdjustに送信されますが、イベントの日時は現在のタイムスタンプに置き換えられます。 - AdjustはIPv6をサポートしていません。**App settings**またはSDKのアクティベーション時にSDKでのIP収集を無効にした場合、バックエンドのIPv6のみが送信され、トラッキングが失敗する可能性があります。IPv4が使用されるよう、SDKのIP収集は有効のままにしておいてください。 ::: ### アプリをAdjustに接続する \{#connect-your-app-to-adjust\} 上記の手順が完了したら、以下の2つのメソッドをアプリに追加します。これらはアプリとAdjust間の通信を確立します: 1. **サブスクリプションデータをAdjustに送信する**: Adjustのデバイス IDを`setIntegrationIdentifier()` SDKメソッドに渡します。 2. **Adjustからアトリビューションデータを受け取る**: `updateAttribution()` SDKメソッドでアトリビューションデータを更新します。 Adjustバージョン5.0以降では、以下の例を使用してください: <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS (Swift)" default> ```swift showLineNumbers class AdjustModuleImplementation { func updateAdjustAdid() { Adjust.adid { adid in guard let adid else { return } // Adapty SDK 4.x Adapty.setIntegrationIdentifier(.adjustDeviceId(adid)) // Adapty SDK 3.x Adapty.setIntegrationIdentifier(key: "adjust_device_id", value: adid) } } func updateAdjustAttribution() { Adjust.attribution { attribution in guard let attribution = attribution?.dictionary() else { return } // Adapty SDK 4.x Adapty.updateAttribution(attribution, source: .adjust) // Adapty SDK 3.x Adapty.updateAttribution(attribution, source: "adjust") } } } ``` </TabItem> <TabItem value="kotlin" label="Android (Kotlin)" default> ```kotlin showLineNumbers Adjust.getAdid { adid -> if (adid == null) return@getAdid Adapty.setIntegrationIdentifier("adjust_device_id", adid) { error -> if (error != null) { // handle the error } } } Adjust.getAttribution { attribution -> if (attribution == null) return@getAttribution Adapty.updateAttribution(attribution, "adjust") { error -> // handle the error } } ``` </TabItem> <TabItem value="java" label="Android (Java)" default> ```java showLineNumbers Adjust.getAdid(adid -> { if (adid == null) return; Adapty.setIntegrationIdentifier("adjust_device_id", adid, error -> { if (error != null) { // handle the error } }); }); Adjust.getAttribution(attribution -> { if (attribution == null) return; Adapty.updateAttribution(attribution, "adjust", error -> { // handle the error }); }); ``` </TabItem> <TabItem value="rn" label="React Native (TS)" default> ```typescript showLineNumbers var adjustConfig = new AdjustConfig(appToken, environment); // Before submiting Adjust config... adjustConfig.setAttributionCallbackListener(attribution => { // Make sure Adapty SDK is activated at this point // You may want to lock this thread awaiting of `activate` adapty.updateAttribution(attribution, "adjust"); }); // ... Adjust.create(adjustConfig); Adjust.getAdid((adid) => { if (adid) adapty.setIntegrationIdentifier("adjust_device_id", adid); }); ``` </TabItem> <TabItem value="flutter" label="Flutter" default> ```javascript showLineNumbers try { final adid = await Adjust.getAdid(); if (adid == null) { // handle the error } await Adapty().setIntegrationIdentifier( key: "adjust_device_id", value: adid, ); final attributionData = await Adjust.getAttribution(); var attribution = Map<String, String>(); if (attributionData.trackerToken != null) attribution['trackerToken'] = attributionData.trackerToken!; if (attributionData.trackerName != null) attribution['trackerName'] = attributionData.trackerName!; if (attributionData.network != null) attribution['network'] = attributionData.network!; if (attributionData.adgroup != null) attribution['adgroup'] = attributionData.adgroup!; if (attributionData.creative != null) attribution['creative'] = attributionData.creative!; if (attributionData.clickLabel != null) attribution['clickLabel'] = attributionData.clickLabel!; if (attributionData.costType != null) attribution['costType'] = attributionData.costType!; if (attributionData.costAmount != null) attribution['costAmount'] = attributionData.costAmount!.toString(); if (attributionData.costCurrency != null) attribution['costCurrency'] = attributionData.costCurrency!; if (attributionData.fbInstallReferrer != null) attribution['fbInstallReferrer'] = attributionData.fbInstallReferrer!; await Adapty().updateAttribution(attribution, source: "adjust"); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` </TabItem> <TabItem value="unity" label="Unity" default> ```csharp showLineNumbers // 1. To update ADID Adjust.GetAdid((adid) => { if (adid == null) { // handle the error return; } Adapty.SetIntegrationIdentifier("adjust_device_id", adid, (error) => { if (error != null) { // handle the error return; } }); }); // 2. To update Attribution // in your adjust configuration scope: adjustConfig.AttributionChangedDelegate = AttributionChangedCallback; public void AttributionChangedCallback(AdjustAttribution attributionData) { var attribution = new Dictionary<string, string>(); if (attributionData.TrackerToken != null) attribution["trackerToken"] = attributionData.TrackerToken; if (attributionData.TrackerName != null) attribution["trackerName"] = attributionData.TrackerName; if (attributionData.Network != null) attribution["network"] = attributionData.Network; if (attributionData.Adgroup != null) attribution["adgroup"] = attributionData.Adgroup; if (attributionData.Creative != null) attribution["creative"] = attributionData.Creative; if (attributionData.ClickLabel != null) attribution["clickLabel"] = attributionData.ClickLabel; if (attributionData.CostType != null) attribution["costType"] = attributionData.CostType; if (attributionData.CostAmount != null) attribution["costAmount"] = attributionData.CostAmount.ToString(); if (attributionData.CostCurrency != null) attribution["costCurrency"] = attributionData.CostCurrency; if (attributionData.FbInstallReferrer != null) attribution["fbInstallReferrer"] = attributionData.FbInstallReferrer; // you will probably need to install Newtonsoft.Json package, if not yet var attributionJsonString = Newtonsoft.Json.JsonConvert.SerializeObject(attribution); Adapty.UpdateAttribution(attributionJsonString, "adjust", (error) => { if (error != null) { // handle the error } }); } ``` </TabItem> </Tabs> ## イベント構造 \{#event-structure\} Adaptyは、[**Adjust Integration page**](https://app.adapty.io/integrations/adjust)の**Events names**セクションで設定された内容に従い、選択したイベントをAdjustに送信します。各イベントの構造は以下のとおりです: ```json { "event_token": "EVENT_TOKEN_FROM_CONFIG", "app_token": "APP_TOKEN_FROM_CONFIG", "s2s": 1, "environment": "production", "created_at_unix": 1709294400, "currency": "USD", "revenue": 9.99, "customer_user_id": "user_12345", "external_device_id": "user_12345", "ip_address": "192.168.100.1", "user_agent": "Mozilla/5.0 (Linux; Android 14; SM-S901B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36", "android_id": "875646c2-4a56-4211-8931-168532479006", "gps_adid": "875646c2-4a56-4211-8931-168532479006", "callback_params": "{\"integration_event_id\":\"550e8400-e29b-41d4-a716-446655440000\",\"customer_user_id\":\"user_12345\",\"vendor_product_id\":\"com.example.app.yearly.premium\",\"transaction_id\":\"GPA.3312-4512-1100-55923\",\"original_transaction_id\":\"GPA.3312-4512-1100-55923\",\"store\":\"play_store\",\"store_country\":\"US\",\"price_usd\":9.99,\"proceeds_usd\":8.49,\"price_local\":9.99,\"proceeds_local\":8.49,\"net_revenue_usd\":8.49,\"net_revenue_local\":8.49,\"tax_amount_usd\":0.0,\"tax_amount_local\":0.0,\"consecutive_payments\":3,\"rate_after_first_year\":false}", "partner_params": "{\"integration_event_id\":\"550e8400-e29b-41d4-a716-446655440000\",\"customer_user_id\":\"user_12345\",\"vendor_product_id\":\"com.example.app.yearly.premium\",\"transaction_id\":\"GPA.3312-4512-1100-55923\",\"original_transaction_id\":\"GPA.3312-4512-1100-55923\",\"store\":\"play_store\",\"store_country\":\"US\",\"price_usd\":9.99,\"proceeds_usd\":8.49,\"price_local\":9.99,\"proceeds_local\":8.49,\"net_revenue_usd\":8.49,\"net_revenue_local\":8.49,\"tax_amount_usd\":0.0,\"tax_amount_local\":0.0,\"consecutive_payments\":3,\"rate_after_first_year\":false}" } ``` 各パラメーターの説明: | パラメーター | 型 | 説明 | |:---------------------|:--------|:---------------------------------------------------------------------------------------------------------------------------------------------| | `app_token` | String | インテグレーション設定に登録されているAdjustのApp Token。 | | `event_token` | String | 特定のAdaptiイベントに対応するAdjustのEvent Token。 | | `s2s` | Integer | サーバー間イベントフラグ。 | | `environment` | String | `sandbox` または `production`。 | | `created_at_unix` | Integer | イベントのタイムスタンプ(秒単位)。 | | `currency` | String | 取引の通貨コード(例: "USD")。収益が0.001を超える場合にのみ含まれます。AdjustはrevenueとcurrencyをセットでRequireするためです。 | | `revenue` | Float | 取引の収益額。値が0.001を超える場合にのみ含まれます。なお、返金イベントはrevenue属性なしで送信されます(Adjustは負の収益値をサポートしていないため)。 | | `customer_user_id` | String | ユーザーのCustomer User ID。 | | `external_device_id` | String | `customer_user_id`と同じ値。 | | `ip_address` | String | ユーザーのIPアドレス(IPv4のみ)。 | | `user_agent` | String | デバイスのUser Agent文字列。 | | `adid` | String | AdjustのデバイスID(判明している場合)。 | | `android_id` | String | **Androidのみ**。Google Advertising ID。 | | `gps_adid` | String | **Androidのみ**。Google Advertising ID。 | | `idfa` | String | **iOSのみ**。広告主向け識別子(IDFA)。 | | `idfv` | String | **iOSのみ**。ベンダー向け識別子(IDFV)。 | | `callback_params` | String | 利用可能な[イベントフィールド](webhook-event-types-and-fields#for-most-event-types)をすべて含むJSON文字列。null以外のフィールドのみが含まれます。 | | `partner_params` | String | `callback_params`と同じ内容。 | ## トラブルシューティング \{#troubleshooting\} ### 収益の不一致 \{#revenue-discrepancy\} AdaptiとAdjust間で収益に差異がある場合、Adapty SDKを含むアプリバージョンを使用していないユーザーが存在することが原因として考えられます。データの一貫性を確保するには、Adapty SDKを搭載したバージョンへのアップデートをユーザーに促すことをお勧めします。 --- # File: airbridge --- --- title: "Airbridge" description: "AdaptyとAirbridgeを連携して、マーケティングとアトリビューションのインサイトを追跡します。" --- [Airbridge](https://www.airbridge.io/) は、複数のデバイス、プラットフォーム、チャネルから収集したデータを統合することで、ウェブサイトとモバイルアプリの統合マーケティングパフォーマンス分析を提供します。AirbridgeのIdentity Resolution Engineを使用すると、ウェブとアプリのインタラクションから得た断片的な顧客IDデータを統合した人ベースのIDに集約でき、より精度の高いアトリビューションを実現できます。 Adaptyは、ストアからの[サブスクリプションイベント](events)を一元管理できる完全なデータセットを提供します。Adaptyを使えば、ユーザーの行動を簡単に把握し、好みを理解した上で、ターゲットを絞った効果的なコミュニケーションに活かすことができます。 AdaptyとAirbridgeの連携は、主に2つの方向で機能します。 1. **Airbridgeからのアトリビューションデータの受信** Airbridge連携を設定すると、AdaptyはAirbridgeからアトリビューションデータの受信を開始します。このデータはユーザーページで簡単に確認できます。 2. **Airbridgeへのサブスクリプションイベントの送信** Adaptyは、連携設定で指定したすべてのサブスクリプションイベントをAirbridgeに送信できます。これにより、Airbridgeのダッシュボード内でこれらのイベントを追跡できるようになります。この連携は、広告キャンペーンの効果測定に役立ちます。 ## 連携の設定 \{#set-up-integration\} ### AdaptyをAirbridgeに接続する \{#connect-adapty-to-airbridge\} Airbridgeを連携するには、[Integrations > Airbridge](https://app.adapty.io/integrations/airbridge) に移動し、トグルをオンにして各フィールドを入力します。 まず、AirbridgeとAdaptyプロファイル間の接続を構築するための認証情報を設定します。AirbridgeのアプリネームとAirbridge APIトークンが必要です。 <img src="/assets/shared/img/2b31d90-Untitled-1_1.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> どちらもAirbridgeダッシュボードの [Third-party Integrations > Adapty](https://app.airbridge.io/app/testad/integrations/third-party/adapty) セクションで確認できます。 <img src="/assets/shared/img/5a2f627-Screenshot_2023-02-21_at_11.19.29_AM.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Adapty APIトークンフィールドはAdaptyバックエンドで事前に生成されています。Adapty APIトークンの値をコピーし、AirbridgeダッシュボードのAdapty Authorization Tokenフィールドに貼り付けてください。 <img src="/assets/shared/img/ff422d1-CleanShot_2023-03-01_at_17.11.412x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### イベントとタグの設定 \{#configure-events-and-tags\} 認証情報の下には、AdaptyからAirbridgeに送信できる3グループのイベントがあります。 <img src="/assets/shared/img/eb4e3a9-CleanShot_2023-08-22_at_13.58.472x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 必要なものをオンにするだけです。 ### アプリをAirbridgeに接続する \{#connect-your-app-to-airbridge\} 連携のために、以下の例のように `airbridge_device_id` をプロファイルビルダーに渡し、`setIntegrationIdentifier` を呼び出してください。 <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS (Swift)" default> ```swift showLineNumbers do { try await Adapty.setIntegrationIdentifier( key: "airbridge_device_id", value: AirBridge.deviceUUID() ) } catch { // handle the error } ``` </TabItem> <TabItem value="kotlin" label="Android (Kotlin)" default> ```kotlin showLineNumbers Airbridge.getDeviceInfo().getUUID(object: AirbridgeCallback.SimpleCallback<String>() { override fun onSuccess(result: String) { Adapty.setIntegrationIdentifier("airbridge_device_id", result) { error -> if (error != null) { // handle the error } } } override fun onFailure(throwable: Throwable) { } }) ``` </TabItem> <TabItem value="flutter" label="Flutter (Dart)" default> ```javascript showLineNumbers final deviceUUID = await Airbridge.state.deviceUUID; try { await Adapty().setIntegrationIdentifier( key: "airbridge_device_id", value: deviceUUID, ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` </TabItem> <TabItem value="rn" label="React Native (TS)" default> ```typescript showLineNumbers try { const deviceId = await Airbridge.state.deviceUUID(); await adapty.setIntegrationIdentifier("airbridge_device_id", deviceId); } catch (error) { // handle `AdaptyError` } ``` </TabItem> </Tabs> airbridgeDeviceIdの詳細については、[Airbridgeのドキュメント](https://help.airbridge.io/en/developers/airbridge-device-id-faq)をご覧ください。 サブスクリプションイベント後、AdaptyがAirbridgeのアトリビューションデータを受信するまで最大24時間かかる場合があります。受信後はダッシュボードに即座に表示されます。 ## イベント構造 \{#event-structure\} Adaptyは、[**Airbridge Integration page**](https://app.adapty.io/integrations/airbridge) の **Events names** セクションで設定された内容に従い、選択したイベントをAirbridgeに送信します。各イベントの構造は以下の通りです。 ```json { "user": { "externalUserID": "user_12345", "externalUserEmail": "user@example.com", "attributes": { "is_premium": true } }, "device": { "deviceUUID": "550e8400-e29b-41d4-a716-446655440000", "deviceModel": "iPhone 14 Pro", "osName": "iOS", "osVersion": "17.0.1", "locale": "en-US", "timezone": "America/New_York", "ifa": "00000000-0000-0000-0000-000000000000", "ifv": "00000000-0000-0000-0000-000000000000" }, "app": { "packageName": "com.example.app", "version": "1.2.3" }, "eventUUID": "d4f6f1f4-96fb-4a31-bafd-599fef77be90", "eventTimestamp": 1709294400000, "eventData": { "goal": { "category": "airbridge.subscribe", "customAttributes": { "isTrialConverted": true }, "semanticAttributes": { "transactionID": "GPA.3383-4699-1373-07113", "totalValue": 9.99, "currency": "USD", "period": "P1M", "isRenewal": true, "renewalCount": 2, "products": [ { "productID": "yearly.premium.6999", "name": "yearly.premium.6999", "position": 1 } ] } } } } ``` 各パラメータの説明: | パラメータ | 型 | 説明 | |:----------------------------------------------|:---------|:-------------------------------------------------------------------| | `user` | Object | ユーザー情報。 | | `user.externalUserID` | String | ユーザーのCustomer User ID。 | | `user.externalUserEmail` | String | ユーザーのメールアドレス(利用可能な場合)。 | | `user.attributes` | Object | カスタムユーザー属性。 | | `device` | Object | デバイス情報。 | | `device.deviceUUID` | String | AirbridgeのDevice UUID。 | | `device.deviceModel` | String | デバイスモデル(例: "iPhone 14 Pro")。 | | `device.osName` | String | OS名(例: "iOS"、"Android")。 | | `device.osVersion` | String | OSバージョン。 | | `device.ifa` | String | **iOSのみ**。ID for Advertisers。 | | `device.ifv` | String | **iOSのみ**。ID for Vendors。 | | `device.gaid` | String | **Androidのみ**。Google Advertising ID。 | | `app` | Object | アプリ情報。 | | `app.packageName` | String | アプリのパッケージ名 / バンドルID。 | | `app.version` | String | アプリのバージョン。 | | `eventUUID` | String | Adaptyにおけるイベントの一意ID。 | | `eventTimestamp` | Long | イベントのタイムスタンプ(ミリ秒)。 | | `eventData` | Object | イベントの詳細。 | | `eventData.goal.category` | String | Airbridgeのイベントカテゴリ(Adaptyイベントからマッピングされる)。 | | `eventData.goal.semanticAttributes` | Object | 標準イベント属性。 | | `...semanticAttributes.transactionID` | String | ストアのTransaction ID。 | | `...semanticAttributes.totalValue` | Float | 売上金額。 | | `...semanticAttributes.currency` | String | 通貨コード(例: "USD")。 | | `...semanticAttributes.period` | String | ISO 8601の期間形式によるサブスクリプション期間(例: "P1M")。 | | `...semanticAttributes.isRenewal` | Boolean | 更新トランザクションの場合は `true`。 | | `...semanticAttributes.renewalCount` | Integer | 成功した更新回数。 | | `...semanticAttributes.products` | Array | イベントに関与するプロダクトのリスト。 | | `...semanticAttributes.products[].productID` | String | ストアのプロダクトID(例: "yearly.premium.6999")。 | | `...semanticAttributes.products[].name` | String | `productID` と同じ。 | | `...semanticAttributes.products[].position` | Integer | リスト内のプロダクトの位置(常に1)。 | --- # File: apple-search-ads --- --- title: "Apple Ads" description: "Apple Ads を Adapty と連携してサブスクリプションのコンバージョンを最適化しましょう。" --- :::important **App settings** の Apple Ads 連携は、基本的なアナリティクスと SplitMetrics Acquire および Asapty 連携にのみ使用されます。 [Apple Ads Manager](adapty-ads-manager) は別の接続を使用します。Apple Ads アカウントは [Apple Ads Manager の設定](adapty-ads-manager-get-started)で接続してください。 ::: Adapty は Apple Ads からアトリビューションデータを取得し、キャンペーンやキーワードのセグメンテーションで指標を分析するのに役立ちます。Adapty は SDK と AdServices Framework を通じて Apple Ads のアトリビューションデータを自動的に収集します。 Apple Ads 連携を設定すると、Adapty が Apple Ads からアトリビューションデータを受信し始めます。このデータはプロファイルページで簡単に確認できます。 <img src="/assets/shared/img/ba4a3e9-CleanShot_2023-08-21_at_15.14.592x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## 連携の設定 \{#set-up-integration\} ### Adapty を AdServices フレームワークに接続する \{#connect-adapty-to-the-adservices-framework\} [AdServices](https://developer.apple.com/documentation/adservices) 経由の Apple Ads は Adapty ダッシュボードでの設定が必要で、アプリ側でも有効化する必要があります。AdServices フレームワークを使って Adapty 経由で Apple Ads を設定するには、以下の手順に従ってください。 #### ステップ 1: 公開鍵を取得する \{#step-1-obtain-public-key\} Adapty ダッシュボードで [Settings -> Apple Ads](https://app.adapty.io/settings/apple-search-ads) に移動します。 事前に生成された公開鍵(Adapty がキーペアを用意しています)を見つけてコピーします。 <img src="/assets/shared/img/baa5998-CleanShot_2023-08-21_at_14.55.542x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> :::note Apple Ads アトリビューションに別のサービスや独自のソリューションを使用している場合は、独自の秘密鍵をアップロードできます。 ::: #### ステップ 2: Apple Ads でユーザー管理を設定する \{#step-2-configure-user-management-on-apple-ads\} [Apple Ads アカウント](https://ads.apple.com/app-store)で **Settings > User Management** ページに移動します。Adapty がアトリビューションデータを取得できるようにするには、別の Apple ID アカウントを招待して API Account Manager アクセス権を付与する必要があります。既存のアカウントを使用するか、この目的専用の新しいアカウントを作成してください。重要なのは、その Apple ID で Apple Ads にログインできる必要があることです。 <img src="/assets/shared/img/ec183b2-kdjsfldsfjkdsfdfd.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> #### ステップ 3: API 認証情報を生成する \{#step-3-generate-api-credentials\} 次に、新しく追加したアカウントで Apple Ads にログインします。Apple Ads の Settings -> API に移動します。先ほどコピーした公開鍵を指定のフィールドに貼り付けて、新しい API 認証情報を生成します。 #### ステップ 4: Apple Ads の認証情報を Adapty に設定する \{#step-4-configure-adapty-with-apple-ads-credentials\} Apple Ads の設定から Client ID、Team ID、Key ID をコピーします。Adapty ダッシュボードで、これらの認証情報を対応するフィールドに貼り付けます。 <img src="/assets/shared/img/7356113-CleanShot_2023-08-21_at_15.08.512x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### アプリを AdServices ネットワークに接続する \{#connect-your-app-to-the-adservices-network\} [AdServices フレームワークの設定](#connect-the-adservices-framework)が完了すると、Adapty は Apple Search Ad のアトリビューションデータの収集を自動的に開始します。SDK コードを追加する必要はありません。 iOS アプリケーションでは、このアトリビューションデータは**常に**他のソースからのデータより優先されます。この動作が不要な場合は、以下の手順で ASA アトリビューションを*無効化*してください。 ## 連携を無効化する \{#disable-integration\} Apple Search Ads アトリビューションをオフにするには、[**App Settings** -> **Apple Search Ads** タブ](https://app.adapty.io/settings/apple-search-ads)を開き、**Receive Apple Search Ads attribution** スイッチをオフにします。 <img src="/assets/shared/img/asa-disable.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> :::warning これを無効化すると、ASA アナリティクスの受信が完全に停止します。その結果、ASA はアナリティクスでの使用や連携への送信が行われなくなります。また、SplitMetrics Acquire と Asapty は ASA アトリビューションに依存して動作するため、機能しなくなります。 この変更以前に受信済みのアトリビューションデータには影響しません。 ::: ## 独自のキーをアップロードする \{#uploading-your-own-keys\} :::note オプション これらの手順は Apple Ads アトリビューションには必要ありません。Asapty などの他のサービスや独自ソリューションと連携する場合にのみ必要です。 ::: ASA アトリビューションに他のサービスや独自ソリューションを使用している場合は、独自の公開鍵・秘密鍵ペアを使用できます。 ### ステップ 1 \{#step-1\} ターミナルで秘密鍵を生成する ```text showLineNumbers title="Text" openssl ecparam -genkey -name prime256v1 -noout -out private-key.pem ``` Adapty の Settings -> Apple Ads でアップロードする(**Upload private key** ボタン) ### ステップ 2 \{#step-2\} ターミナルで公開鍵を生成する ```text showLineNumbers title="Text" openssl ec -in private-key.pem -pubout -out public-key.pem ``` この公開鍵は、API Account Manager ロールを持つアカウントの Apple Ads 設定で使用できます。これにより、生成された Client ID、Team ID、Key ID の値を Adapty や他のサービスで利用できます。 --- # File: switch-from-appsflyer-s2s-api-2-to-3 --- --- title: "AppsFlyer S2S API 2 から 3 への切り替え" description: "Adapty で AppsFlyer S2S API 2 から 3 へアップグレードする方法。" --- [AppsFlyer の公式 What's New](https://support.appsflyer.com/hc/en-us/articles/20509378973457-Bulletin-Upgrading-the-AppsFlyer-S2S-API) によると、API 利用をより安全にし、不正を減らすために、AppsFlyer はアプリ内イベント向けのサーバー間 (S2S) API をアップグレードしました。既存のエンドポイントは将来的に廃止される予定であるため、切り替えの計画を早めに始めることをおすすめします。 Adapty は AppsFlyer S2S API 3 に対応しており、API 2 からスムーズに切り替えられます。ただし、この切り替えは一方向です。一度変更すると API 2 に戻すことはできません。 AppsFlyer S2S API 2 から 3 に切り替えるには: 1. [AppsFlyer サイト](https://www.appsflyer.com/home)を開いてログインします。 2. ダッシュボード左上の **Your account name** -> **Security Center** をクリックします。 <img src="/assets/shared/img/be299ea-appsflyer_security_center.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. **Manage your account security** ウィンドウで、**Manage your AppsFlyer API and S2S tokens** ボタンをクリックします。 4. S2S トークンがない場合は **New token** ボタンをクリックします。すでにある場合は手順 8 に進んでください。 <img src="/assets/shared/img/7934920-appsflyer_new_token.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. **New token** ウィンドウで、トークンの名前を入力します。この名前はあなただけの管理用です。 6. **Choose type** リストから **S2S** を選択します。 7. **Create new token** ボタンをクリックして新しいトークンを保存することを忘れずに。 8. **Tokens** ウィンドウで S2S トークンをコピーします。 <img src="/assets/shared/img/d014c25-appsflyer_tokens.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 9. Adapty ダッシュボードで [**Integrations** -> **AppsFlyer**](https://app.adapty.io/integrations/appsflyer) を開きます。 10. **AppsFlyer S2S API** フィールドで **API 3** を選択します。 <img src="/assets/shared/img/c0b3e72-appsflyer_switch_API.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 11. コピーした S2S キーを **Dev key for iOS** と **Dev key for Android** フィールドに貼り付けます。 12. **Save** ボタンをクリックして切り替えを確定します。 この操作が完了すると、インテグレーションは即座に AppsFlyer S2S API 3 に切り替わり、新しいイベントは新しい URL `https://api3.appsflyer.com/inappevent` に送信されます。 --- # File: asapty --- --- title: "Asapty" description: "AdaptyのサブスクリプションエコシステムにおけるAsaptyとその役割を詳しく説明します。" --- [Asapty](https://asapty.com/) インテグレーションを使用すると、Search Ads キャンペーンを最適化できます。AdaptyはサブスクリプションイベントをAsaptyに送信するため、Apple Search Adsアトリビューションに基づいたカスタムダッシュボードをAsapty上で構築できます。 このインテグレーションはAdaptyにアトリビューションデータを追加しません。[ASA](apple-search-ads) から直接必要なデータをすべて取得しているためです。 ## インテグレーションの設定 \{#set-up-integration\} ### AdaptyとAsaptyを接続する \{#connect-adapty-to-asapty\} Asaptyを連携するには、Adapty ダッシュボードの [Integrations > Asapty](https://app.adapty.io/integrations/asapty) に移動し、Asapty IDのフィールドに値を入力してください。 <img src="/assets/shared/img/895de2b-CleanShot_2023-08-14_at_18.57.462x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Asapty IDは、Asaptyアカウントの Settings > General セクションで確認できます。 ### イベントとタグを設定する \{#configure-events-and-tags\} 認証情報の下には、AdaptyからAsaptyに送信できるイベントが3つのグループに分かれています。必要なものをオンにするだけです。Adaptyが提供するイベントの全リストは[こちら](events)で確認できます。 <img src="/assets/shared/img/58ddf41-CleanShot_2023-08-15_at_15.11.072x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Asaptyが提供するデフォルトのイベント名を使用することを推奨しますが、必要に応じてイベント名を変更することもできます。 ### アプリをAsaptyに接続する \{#connect-your-app-to-asapty\} 上記の手順を完了すると、Adaptyは自動的にAsaptyからアトリビューションデータを受信します。アプリのコードでアトリビューションデータを明示的にリクエストする必要はありません。アトリビューションデータの精度を高めるために、各イベントのデータに `customerUserId` を含めるようAsaptyを設定してください。 ## Asaptyイベントの構造 \{#asapty-event-structure\} AdaptyはGETリクエストのクエリパラメーターを使用してAsaptyにイベントを送信します。各イベントのURLは次のような形式になります。 ``` https://asapty.com/_api/mmpEvents/?source=adapty&asaptyid=a1b2c3d4&keywordid=12345&adgroupid=67890&campaignid=11223&conversiondate=1709294400000&event_name=subscription_renewed&install_time=1709100000&app_name=MyApp&json=%7B%22af_revenue%22%3A%229.99%22%2C%22af_currency%22%3A%22USD%22...%7D ``` クエリパラメーター: | パラメーター | 型 | 説明 | |:-----------------|:-------|:-----------------------------------------------------| | `source` | String | 常に "adapty"。 | | `asaptyid` | String | 認証情報のAsapty ID。 | | `keywordid` | String | Apple Search AdsのキーワードID(利用可能な場合)。 | | `adgroupid` | String | Apple Search AdsのADグループID(利用可能な場合)。 | | `campaignid` | String | Apple Search AdsのキャンペーンID(利用可能な場合)。 | | `conversiondate` | Long | イベントのタイムスタンプ(**ミリ秒**単位)。 | | `event_name` | String | イベント名(Adaptyイベントからマッピングされたもの)。| | `install_time` | Long | インストールのタイムスタンプ(秒単位)。 | | `app_name` | String | Adaptyのアプリタイトル(利用可能な場合)。 | | `json` | String | イベントの詳細を含むURLエンコードされたJSON文字列(下記参照)。 | `json` パラメーターは、以下のフィールドを含むURLエンコードされたJSON文字列です: | パラメーター | 型 | 説明 | |:--------------------------|:-------|:---------------------------------------------| | `af_revenue` | String | 収益金額(文字列形式)。 | | `af_currency` | String | 通貨コード(例:"USD")。 | | `transaction_id` | String | ストアのトランザクションID。 | | `original_transaction_id` | String | ストアの元のトランザクションID。 | | `purchase_date` | Long | 購入タイムスタンプ(ミリ秒単位)。 | | `original_purchase_date` | Long | 元の購入タイムスタンプ(ミリ秒単位)。 | | `environment` | String | `Production` または `Sandbox`。 | | `vendor_product_id` | String | ストアのプロダクトID。 | | `profile_country` | String | ユーザーのIPに基づく国コード。 | | `store_country` | String | ストアユーザーの国コード。 | ## トラブルシューティング \{#troubleshooting\} - AdaptyでApple Search Adsを設定し、[認証情報をアップロード](https://app.adapty.io/settings/apple-search-ads)していることを確認してください。設定がないとAsaptyは機能しません。 - 詳細な非オーガニックASAアトリビューションを持つプロファイルのみが、Asaptyにイベントを送信します。アトリビューションが不十分な場合は、"The user profile is missing the required integration data." と表示されます。 - インテグレーションの設定前に作成されたプロファイルは、Asaptyにイベントを送信できません。 - 正しく設定しているにもかかわらずAdaptyとのインテグレーションが機能しない場合は、[**App Settings** -> **Apple Search Ads** タブ](https://app.adapty.io/settings/apple-search-ads)で **Receive Apple Search Ads attribution in Adapty** トグルが有効になっているか確認してください。 --- # File: branch --- --- title: "Branch" description: "Branch と Adapty を統合して、ディープリンクとアプリのコンバージョンを追跡します。" --- [Branch](https://www.branch.io/) を使うと、さまざまなデバイス・チャネル・プラットフォームをまたいでユーザーへのリーチ、エンゲージメント、効果測定ができます。あらゆるデバイス・チャネル・プラットフォームで機能する専用リンクを通じて、モバイル収益を高めるために設計された使いやすいプラットフォームです。 Adapty は、ストアからの[サブスクリプションイベント](events)を一か所で追跡できる完全なデータセットを提供します。Adapty を使えば、サブスクライバーの行動を簡単に把握し、好みを理解した上で、ターゲットを絞った効果的なコミュニケーションに役立てることができます。 Adapty と Branch の連携は、主に 2 つの方法で動作します。 1. **Branch からアトリビューションデータを受信する** Branch 連携を設定すると、Adapty は Branch からアトリビューションデータを受信し始めます。このデータはユーザーのプロファイルページで簡単に確認できます。 <img src="/assets/shared/img/49f4aa7-CleanShot_2023-08-11_at_17.36.072x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. **サブスクリプションイベントを Branch に送信する** Adapty は、連携で設定されたすべてのサブスクリプションイベントを Branch に送信できます。これにより、Branch ダッシュボード内でこれらのイベントを追跡し、獲得キャンペーンと紐付けることができます。 ## 連携のセットアップ \{#set-up-integration\} ### Adapty を Branch に接続する \{#connect-adapty-to-branch\} Branch を連携するには、Adapty ダッシュボードの [Integrations > Branch](https://app.adapty.io/integrations/branch) に移動し、トグルをオンにして各フィールドに入力してください。 <img src="/assets/shared/img/817a051-CleanShot_2023-08-11_at_15.54.372x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> **Branch Key** の値を取得するには、Branch の [Account Settings](https://dashboard.branch.io/account-settings/profile) を開き、**Branch Key** フィールドを確認してください。Adapty ダッシュボードの **Key test**(サンドボックス用)または **Key live**(本番用)フィールドに使用します。Branch 側では、Live と Test の環境を切り替えて適切なキーを取得してください。 <img src="/assets/shared/img/130e58b-CleanShot_2023-08-11_at_15.24.162x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### イベントとタグを設定する \{#configure-events-and-tags\} 認証情報の下には、Adapty から Branch に送信できるイベントが 3 つのグループに分かれています。必要なものをオンにするだけです。Adapty が提供するイベントの全一覧は[こちら](events)で確認できます。 収益(Apple/Google の手数料差し引き後)または売上金額のみでイベントを送信できます。また、ユーザーの通貨でレポートするチェックボックスもあります。 <img src="/assets/shared/img/a645cf8-CleanShot_2023-08-11_at_15.18.282x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Adapty が提供するデフォルトのイベント名を使用することを推奨します。ただし、必要に応じてイベント名を変更することも可能です。 Adapty はサーバー間連携を使って Branch にサブスクリプションイベントを送信するため、Branch ダッシュボードですべてのサブスクリプションイベントを確認し、獲得キャンペーンと紐付けることができます。 ### アプリを Branch に接続する \{#connect-your-app-to-branch\} 1. `.setIntegrationIdentifier()` SDK メソッドを呼び出して接続を初期化します。Branch の Identity ID を `customerUserId` パラメータに渡すことができます。 --- no_index: true --- import Callout from '../../../components/Callout.astro'; <Callout type="note"> サードパーティのユーザーIDをCustomer User IDとして使用する場合、`activate()`の際に渡さないでください。サードパーティSDKがまだIDを生成していない可能性があります。代わりに、まず`activate()`をCUIDなしで呼び出し、次に`setIntegrationIdentifier()`、そして`identify()`にCUIDを渡して呼び出してください。 </Callout> <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS (Swift)" default> ```swift showLineNumbers do { // Adapty SDK 4.x try await Adapty.setIntegrationIdentifier(.branchId(<BRANCH_IDENTITY_ID>)) // Adapty SDK 3.x try await Adapty.setIntegrationIdentifier( key: "branch_id", value: <BRANCH_IDENTITY_ID> ) } catch { // handle the error } ``` </TabItem> <TabItem value="kotlin" label="Android (Kotlin)" default> ```kotlin showLineNumbers // login and update attribution and identifier Branch.getAutoInstance(this) .setIdentity("YOUR_USER_ID") { referringParams, error -> referringParams?.let { data -> Adapty.updateAttribution(data, "branch") { error -> if (error != null) { //handle the error } } } } // logout Branch.getAutoInstance(context).logout() ``` </TabItem> <TabItem value="flutter" label="Flutter" default> ```javascript showLineNumbers import 'package:flutter_branch_sdk/flutter_branch_sdk.dart'; FlutterBranchSdk.setIdentity('YOUR_USER_ID'); ``` </TabItem> <TabItem value="unity" label="Unity (C#)" default> ```csharp showLineNumbers Branch.setIdentity("your user id"); ``` </TabItem> <TabItem value="rn" label="React Native (TS)" default> ```typescript showLineNumbers import branch from 'react-native-branch'; branch.setIdentity('YOUR_USER_ID'); ``` </TabItem> </Tabs> 2. `.updateAttribution()` メソッドを使用してアトリビューションデータを保存します。前のステップで Branch のユーザー ID を指定しなかった場合は、ここで `networkUserId` パラメータに渡してください。 <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS (Swift)" default> ```swift showLineNumbers class YourBranchImplementation { func initializeBranch() { // Pass the attribution you receive from the initializing method of Branch iOS SDK to Adapty. Branch.getInstance().initSession(launchOptions: launchOptions) { (data, error) in if let data { // Adapty SDK 4.x Adapty.updateAttribution(data, source: .branch) // Adapty SDK 3.x Adapty.updateAttribution(data, source: "branch") } } } } ``` </TabItem> <TabItem value="kotlin" label="Android (Kotlin)" default> ```kotlin showLineNumbers //everything is in the above snippet for Android ``` </TabItem> <TabItem value="flutter" label="Flutter (Dart)" default> ```javascript showLineNumbers try { await Adapty().setIntegrationIdentifier( key: "branch_id", value: <BRANCH_IDENTITY_ID>, ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` </TabItem> <TabItem value="unity" label="Unity (C#)" default> ```csharp showLineNumbers using AdaptySDK; Branch.initSession(delegate(Dictionary<string, object> parameters, string error) { string attributionString = JsonUtility.ToJson(parameters); Adapty.UpdateAttribution( attributionString, "branch", (error) => { // handle the error }); }); ``` </TabItem> <TabItem value="rn" label="React Native (TS)" default> ```typescript showLineNumbers import { adapty, AttributionSource } from 'react-native-adapty'; import branch from 'react-native-branch'; branch.subscribe({ enComplete: ({ params, }) => { adapty.updateAttribution(params, "branch"); }, }); ``` </TabItem> </Tabs> ## イベント構造 \{#event-structure\} Adapty は、[**Branch Integration ページ**](https://app.adapty.io/integrations/branch)の **Events names** セクションで設定された内容に従って、選択したイベントを Branch に送信します。各イベントは次のような構造になっています: ```json { "branch_key": "key_live_kaFuWw8WvY7n1ss7...", "name": "PURCHASE", "user_data": { "os": "iOS", "developer_identity": "user_12345", "country": "US", "ip": "192.168.100.1", "idfa": "00000000-0000-0000-0000-000000000000", "idfv": "00000000-0000-0000-0000-000000000000", "aaid": "00000000-0000-0000-0000-000000000000" }, "event_data": { "transaction_id": "GPA.3383-4699-1373-07113", "revenue": 9.99, "currency": "USD" }, "custom_data": { "vendor_product_id": "yearly.premium.6999", "original_transaction_id": "GPA.3383-4699-1373-07113", "store": "play_store", "environment": "production" } } ``` 各パラメータの説明: | パラメータ | 型 | 説明 | |:-------------------------------|:-------|:------------------------------------------------------------------------------------------------------------------------| | `branch_key` | String | Branch Key。 | | `name` | String | Branch イベント名(Adapty イベントからマッピングされたもの。例:"PURCHASE")。 | | `user_data` | Object | ユーザー情報。 | | `user_data.os` | String | "Android" または "iOS"。 | | `user_data.developer_identity` | String | ユーザーの Customer User ID。 | | `user_data.country` | String | ユーザーの IP に基づく国コード。 | | `user_data.ip` | String | ユーザーの IP アドレス。 | | `user_data.idfa` | String | **iOS のみ**。広告主向け識別子(ID for Advertisers)。 | | `user_data.idfv` | String | **iOS のみ**。ベンダー向け識別子(ID for Vendors)。 | | `user_data.aaid` | String | **Android のみ**。Google 広告 ID。 | | `event_data` | Object | 標準イベント指標(PURCHASE など該当イベントにのみ含まれます)。 | | `event_data.transaction_id` | String | ストアのトランザクション ID。 | | `event_data.revenue` | Float | 収益額。 | | `event_data.currency` | String | 通貨コード(例:"USD")。 | | `custom_data` | Object | 詳細なイベント属性(利用可能なすべての[イベントフィールド](webhook-event-types-and-fields#for-most-event-types)を含みます)。 | --- # File: facebook-ads --- --- title: "Facebook Ads" description: "Facebook AdsをAdaptyと統合して、効果的なサブスクリプションマーケティングを実現します。" --- Facebook Ads連携を利用すると、Meta Analyticsでアプリの統計情報を簡単に確認できます。AdaptyはMeta Ads Managerにイベントを送信し、サブスクリプションに基づいた類似オーディエンスの作成をサポートすることで、より高いリターンを実現します。これにより、広告がサブスクリプションからどれだけの収益を生み出しているかを正確に把握できます。 AdaptyとFacebook Adsの連携は次のように動作します。Adaptyは、連携で設定されたすべてのサブスクリプションイベントをFacebook Adsに送信します。この連携は、広告キャンペーンの効果を評価するのに役立ちます。 ## 連携のセットアップ \{#set-up-integration\} ### AdaptyをFacebook Adsに接続する \{#connect-adapty-to-facebook-ads\} Facebook Adsと連携してアプリの指標を分析するには、Meta Analyticsとの連携をセットアップします。Meta Ads Managerにイベントを送信することで、更新などのサブスクリプションイベントを基に類似オーディエンスを作成できます。この連携を設定するには、Adapty ダッシュボードの [Integrations > Facebook Ads](https://app.adapty.io/integrations/facebookanalytics) に移動し、必要な認証情報を入力してください。 :::note Facebook Ads連携は、ATTの同意を得たユーザーに対してiOS 14.5以降でのみ動作します。 ::: <img src="/assets/shared/img/fd84ddf-CleanShot_2023-08-15_at_15.45.442x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 1. App IDを確認するには、[App Store Connect](https://appstoreconnect.apple.com/) でアプリのページを開き、**General** セクションの **App Information** ページに移動して、画面左下の **Apple ID** を確認します。 2. [Meta for Developers](https://developers.facebook.com/) プラットフォームでアプリケーションが必要です。アプリにログインして詳細設定を開くと、ヘッダーに **App ID** が表示されます。 <img src="/assets/shared/img/4b326c4-001563-August-23-4tO3JVso.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. Meta Ads Managerでの収益の二重カウントを防ぐため、Meta SDKの設定でクライアントサイドのトラッキングを無効にしてください。この設定は、Meta Developer Consoleの **App Settings > Advanced Settings** にあります。**Log in-app events automatically** を「No」に設定してください。これにより、収益イベントはAdaptyの連携経由でのみトラッキングされます。 インストールや使用状況のイベントをトラッキングするには、コード内でMeta SDKを有効化する必要があります。各プラットフォームのMeta SDKドキュメントで実装の詳細を確認できます: - [iOS SDK](https://developers.facebook.com/docs/ios/getting-started) - [Android SDK](https://developers.facebook.com/docs/android/getting-started) - [Unity SDK](https://developers.facebook.com/docs/unity/getting-started/canvas) <img src="/assets/shared/img/c4eb8eb-001565-August-23-483KKBbC.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> この連携はAndroidアプリでも利用できます。**App Settings** でAndroid SDKの設定を行っている場合は、**Facebook App ID** を設定するだけで十分です。 ### イベントとタグの設定 \{#configure-events-and-tags\} Facebook Ads連携は、Metaを広告キャンペーンに活用し、顧客行動に基づいて最適化している企業向けです。Metaの標準イベントを最適化目的でサポートしています。そのため、Meta Ads連携ではイベント名の変更はできません。Adaptyはお客様の顧客イベントを対応するMetaイベントに正確にマッピングします。 | Adaptyイベント | Meta Adsイベント | | :---------------------------- | :-------------------------- | | Subscription initial purchase | Subscribe | | Subscription renewed | Subscribe | | Subscription cancelled | CancelSubscription | | Trial started | StartTrial | | Trial converted | Subscribe | | Trial cancelled | CancelTrial | | Non subscription purchase | fb_mobile_purchase | | Billing issue detected | billing_issue_detected | | Entered grace period | entered_grace_period | | Auto renew off | auto_renew_off | | Auto renew on | auto_renew_on | | Auto renew off subscription | auto_renew_off_subscription | | Auto renew on subscription | auto_renew_on_subscription | StartTrial、Subscribe、CancelSubscriptionは標準イベントです。 <img src="/assets/shared/img/8a5df9d-CleanShot_2023-07-04_at_12.47.312x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 特定のイベントを有効にするには、必要なものをトグルでオンにするだけです。複数のイベント名が選択された場合、Adaptyはすべての選択されたイベントのデータを1つのAdaptyイベント名にまとめます。 ### アプリをFacebook Adsに接続する \{#connect-your-app-to-facebook-ads\} 上記の手順を完了すると、FacebookはAdaptyからサブスクリプションデータを自動的に受信します。 iOS 14.5でのIDFAの変更を受け、ユーザーの`facebookAnonymousId`をFacebookからリクエストすることをお勧めします。これにより、ユーザーのIDFAが取得できない場合でも連携が継続して機能します。このパラメーターを設定するには、<InlineTooltip tooltip="ユーザー属性設定ガイド">[iOS](setting-user-attributes)、[Android](android-setting-user-attributes)、[React Native](react-native-setting-user-attributes)、[Flutter](flutter-setting-user-attributes)、[Unity](unity-setting-user-attributes)</InlineTooltip> をご参照ください。 <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS (Swift)" default> ```swift showLineNumbers do { try await Adapty.setIntegrationIdentifier( key: "facebook_anonymous_id", value: AppEvents.shared.anonymousID ) } catch { // handle the error } ``` </TabItem> <TabItem value="kotlin" label="Android (Kotlin)" default> ```kotlin showLineNumbers Adapty.setIntegrationIdentifier( "facebook_anonymous_id", AppEventsLogger.getAnonymousAppDeviceGUID(context) ) { error -> if (error != null) { // handle the error } } ``` </TabItem> <TabItem value="rn" label="React Native (TS)" default> ```typescript showLineNumbers try { const anonymousId = await AppEventsLogger.getAnonymousID(); await adapty.setIntegrationIdentifier("facebook_anonymous_id", anonymousId); } catch (error) { // handle `AdaptyError` } ``` </TabItem> <TabItem value="flutter" label="Flutter (Dart)" default> ```text There is no official SDK for Flutter ``` </TabItem> <TabItem value="unity" label="Unity (C#)" default> ```csharp anonymousID is not available in the official SDK https://github.com/facebook/facebook-sdk-for-unity/issues/676 ``` </TabItem> </Tabs> ## イベント構造 \{#event-structure\} AdaptyはGraph API経由でFacebook Ads(Meta)にイベントを送信します。各イベントは次のような構造になっています: ```json { "event": "CUSTOM_APP_EVENTS", "app_user_id": "user_12345", "advertiser_id": "00000000-0000-0000-0000-000000000000", "advertiser_tracking_enabled": 1, "application_tracking_enabled": 1, "custom_events": "[{\"_eventName\":\"Subscribe\",\"_logTime\":1709294400,\"fb_num_items\":1,\"fb_content_type\":\"in_app\",\"fb_content_id\":\"yearly.premium.6999\",\"fb_currency\":\"USD\",\"fb_order_id\":\"GPA.3383...\",\"fb_transaction_id\":\"GPA.3383...\",\"_valueToSum\":9.99}]", "extinfo": "[\"i2\",\"com.example.app\",\"1.0.0\",\"100\",\"17.0.1\",\"iPhone14,3\",\"en_US\",\"GMT+3\",\"\",0,0,0,0,0,0,\"GMT+3\"]", "anon_id": "facebook_anon_id_123" } ``` 各パラメーターの説明: | パラメーター | 型 | 説明 | |:---|:---|:---| | `event` | String | 常に「CUSTOM_APP_EVENTS」。 | | `app_user_id` | String | ユーザーのCustomer User ID。 | | `advertiser_id` | String | IDFA(iOS)またはAdvertising ID(Android)。 | | `advertiser_tracking_enabled` | Integer | トラッキングが有効(ATT承認済み)の場合は`1`、それ以外は`0`。 | | `application_tracking_enabled` | Integer | 常に`1`。 | | `custom_events` | String | イベントオブジェクトのJSON形式の文字列(下記参照)。 | | `extinfo` | String | アプリ・デバイス情報(バージョン、OS、ロケールなど)を含むJSON形式の文字列。 | | `anon_id` | String | Facebook Anonymous ID(利用可能な場合)。 | `custom_events` パラメーターはオブジェクトのJSON配列で、以下の情報を含みます: | パラメーター | 型 | 説明 | |:---|:---|:---| | `_eventName` | String | Meta Adsのイベント名(例:「Subscribe」)。 | | `_logTime` | Long | イベントのタイムスタンプ(秒単位)。 | | `_valueToSum` | Float | 収益金額。 | | `fb_content_id` | String | ストアのプロダクトID。 | | `fb_currency` | String | 通貨コード(例:「USD」)。 | | `fb_order_id` | String | オリジナルトランザクションID。 | | `fb_transaction_id` | String | オリジナルトランザクションID。 | | `fb_content_type` | String | 常に「in_app」。 | | `fb_num_items` | Integer | 購入イベントでは常に1。 | --- # File: singular --- --- title: "Singular" description: "AdaptyとSingularを統合して、マーケティングとサブスクリプションデータを分析します。" --- [Singular](https://www.singular.net/) は主要なMobile Measurement Partner(MMP)プラットフォームの1つで、マーケティングキャンペーンのデータを収集・可視化します。これにより、企業はキャンペーンのパフォーマンスを追跡できます。 Adaptyは、ストアからの[サブスクリプションイベント](events)を一か所で追跡できる完全なデータセットを提供します。Adaptyを使えば、サブスクライバーの行動を簡単に把握し、ユーザーの好みを理解し、ターゲットを絞った効果的なコミュニケーションに活用できます。この連携により、Singularでサブスクリプションイベントを追跡し、キャンペーンが生み出す収益を正確に分析できます。 Adaptyは、連携で設定されたすべてのサブスクリプションイベントをSingularに送信できます。その結果、Singularダッシュボード内でこれらのイベントを追跡できるようになります。この連携は、広告キャンペーンの効果を評価する際に役立ちます。 ## 連携のセットアップ \{#set-up-integration\} ### AdaptyとSingularを接続する \{#connect-adapty-to-singular\} Singularとの連携をセットアップするには、Adapty ダッシュボードの [Integrations > Singular](https://app.adapty.io/integrations/singular) に移動し、トグルをオンにしてフィールドに入力します。 以下の認証情報が利用できます: - **Singular SDK Key**:必須。SingularアプリのプロダクションSDKキー。 - **Singular SDK Key (Sandbox)**:オプション。サンドボックス用SingularアプリのSDKキー。設定しない場合、サンドボックスイベントはSingularに送信されません。 両方のキーは、Singularダッシュボードの **Developer tools -> SDK Keys -> SDK Key(**SDKシークレットではありません**)** から確認できます: <img src="/assets/shared/img/4bc50d1-singular_sdk_key.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 認証情報の下には、AdaptyからSingularに送信できる3グループのイベントがあります。Adaptyが提供するイベントの完全なリストは[こちら](events)でご確認ください。 <img src="/assets/shared/img/e67de0c-singular_events.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Adaptyが提供するデフォルトのイベント名を使用することをお勧めします。ただし、必要に応じてイベント名を変更することも可能です。 Adaptyはサーバー間連携を使用してサブスクリプションイベントをSingularに送信するため、Singularダッシュボードですべてのサブスクリプションイベントを確認し、獲得キャンペーンと紐付けることができます。 :::warning 連携を設定する前に作成されたプロファイルは、Singularにイベントを送信できません。 ::: ### アプリをSingularに接続する \{#connect-your-app-to-singular\} AdaptyとSingularの連携はサーバー間連携です。そのため、アプリケーションに追加のコードを記述する必要はありません。 ## イベント構造 \{#event-structure\} AdaptyはGETリクエストのクエリパラメーターを使用してSingularにイベントを送信します。各イベントの構造は次のとおりです: ```json { "n": "subscription_renewed", "a": "singular_sdk_key_123", "p": "iOS", "i": "com.example.app", "ip": "192.168.100.1", "idfa": "00000000-0000-0000-0000-000000000000", "idfv": "00000000-0000-0000-0000-000000000000", "ve": "17.0.1", "att_authorization_status": 3, "custom_user_id": "user_12345", "utime": 1709294400, "amt": 9.99, "cur": "USD", "purchase_product_id": "yearly.premium.6999", "purchase_transaction_id": "GPA.3383...", "e": "{\"is_revenue_event\":true,\"amt\":9.99,\"cur\":\"USD\",\"purchase_product_id\":\"yearly.premium.6999\",\"purchase_transaction_id\":\"GPA.3383...\"}" } ``` 各パラメーターの説明: | パラメーター | 型 | 説明 | |:---------------------------|:--------|:---------------------------------------------------------| | `n` | String | イベント名(Adaptyイベントからマッピングされたもの)。 | | `a` | String | Singular SDKキー。 | | `p` | String | プラットフォーム("iOS" または "Android")。 | | `i` | String | ストアアプリID(バンドルID)。 | | `ip` | String | ユーザーのIPアドレス。 | | `idfa` | String | **iOSのみ**。広告主向けID(大文字)。 | | `idfv` | String | **iOSのみ**。ベンダー向けID(大文字)。 | | `aifa` | String | **Androidのみ**。Google広告ID(小文字)。 | | `andi` | String | **Androidのみ**。Android ID(小文字)。 | | `asid` | String | **Androidのみ**。アプリセットID(小文字)。 | | `ve` | String | OSバージョン。 | | `att_authorization_status` | Integer | **iOSのみ**。ATTステータス(例:`3` は承認済み)。 | | `custom_user_id` | String | ユーザーのカスタマーユーザーID。 | | `utime` | Long | イベントのUNIXタイムスタンプ(秒単位)。 | | `amt` | Float | 収益金額。 | | `cur` | String | 通貨コード(例:"USD")。 | | `purchase_product_id` | String | ストアのプロダクトID。 | | `purchase_transaction_id` | String | 元のトランザクションID。 | | `e` | String | イベント詳細を含むJSONエンコード文字列(以下参照)。 | `e` パラメーター(カスタムイベントデータ)は、以下を含むJSONエンコード文字列です: | パラメーター | 型 | 説明 | |:--------------------------|:--------|:---------------------------------------| | `is_revenue_event` | Boolean | イベントに収益が含まれる場合は `true`。 | | `amt` | Float | 収益金額。 | | `cur` | String | 通貨コード。 | | `purchase_product_id` | String | ストアのプロダクトID。 | | `purchase_transaction_id` | String | 元のトランザクションID。 | --- # File: tenjin --- --- title: "Tenjin連携" description: "" --- Tenjinは、アプリ開発者やマーケター向けのモバイルアトリビューション・分析プラットフォームです。広告ネットワークやアプリストアのデータを集約し、ROIの分析、コンバージョンのトラッキング、主要なパフォーマンス指標のモニタリングを可能にします。透明性が高く柔軟なアプローチで、ユーザー獲得キャンペーンの計測と最適化を支援します。 [サブスクリプションイベント](events)をTenjinに転送することで、コンバージョンの発生源や最も価値をもたらすキャンペーンを、すべてのチャネル・プラットフォーム・デバイスにわたって正確に把握できます。TenjinのダッシュボードはマーケティングキャンペーンのA/Bテスト向け高度な分析機能を提供します。 TenjinのアトリビューションをAdaptyに転送することで、Adaptyのアナリティクスにコホート分析やコンバージョン分析で活用できる追加フィルタ条件を追加できます。 この連携は2つの方法で機能します: 1. **Tenjinからアトリビューションデータを受け取る** 連携後、AdaptyはTenjinからアトリビューションデータを収集します。この情報はAdapty Dashboardのユーザーのプロファイルページで確認できます。 2. **サブスクリプションイベントをTenjinに送信する** Adatyはリアルタイムで購入イベントをTenjinに送信します。これらのイベントを使って、Tenjinのダッシュボード内で広告キャンペーンの効果を直接評価できます。 | 連携の特性 | 説明 | | -------------------------- | ------------------------------------------------------------ | | スケジュール | リアルタイム | | データの方向 | <p>双方向転送:</p><ul><li> **Adaptyイベント**:AdaptyサーバーからTenjinサーバーへ</li><li> **Tenjinアトリビューション**:Tenjin SDKからAdaptyサーバーへ</li></ul> | | Adaptyの連携ポイント | <ul><li> モバイルアプリコード内のTenjinとAdapty SDK</li><li> Adaptyサーバー</li></ul> | ## 連携のセットアップ \{#set-up-integration\} ### AdaptyをTenjinに接続する \{#connect-adapty-to-tenjin\} 1. Adapty Dashboardの[**Integrations** -> **Tenjin**](https://app.adapty.io/integrations/tenjin)ページを開きます。 2. トグルを有効にして連携をアクティブにします。 <img src="/assets/shared/img/tenjin-toggle.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. [Tenjin Dashboard](https://tenjin.com/)にログインします。 4. ナビゲーションメニューで**Configuration** -> **Apps**に移動します。 <img src="/assets/shared/img/tenjin-apps.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. お使いのプラットフォーム(iOSまたはAndroid)のアプリを選択し、**App and SDK**タブに移動します。 6. **App and SDK**タブで、**SDK Key**列の**Copy**をクリックします。SDKキーがまだない場合は、**Generate SDK Key**ボタンをクリックして作成します。 <img src="/assets/shared/img/tenjin-copy-sdk-key.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 7. Adapty Dashboardに戻り、コピーしたSDKキーを対応するプラットフォームのフィールドに貼り付けます: - iOSアプリの場合:**iOS SDK Key**または**iOS Sandbox SDK Key**フィールドに貼り付けます - Androidアプリの場合:**Android SDK Key**または**Android Sandbox SDK Key**フィールドに貼り付けます :::info Tenjinにはサーバー間連携向けの専用サンドボックスモードはありません。本番環境とサンドボックスイベントの両方に、別のTenjinアプリまたは同じキーを使用してください。 ::: <img src="/assets/shared/img/tenjin-keys.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 8. 両方のプラットフォームにアプリがある場合は、もう一方のプラットフォームについて手順5〜7を繰り返します。 9. (任意)必要に応じて**How the revenue data should be sent**セクションを調整します。設定の詳細については、[連携設定](configuration#integration-settings)を参照してください。 10. **Save**をクリックしてセットアップを完了します。 これでAdaptyはTenjinに購入イベントを送信し、アトリビューションデータを受信します。**Events names**セクションでイベントの共有を調整できます。 ### イベントとタグを設定する \{#configure-events-and-tags\} Tenjinは購入イベントと**Trial started**イベントのみを受け付けます。**Events names**セクションで、トラッキング目標に合わせてTenjinと共有するイベントを選択します。 <img src="/assets/shared/img/tenjin-events.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### アプリをTenjinに接続する \{#connect-your-app-to-tenjin\} `Adapty.updateAttribution()` SDKメソッドを使用してTenjinからアトリビューションデータを取得し、Adaptyに渡します。 <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS (Swift)" default> ```swift showLineNumbers func updateTenjinId() { guard let tenjinId = TenjinSDK.getAnalyticsInstallationId() else { return } do { // Adapty SDK 4.x try await Adapty.setIntegrationIdentifier(.tenjinAnalyticsInstallationId(tenjinId)) // Adapty SDK 3.x try await Adapty.setIntegrationIdentifier( key: "tenjin_analytics_installation_id", value: tenjinId ) } catch { // handle the error } } func updateTenjinAttribution() { let instance = TenjinSDK.getInstance("<YOUR_TENJIN_API_TOKEN>") instance?.getAttributionInfo { info, _ in guard let info else { return } Task { do { // Adapty SDK 4.x try await Adapty.updateAttribution(info, source: .tenjin) // Adapty SDK 3.x try await Adapty.updateAttribution(info, source: "tenjin") } catch { // handle the error } } } } ``` </TabItem> <TabItem value="kotlin" label="Android (Kotlin)" default> ```kotlin showLineNumbers Adapty.setIntegrationIdentifier("tenjin_analytics_installation_id", tenjinSdk.analyticsInstallationId) { error -> if (error != null) { // handle the error } } tenjinSdk.getAttributionInfo { attribution -> if (attribution == null) return@getAttributionInfo Adapty.updateAttribution(attribution, "tenjin") { error -> if (error != null) { // handle the error } } } ``` </TabItem> <TabItem value="java" label="Android (Java)" default> ```java showLineNumbers Adapty.setIntegrationIdentifier("tenjin_analytics_installation_id", tenjinSdk.getAnalyticsInstallationId(), error -> { if (error != null) { // handle the error } }); tenjinSdk.getAttributionInfo(attribution -> { if (attribution == null) return; Adapty.updateAttribution(attribution, "tenjin", error -> { // handle the error }); }); ``` </TabItem> <TabItem value="flutter" label="Flutter (Dart)" default> ```javascript showLineNumbers try { final tenjinId = await TenjinSDK.instance.getAnalyticsInstallationId(); if (tenjinId != null) { await Adapty().setIntegrationIdentifier( key: 'tenjin_analytics_installation_id', value: tenjinId, ); } final attribution = await TenjinSDK.instance.getAttributionInfo(); if (attribution != null) { await Adapty().updateAttribution(attribution, source: 'tenjin'); } } catch (e) { // handle the error } ``` </TabItem> <TabItem value="unity" label="Unity (C#)" default> ```csharp showLineNumbers using AdaptySDK; using System.Linq; BaseTenjin instance = Tenjin.getInstance("<SDK_KEY>"); var tenjinId = instance.GetAnalyticsInstallationId(); Adapty.SetIntegrationIdentifier( "tenjin_analytics_installation_id", tenjinId, (error) => { // handle the error }); instance.GetAttributionInfo((attribution) => { var dynamicAttribution = attribution.ToDictionary( kvp => kvp.Key, kvp => (dynamic)kvp.Value ); Adapty.UpdateAttribution( dynamicAttribution, "tenjin", (error) => { // handle the error }); }); ``` </TabItem> <TabItem value="rn" label="React Native (TS)" default> ```typescript showLineNumbers // ... const posthog = usePostHog() // ... try { await adapty.setIntegrationIdentifier("tenjin_analytics_installation_id", await Tenjin.getAnalyticsInstallationId()); } catch (error) { // handle `AdaptyError` } ``` </TabItem> </Tabs> ## イベント構造 \{#event-structure\} Adatyは[**Tenjin Integration page**](https://app.adapty.io/integrations/tenjin)の**Events names**セクションで設定した選択済みイベントをTenjinに送信します。各イベントの構造は次のとおりです: ```json showLineNumbers title="Json" { "price": 99.0, "locale": "en-US", "country": "ME", "postcut": "false", "currency": "USD", "platform": "ios", "quantity": 1, "bundle_id": "com.adapty.adaptydemoapp", "ip_address": "127.0.0.1", "os_version": "18.1.1", "product_id": "month.premium.99", "app_version": "3.2.0", "sdk_version": "server", "device_model": "iPhone 13 Mini", "advertising_id": "00000000-0000-0000-0000-000000000000", "os_version_release": "18.1.1", "developer_device_id": "00000000-0000-0000-0000-000000000000", "analytics_installation_id": "00000000-0000-0000-0000-000000000000" } ``` 各パラメーターの説明: | **パラメーター** | **型** | **説明** | | ----------------------------- | ---------------- | ------------------------------------------------------------ | | **price** | Float | 購入アイテムの単価(通貨の標準単位。例:USDはドル単位で報告)。 | | **locale** | String | デバイスのロケール。Android:`Locale.getDefault().toString()`、iOS:`[[NSLocale currentLocale] localeIdentifier]`。 | | **country** | String | ISO標準の国コード(例:米国はUS)。 | | **postcut** | String (Boolean) | プラットフォームの手数料差し引き後に購入が送信されたかどうかを示します。trueの場合は1、falseの場合は0。 | | **currency** | String | ISO通貨コード(例:米ドルはUSD)。 | | **platform** | String | デバイスのプラットフォーム(例:ios、android、windows、amazon)。 | | **quantity** | Integer | 購入した数量。 | | **bundle_id** | String | アプリのバンドル識別子(例:`com.example.app`)。 | | **ip_address** | String (IPv4) | ユーザーのIPアドレス。国の検索に使用されます。 | | **os_version** | String | デバイスのOSバージョン。Android:`String.valueOf(Build.VERSION.SDK_INT)`、iOS:`[[UIDevice currentDevice] systemVersion]`。 | | **product_id** | String | 購入したプロダクトの一意識別子。 | | **app_version** | Float, Decimal | アプリのバージョン。Android:`context.getPackageManager().getPackageInfo()`、iOS:`[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"]`。 | | **sdk_version** | String | 使用中のSDKバージョン。常に`server`に設定されます。 | | **device_model** | String | デバイスのモデル。Android:`Build.MODEL`、iOS:`sysctl("hw.machine")`。 | | **advertising_id** | UUID | デバイスの広告ID。Androidでは必須です。iOSでは空またはすべてゼロになることがあります。 | | **os_version_release** | String | OSバージョンのリリース情報。Android:`String.valueOf(Build.VERSION.RELEASE)`、iOS:`[[UIDevice currentDevice] systemVersion]`。 | | **developer_device_id** | UUID | ベンダー識別子(iOSのみ)。 | | **analytics_installation_id** | UUID | アナリティクスインストールID。詳細については、`https://docs.tenjin.com`のドキュメントを参照してください。 | --- # File: amplitude --- --- title: "Amplitude" description: "ユーザー行動をより深く把握するために、AmplitudeとAdaptyを連携しましょう。" --- [Amplitude](https://amplitude.com/) は強力なモバイル解析サービスです。Adaptyと組み合わせることで、イベントをAmplitudeに簡単に送信し、ユーザーの行動を把握して、的確な意思決定を行えます。 Adaptyは、ストアからの[サブスクリプションイベント](events)を一箇所で追跡できる完全なデータセットを提供し、Amplitudeアカウントに送信します。これにより、Amplitude上でユーザーの行動と課金履歴を紐付け、プロダクトの意思決定に役立てることができます。 ### Amplitude 連携のセットアップ方法 \{#how-to-set-up-amplitude-integration\} Adaptyでは、AppleまたはStripeサンドボックス環境、もしくはGoogleテストアカウントからの**本番**イベントと**テスト**イベントに対して、それぞれ個別のフローを設定できます。 - 本番イベントには、AmplitudeダッシュボードのプラットフォームごとのAPIキー(iOS、Android、Stripe各固有のキー)を **Production** フィールドに入力してください。 - テストイベントには、必要に応じて **Sandbox** フィールドを使用してください。 Amplitude連携をセットアップするには: 1. Adapty ダッシュボードで [**Integrations** -> **Amplitude**](https://app.adapty.io/integrations/amplitude) を開きます。 <img src="/assets/shared/img/3b50552-CleanShot_2023-08-15_at_16.47.102x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. **Amplitude integration** をオンに切り替えて有効化します。 3. 連携フィールドに入力します: | フィールド | 説明 | | ------------------------------------------ | ------------------------------------------------------------ | | **Amplitude iOS/ Android/ Stripe API key** | iOS / Android / Stripe用のAmplitude **API Key** をAdaptyに入力します。Amplitudeの **Project settings** から確認できます。詳しくは [Amplitude ドキュメント](https://amplitude.com/docs/apis/authentication) をご覧ください。まず **Sandbox** キーでテストを行い、成功したら **Production** キーに切り替えてください。 | <img src="/assets/shared/img/2297782-CleanShot_2023-08-15_at_16.53.512x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. さらに詳細なカスタマイズのためのオプション設定: | パラメータ | 説明 | | --------------------------------------- | ------------------------------------------------------------ | | **How the revenue data should be sent** | 総収益を送るか、税金と手数料控除後の収益を送るかを選択します。詳細は[ストア手数料と税金](controls-filters-grouping-compare-proceeds#display-gross-or-net-revenue)をご覧ください。 | | **Exclude historical events** | Adapty SDK インストール以前のイベントを除外するか選択します。データの重複を防ぐことができます。たとえば、ユーザーが1月10日にサブスクリプションを開始し、3月6日にAdapty SDKをインストールした場合、Adaptyは3月6日以降のイベントのみを送信します。 | | **Send User Attributes** | 言語設定などのユーザー固有の属性を送信するにはこのオプションを選択します。 | | **Always populate user_id** | Adaptyは自動的に `device_id` を `amplitudeDeviceId` として送信します。`user_id` については、この設定で動作を定義します:<ul><li>**ON**:`amplitudeUserId` または `customer_user_id` が利用できない場合、Adaptyの `profile_id` を送信します。</li><li>**OFF**:いずれのIDも利用できない場合、`user_id` を空のままにします。</li></ul> | 5. 受信したいイベントを選択し、[イベント名をマッピング](amplitude#events-and-tags)します。 6. **Save** をクリックして変更を保存します。 **Save** をクリックすると、AdaptyはAmplitudeへのイベント送信を開始します。 イベントに加えて、Adaptyは[サブスクリプションステータス](subscription-status)とサブスクリプションのプロダクトIDを[Amplitudeユーザープロパティ](https://amplitude.com/docs/data/user-properties-and-events)に送信します。 ### イベントとタグ \{#events-and-tags\} 認証情報の下に、AdaptyからAmplitudeに送信できるイベントが3つのグループに分かれて表示されています。必要なものをオンにするだけで使えます。Adaptyが提供するイベントの全リストは[こちら](events)で確認できます。 <img src="/assets/shared/img/da67694-CleanShot_2023-08-15_at_16.52.352x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Adaptyが提供するデフォルトのイベント名を使用することをお勧めします。ただし、必要に応じてイベント名を変更することも可能です。Adaptyはサーバー間連携を使ってAmplitudeにサブスクリプションイベントを送信するため、Amplitudeダッシュボードですべてのサブスクリプションイベントを確認できます。 ### SDK の設定 \{#sdk-configuration\} `setIntegrationIdentifier()` メソッドを使用して `amplitude_device_id` パラメータを設定します。これは連携のセットアップに必須です。 ユーザー登録がある場合は、`amplitude_user_id` も合わせて渡すことができます。 --- no_index: true --- import Callout from '../../../components/Callout.astro'; <Callout type="note"> サードパーティのユーザーIDをCustomer User IDとして使用する場合、`activate()`の際に渡さないでください。サードパーティSDKがまだIDを生成していない可能性があります。代わりに、まず`activate()`をCUIDなしで呼び出し、次に`setIntegrationIdentifier()`、そして`identify()`にCUIDを渡して呼び出してください。 </Callout> <Tabs groupId="current-os" queryString> <TabItem value="Swift" label="iOS (Swift)" default> **amplitudeDeviceId の設定** ```swift showLineNumbers do { try await Adapty.setIntegrationIdentifier( key: "amplitude_device_id", value: Amplitude.instance().deviceId ) } catch { // handle the error } ``` **amplitudeUserId の設定** ```swift showLineNumbers do { try await Adapty.setIntegrationIdentifier( key: "amplitude_user_id", value: "YOUR_AMPLITUDE_USER_ID" ) } catch { // handle the error } ``` </TabItem> <TabItem value="kotlin" label="Android (Kotlin)" default> **amplitudeDeviceId の設定** ```kotlin showLineNumbers //for Amplitude maintenance SDK (obsolete) val amplitude = Amplitude.getInstance() val amplitudeDeviceId = amplitude.getDeviceId() val amplitudeUserId = amplitude.getUserId() //for actual Amplitude Kotlin SDK val amplitude = Amplitude( Configuration( apiKey = AMPLITUDE_API_KEY, context = applicationContext ) ) val amplitudeDeviceId = amplitude.store.deviceId // Adapty.setIntegrationIdentifier("amplitude_device_id", amplitudeDeviceId) { error -> if (error != null) { // handle the error } } ``` **amplitudeUserId の設定** ```kotlin showLineNumbers //for Amplitude maintenance SDK (obsolete) val amplitude = Amplitude.getInstance() val amplitudeDeviceId = amplitude.getDeviceId() val amplitudeUserId = amplitude.getUserId() //for actual Amplitude Kotlin SDK val amplitude = Amplitude( Configuration( apiKey = AMPLITUDE_API_KEY, context = applicationContext ) ) val amplitudeUserId = amplitude.store.userId // Adapty.setIntegrationIdentifier("amplitude_user_id", amplitudeUserId) { error -> if (error != null) { // handle the error } } ``` </TabItem> <TabItem value="Flutter" label="Flutter (Dart)" default> **amplitudeDeviceId の設定** ```javascript showLineNumbers final Amplitude amplitude = Amplitude.getInstance(instanceName: "YOUR_INSTANCE_NAME"); try { await Adapty().setIntegrationIdentifier( key: "amplitude_device_id", value: amplitude.getDeviceId(), ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` **amplitudeUserId の設定** ```javascript showLineNumbers final Amplitude amplitude = Amplitude.getInstance(instanceName: "YOUR_INSTANCE_NAME"); try { await Adapty().setIntegrationIdentifier( key: "amplitude_user_id", value: "YOUR_AMPLITUDE_USER_ID", ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` </TabItem> <TabItem value="Unity" label="Unity (C#)" default> **amplitudeDeviceId の設定** ```csharp showLineNumbers using AdaptySDK; Adapty.SetIntegrationIdentifier( "amplitude_device_id", amplitude.getDeviceId(), (error) => { // handle the error }); ``` **amplitudeUserId の設定** ```csharp showLineNumbers using AdaptySDK; Adapty.SetIntegrationIdentifier( "amplitude_user_id", "YOUR_AMPLITUDE_USER_ID", (error) => { // handle the error }); ``` </TabItem> <TabItem value="rn" label="React Native (TS)" default> **amplitudeDeviceId の設定** ```typescript showLineNumbers try { await adapty.setIntegrationIdentifier("amplitude_device_id", deviceId); } catch (error) { // handle `AdaptyError` } ``` **amplitudeUserId の設定** ```typescript showLineNumbers try { await adapty.setIntegrationIdentifier("amplitude_user_id", userId); } catch (error) { // handle `AdaptyError` } ``` </TabItem> </Tabs> ## Amplitude イベント構造 \{#amplitude-event-structure\} AdaptyはHTTP API v2を介してAmplitudeにイベントを送信します。各イベントの構造は次のとおりです: ```json { "api_key": "your_amplitude_api_key", "events": [ { "partner_id": "adapty", "event_type": "subscription_renewed", "time": 1709294400000, "insert_id": "123e4567-e89b-12d3-a456-426614174000", "user_id": "user_12345", "device_id": "device_12345", "platform": "iOS", "os_name": "iOS", "productId": "yearly.premium.6999", "revenue": 9.99, "event_properties": { "vendor_product_id": "yearly.premium.6999", "original_transaction_id": "GPA.3383...", "currency": "USD", "environment": "Production", "store": "app_store" }, "user_properties": { "subscription_state": "subscribed", "subscription_product": "yearly.premium.6999" } } ] } ``` 各フィールドの説明: | パラメータ | 型 | 説明 | |:----------------------------|:-------|:---------------------------------------------------------------------| | `api_key` | String | Amplitude API キー。 | | `events` | Array | イベントオブジェクトのリスト(Adaptyは1件ずつ送信します)。 | | `events[].partner_id` | String | 常に "adapty"。 | | `events[].event_type` | String | イベント名(Adaptyイベントからマッピングされたもの)。 | | `events[].time` | Long | イベントのタイムスタンプ(ミリ秒)。 | | `events[].insert_id` | String | 一意のイベントID(UUID)。 | | `events[].user_id` | String | Amplitude ユーザーIDまたはカスタマーユーザーID。 | | `events[].device_id` | String | Amplitude デバイスID。 | | `events[].platform` | String | プラットフォーム(例:「iOS」、「Android」)。 | | `events[].os_name` | String | OS名。 | | `events[].productId` | String | ストアのプロダクトID。 | | `events[].revenue` | Float | 収益額。 | | `events[].event_properties` | Object | 詳細なイベント属性(利用可能な[イベントフィールド](webhook-event-types-and-fields#for-most-event-types)をすべて含む)。 | | `events[].user_properties` | Object | サブスクリプションステータスなどのユーザー属性。 | --- # File: appmetrica --- --- title: "AppMetrica" description: "AppMetricaをAdaptyと統合して、サブスクリプション分析を深化させましょう。" --- [AppMetrica](https://appmetrica.yandex.com/about) は、ユーザーの行動を追跡し、モバイルアプリのパフォーマンスをリアルタイムで分析できる無料の解析ツールです。AppMetricaをAdaptyと統合することで、サブスクリプション指標やユーザーエンゲージメントについてより深い洞察を得られます。 ## AppMetrica連携の設定方法 \{#how-to-set-up-appmetrica-integration\} AppMetrica連携の設定は、主に2つのステップで構成されます。 1. Adapty ダッシュボードで連携を設定する 2. アプリのコードに連携を実装する ### ダッシュボードの設定 \{#dashboard-configuration\} AppMetrica連携を設定するには: 1. [AppMetricaアプリ一覧](https://appmetrica.yandex.ru/application/list)を開く 2. トラッキングしたいアプリを選択する 3. **Settings > Main** に移動し、**Application ID** と **Post API key** をコピーする <img src="/assets/shared/img/appmetrica.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. Adapty ダッシュボードの [Integrations > AppMetrica](https://app.adapty.io/integrations/appmetrica) に移動する 5. AppMetricaの認証情報を貼り付ける <img src="/assets/shared/img/appmetrica_creds.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### イベントとタグ \{#events-and-tags\} Adaptyでは、3つのグループのイベントをAppMetricaに送信できます。アプリのパフォーマンスを追跡するために必要なイベントを有効化してください。利用可能なイベントの完全なリストは、[イベントドキュメント](events)をご参照ください。 :::note AppMetricaは4時間ごとにイベントを同期するため、ダッシュボードにイベントが表示されるまで遅延が生じる場合があります。 ::: <img src="/assets/shared/img/6ed2d88-CleanShot_2023-08-18_at_14.59.042x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> :::tip 一貫性を保つためにAdaptyのデフォルトイベント名の使用を推奨しますが、既存のアナリティクス設定に合わせてカスタマイズすることも可能です。 ::: ### 収益の設定 \{#revenue-settings\} デフォルトでは、Adaptyは収益データをイベントのプロパティとして送信し、AppMetricaのEventsレポートに表示されます。この収益データの計算と表示方法を設定できます。 - **収益の計算方法**: 財務レポートのニーズに合わせて収益値の計算方法を選択します: - **総収益(Gross revenue)**: 控除前の総収益を表示します。顧客が支払う全額の追跡に役立ちます - **ストア手数料控除後の収益(Proceeds after store commission)**: App Store/Play Storeの手数料を差し引いた収益を表示します。実際の収益の追跡に役立ちます - **ストア手数料・税金控除後の収益(Proceeds after store commission and taxes)**: ストア手数料と適用される税金の両方を差し引いた純収益を表示します。最も正確な収益の把握ができます - **ユーザーの通貨で報告(Report user's currency)**: 有効にすると、売上がユーザーのローカル通貨で報告され、地域別の収益分析がしやすくなります。無効にすると、異なる市場間での一貫したレポートのためにすべての売上がUSDに変換されます。 - **収益イベントを送信(Send revenue events)**: このオプションを有効にすると、収益データがEventsレポートだけでなく、AppMetricaの[アプリ内・広告収益](https://appmetrica.yandex.com/docs/en/mobile-reports/revenue-report)レポートにも表示されます。収益の重複を避けるため、他の場所からすでに収益を送信していないことを確認してください。 - **過去のイベントを除外(Exclude historical events)**: 有効にすると、ユーザーがAdapty SDKを含むアプリをインストールする前に発生したイベントは送信されません。Adaptyを統合する前からアナリティクスにイベントを送信していた場合のデータ重複を防ぐのに役立ちます。 <img src="/assets/shared/img/appmetrica_revenue.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### SDKの設定 \{#sdk-configuration\} アプリでAppMetrica連携を有効にするには、2つの識別子を設定する必要があります。 1. `appmetrica_device_id`: 基本的な連携に必要 2. `appmetrica_profile_id`: 任意ですが、アプリにユーザー登録機能がある場合は推奨 これらの値を設定するには `setIntegrationIdentifier()` メソッドを使用します。各プラットフォームでの実装方法は以下のとおりです。 --- no_index: true --- import Callout from '../../../components/Callout.astro'; <Callout type="note"> サードパーティのユーザーIDをCustomer User IDとして使用する場合、`activate()`の際に渡さないでください。サードパーティSDKがまだIDを生成していない可能性があります。代わりに、まず`activate()`をCUIDなしで呼び出し、次に`setIntegrationIdentifier()`、そして`identify()`にCUIDを渡して呼び出してください。 </Callout> <Tabs groupId="current-os" queryString> <TabItem value="Swift" label="iOS (Swift)" default> **appmetrica_device_idの設定** ```swift showLineNumbers AppMetrica.requestStartupIdentifiers(on: nil) { ids, error in if let error { // handle AppMetrica error return } guard let deviceIDHash = ids?[.deviceIDHashKey] as? String else { // handle AppMetrica error return } Task { do { try await Adapty.setIntegrationIdentifier( key: "appmetrica_device_id", value: deviceIDHash ) } catch { // handle the error } } } ``` **appmetrica_profile_idの設定** ```swift showLineNumbers do { try await Adapty.setIntegrationIdentifier( key: "appmetrica_profile_id", value: "YOUR_APPMETRICA_PROFILE_ID" ) } catch { // handle the error } ``` </TabItem> <TabItem value="kotlin" label="Android (Kotlin)" default> **appmetrica_device_idの設定** ```kotlin showLineNumbers val startupParamsCallback = object: StartupParamsCallback { override fun onReceive(result: StartupParamsCallback.Result?) { val deviceIdHash = result?.deviceIdHash ?: return Adapty.setIntegrationIdentifier("appmetrica_device_id", deviceIdHash) { error -> if (error != null) { // handle the error } } } override fun onRequestError( reason: StartupParamsCallback.Reason, result: StartupParamsCallback.Result? ) { //handle the error } } AppMetrica.requestStartupParams(context, startupParamsCallback, listOf(StartupParamsCallback.APPMETRICA_DEVICE_ID_HASH)) ``` **appmetrica_profile_idの設定** ```kotlin showLineNumbers val startupParamsCallback = object: StartupParamsCallback { override fun onReceive(result: StartupParamsCallback.Result?) { val deviceIdHash = result?.deviceIdHash ?: return Adapty.setIntegrationIdentifier("appmetrica_device_id", deviceIdHash) { error -> if (error != null) { // handle the error } } Adapty.setIntegrationIdentifier("appmetrica_profile_id", "YOUR_ADAPTY_CUSTOMER_USER_ID") { error -> if (error != null) { // handle the error } } } override fun onRequestError( reason: StartupParamsCallback.Reason, result: StartupParamsCallback.Result? ) { //handle the error } } AppMetrica.requestStartupParams(context, startupParamsCallback, listOf(StartupParamsCallback.APPMETRICA_DEVICE_ID_HASH)) ``` </TabItem> <TabItem value="Flutter" label="Flutter (Dart)" default> **appmetrica_device_idの設定** ```javascript showLineNumbers final startupParams = await AppMetrica.requestStartupParams([AppMetricaStartupParams.deviceIdHashKey]); final deviceIdHash = startupParams.result?.deviceIdHash; if (deviceIdHash != null) { try { await Adapty().setIntegrationIdentifier( key: "appmetrica_device_id", value: deviceIdHash, ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } } ``` **appmetrica_profile_idの設定** ```javascript showLineNumbers try { await Adapty().setIntegrationIdentifier( key: "appmetrica_profile_id", value: "YOUR_APPMETRICA_PROFILE_ID", ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` </TabItem> <TabItem value="Unity" label="Unity (C#)" default> **appmetrica_device_idの設定** ```csharp showLineNumbers using AdaptySDK; using Io.AppMetrica; AppMetrica.RequestStartupParams( (result, errorReason) => { string deviceIdHash = result.DeviceIdHash; if (deviceIdHash != null) { Adapty.SetIntegrationIdentifier( "appmetrica_device_id", deviceIdHash, (error) => { // handle the error }); } }, new List<string>() { StartupParamsKey.AppMetricaDeviceIDHash } ); ``` **appmetrica_profile_idの設定** ```csharp showLineNumbers Adapty.SetIntegrationIdentifier( "appmetrica_profile_id", "YOUR_APPMETRICA_PROFILE_ID", (error) => { // handle the error }); ``` </TabItem> <TabItem value="RN" label="React Native (TS)" default> **appmetrica_device_idの設定** ```typescript showLineNumbers // ... const startupParamsCallback = async ( params?: StartupParams, reason?: StartupParamsReason ) => { const deviceIdHash = params?.deviceIdHash if (deviceIdHash) { try { await adapty.setIntegrationIdentifier("appmetrica_device_id", deviceIdHash); } catch (error) { // handle `AdaptyError` } } } AppMetrica.requestStartupParams(startupParamsCallback, [DEVICE_ID_HASH_KEY]) ``` **appmetrica_profile_idの設定** ```typescript showLineNumbers try { await adapty.setIntegrationIdentifier("appmetrica_profile_id", 'YOUR_ADAPTY_CUSTOMER_USER_ID'); } catch (error) { // handle `AdaptyError` } ``` </TabItem> </Tabs> ## AppMetricaのイベント構造 \{#appmetrica-event-structure\} AdaptyはPOSTリクエストを通じてAppMetricaにイベントを送信し、パラメーターはクエリパラメーターとして渡されます。Adaptyの各イベントに対して、AppMetricaは最大**2つの個別リクエスト**を受け取ります。 1. **プロファイルイベント**(常に送信): イベントのメタデータを含む 2. **収益イベント**(任意): Adapty ダッシュボードで「収益イベントを送信」オプションが有効な場合に収益データを含む ### プロファイルイベントリクエスト \{#profile-event-request\} 送信先: `https://api.appmetrica.yandex.ru/logs/v1/import/events` クエリパラメーター付きのURLの例: ``` POST https://api.appmetrica.yandex.ru/logs/v1/import/events?post_api_key=your_key&application_id=your_app_id&event_name=subscription_renewed&event_timestamp=1709294400&event_json=%7B%22vendor_product_id%22%3A%22yearly.premium%22...%7D&os_name=ios&ios_ifa=00000000-0000-0000-0000-000000000000&ios_ifv=12345678-1234-1234-1234-123456789012&profile_id=user_12345&session_type=foreground ``` クエリパラメーター: | パラメーター | 型 | 説明 | |:-----------------------|:-------|:----------------------------------------------------------------------------------------------------------------------------------------------------| | `post_api_key` | String | AppMetricaのPost APIキー | | `application_id` | String | AppMetricaのアプリケーションID | | `event_name` | String | イベント名(Adaptyのイベントからマッピング) | | `event_timestamp` | Long | イベントのUNIXタイムスタンプ(秒単位)。7日以上前の場合は直近7日以内に制限されます | | `event_json` | String | 利用可能な[イベントフィールド](webhook-event-types-and-fields#for-most-event-types)をすべて含むURLエンコードされたJSON文字列。nullでないフィールドのみ含まれます | | `os_name` | String | "ios" または "android" | | `profile_id` | String | AppMetricaのプロファイルID(設定されている場合)、それ以外はカスタマーユーザーID(利用可能な場合) | | `appmetrica_device_id` | String | AppMetricaのデバイスIDハッシュ。`profile_id` が利用できない場合のみ送信されます | | `session_type` | String | 常に "foreground" | | `ios_ifa` | String | **iOSのみ**。広告主向けID(IDFA) | | `ios_ifv` | String | **iOSのみ**。ベンダー向けID(IDFV) | | `google_aid` | String | **Androidのみ**。Google広告ID | ### 収益イベントリクエスト(任意) \{#revenue-event-request-optional\} 送信先: `https://api.appmetrica.yandex.ru/logs/v1/import/revenue` このリクエストは、Adapty ダッシュボードの連携設定で「収益イベントを送信」オプションが有効な場合にのみ送信されます。 クエリパラメーター付きのURLの例: ``` POST https://api.appmetrica.yandex.ru/logs/v1/import/revenue?post_api_key=your_key&application_id=your_app_id&revenue_event_type=subscription_renewed&price=9.99¤cy=USD&product_id=yearly.premium&quantity=1&transaction_id=GPA.3383...&payload=%7B%22vendor_product_id%22%3A%22yearly.premium%22...%7D&os_name=ios&ios_ifa=00000000-0000-0000-0000-000000000000&profile_id=user_12345&session_type=foreground ``` クエリパラメーター: | パラメーター | 型 | 説明 | |:---------------------|:--------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `post_api_key` | String | AppMetricaのPost APIキー | | `application_id` | String | AppMetricaのアプリケーションID | | `revenue_event_type` | String | 収益イベントのタイプ(例:"subscription_renewed"、"refund"、"intro_started")。[AppMetricaのイベントマッピング](#revenue-event-type-mapping)をご参照ください | | `price` | Float | 収益額(収益計算設定に基づく) | | `currency` | String | 通貨コード(例:"USD") | | `product_id` | String | ストアのプロダクトID | | `quantity` | Integer | 常に1 | | `transaction_id` | String | ストアのトランザクションID | | `payload` | String | イベントの詳細を含むURLエンコードされたJSON文字列。30KBを超える場合は、最も重要なデータを保持するために重要度の低いフィールドから順に削除されて自動的にトリミングされます | | `os_name` | String | "ios" または "android" | | `profile_id` | String | AppMetricaのプロファイルID(設定されている場合)、それ以外はカスタマーユーザーID(利用可能な場合) | | `appmetrica_device_id` | String | AppMetricaのデバイスIDハッシュ。`profile_id` が利用できない場合のみ送信されます | | `session_type` | String | 常に "foreground" | | `ios_ifa` | String | **iOSのみ**。広告主向けID(IDFA) | | `ios_ifv` | String | **iOSのみ**。ベンダー向けID(IDFV) | | `google_aid` | String | **Androidのみ**。Google広告ID | --- # File: firebase-and-google-analytics --- --- title: "Firebase and Google Analytics" description: "AdaptyとFirebase・Google Analyticsを統合して、より深いインサイトを得ましょう。" --- Google AnalyticsやFirebaseといったGoogleのプロダクトを利用している場合、この記事で説明する統合を使ってAdaptyのイベントで分析データを拡充できます。イベントはGoogle Analytics経由でFirebaseに送信され、これらのサービスのどちらでも利用できます。 この機能により、ユーザーの行動と支払い履歴をFirebase上で紐づけ、プロダクトに関する意思決定をデータに基づいて行えるようになります。 ## Firebase統合のセットアップ方法 \{#how-to-set-up-firebase-integration\} ### 1\. Firebaseをセットアップする \{#1-set-up-firebase\} まず、FirebaseとGoogle Analyticsの統合を有効にする必要があります。Firebase Consoleの **Integrations** タブから設定できます。 <img src="/assets/shared/img/14b6d84-CleanShot_2023-08-18_at_20.37.462x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### 2\. Adaptyと統合する \{#2-integrate-with-adapty\} 次に、AdaptyがイベントとユーザープロパティをFirebase App IDとGoogle Analytics API Secretを使って送信できるよう設定します。これらのパラメーターはFirebase ConsoleおよびGoogle Analytics Data Streamsタブでそれぞれ確認できます。 <img src="/assets/shared/img/14d8224-CleanShot_2023-08-21_at_12.14.182x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 次に、[Google Analytics](https://analytics.google.com/analytics/web/#/)の管理設定にあるData Streamsセクションで、アプリのStream詳細ページにアクセスします。 <img src="/assets/shared/img/b26ae6a-CleanShot_2023-08-21_at_12.28.482x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> **Additional settings** から **Measurement Protocol API secrets** ページに進み、**API Secret** が存在しない場合は新規作成して値をコピーします。 <img src="/assets/shared/img/7404bde-CleanShot_2023-08-21_at_12.33.242x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> <img src="/assets/shared/img/0266112-CleanShot_2023-08-21_at_12.34.442x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 次に、Adapty ダッシュボードで統合の設定を行います。iOS、Android、Stripeプラットフォームそれぞれに対して、Firebase App IDとGoogle Analytics API Secretを入力してください。 :::note Stripe統合を使用している場合は、専用の[ガイド](stripe#current-limitations)に記載された制限事項を確認してください。これらの制限はFirebase統合にも適用されます。 ::: <img src="/assets/shared/img/4eaae3f-CleanShot_2023-08-21_at_12.35.312x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## SDK設定 \{#sdk-configuration\} :::important 統合を機能させるには、まずアプリにFirebaseを追加してください: - [iOS](https://firebase.google.com/docs/ios/setup) - [Android](https://firebase.google.com/docs/android/setup) - [React Native](https://firebase.google.com/docs/web/setup) - [Flutter](https://firebase.google.com/docs/flutter/setup) - [Unity](https://firebase.google.com/docs/unity/setup) ::: 次に、ユーザーをFirebaseと紐づけるためにAdapty SDKを設定する必要があります。各ユーザーに対して、`firebase_app_instance_id`をAdaptyに送信してください。以下に、Firebase SDKとAdapty SDKを統合するコード例を示します。 <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS (Swift)" default> ```swift showLineNumbers FirebaseApp.configure() if let appInstanceId = Analytics.appInstanceID() { do { try await Adapty.setIntegrationIdentifier( key: "firebase_app_instance_id", value: appInstanceId ) } catch { // handle the error } } ``` </TabItem> <TabItem value="kotlin" label="Android (Kotlin)" default> ```kotlin showLineNumbers //after Adapty.activate() FirebaseAnalytics.getInstance(context).appInstanceId.addOnSuccessListener { appInstanceId -> Adapty.setIntegrationIdentifier("firebase_app_instance_id", appInstanceId) { error -> if (error != null) { // handle the error } } } ``` </TabItem> <TabItem value="java" label="Java" default> ```java showLineNumbers //after Adapty.activate() FirebaseAnalytics.getInstance(context).getAppInstanceId().addOnSuccessListener(appInstanceId -> { Adapty.setIntegrationIdentifier("firebase_app_instance_id", appInstanceId, error -> { if (error != null) { // handle the error } }); }); ``` </TabItem> <TabItem value="flutter" label="Flutter (Dart)" default> ```javascript showLineNumbers final appInstanceId = await FirebaseAnalytics.instance.appInstanceId; try { await Adapty().setIntegrationIdentifier( key: "firebase_app_instance_id", value: appInstanceId, ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` </TabItem> <TabItem value="unity" label="Unity (C#)" default> ```csharp showLineNumbers using AdaptySDK; // We suppose FirebaseAnalytics Unity Plugin is already installed Firebase.Analytics .FirebaseAnalytics .GetAnalyticsInstanceIdAsync() .ContinueWithOnMainThread((task) => { if (!task.IsCompletedSuccessfully) { // handle error return; } var firebaseId = task.Result var builder = new Adapty.ProfileParameters.Builder(); Adapty.SetIntegrationIdentifier( "firebase_app_instance_id", firebaseId, (error) => { // handle the error }); }); ``` </TabItem> <TabItem value="rn" label="React Native (TS)" default> ```typescript showLineNumbers try { const appInstanceId = await analytics().getAppInstanceId(); await adapty.setIntegrationIdentifier("firebase_app_instance_id", appInstanceId); } catch (error) { // handle `AdaptyError` } ``` </TabItem> </Tabs> ## イベントとユーザープロパティの送信 \{#sending-events-and-user-properties\} 次に、FirebaseとGoogle Analyticsで受け取るイベントを選択します。 <img src="/assets/shared/img/7923397-set_up_events_names.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 一部のイベントには「Purchase」などの固有の名前が付いており、その他は通常のAdaptyイベントとなっています。この違いは[Google Analyticsのイベントタイプ](https://developers.google.com/analytics/devguides/collection/protocol/ga4/reference/events)に由来します。現在サポートされているイベントは[Refund](https://developers.google.com/analytics/devguides/collection/protocol/ga4/reference/events#refund)と[Purchase](https://developers.google.com/analytics/devguides/collection/protocol/ga4/reference/events#purchase)で、それ以外はカスタムイベントです。イベント名がGoogle Analyticsで[サポートされているか](https://developers.google.com/analytics/devguides/collection/protocol/ga4/sending-events?client_type=firebase#limitations)確認してください。 また、Adapty ダッシュボードからユーザープロパティの送信設定も行えます。 <img src="/assets/shared/img/e053006-CleanShot_2023-08-21_at_12.50.162x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> これにより、イベントにはAdaptyによって`subscription_state`と`subscription_product_id`が付加されます。ただし、この機能をGoogle Analyticsで[有効化](https://support.google.com/analytics/answer/14240153?hl=en)する必要があります。**User properties** を分析で使用するには、Firebase Consoleの **Custom Definitions** でカスタムディメンションを作成し、**User scope** を選択してから名前と説明を設定してください。 <img src="/assets/shared/img/1962ef1-CleanShot_2023-08-21_at_12.48.222x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> <img src="/assets/shared/img/2425cc0-CleanShot_2023-08-21_at_12.52.532x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ユーザープロパティ名が`subscription_state`と`subscription_product_id`であることを確認してください。それ以外の名前ではサブスクリプションステータスのデータを送信できません。 以上で設定は完了です!Googleからの新しいインサイトをお待ちください。 ## トラブルシューティング \{#troubleshooting\} ### データの不一致 \{#data-discrepancy\} AdaptyとFirebaseの間でデータに差異がある場合、Adapty SDKを含むアプリバージョンを使用していないユーザーが存在することが原因として考えられます。データの一貫性を確保するには、ユーザーにAdapty SDKを含むバージョンへのアップデートを促すことをお勧めします。 また、サンドボックスイベントはデフォルトでFirebaseに送信され、これを無効にすることはできません。本番環境のイベントが少なくサンドボックスのイベントが多い場合、AdaptyのアナリティクスとFirebaseの数値に顕著な差が生じることがあります。 ### AdaptyではイベントがDeliveredと表示されているがFirebaseに表示されない \{#events-are-shown-as-delivered-in-adapty-but-not-available-in-firebase\} Adaptyからイベントが送信されてからGoogle Analyticsダッシュボードに表示されるまで、タイムラグが生じます。最新のイベントをリアルタイムで確認するには、Google AnalyticsアカウントのRealtime Dashboardを確認することをお勧めします。 --- # File: mixpanel --- --- title: "Mixpanel" description: "Adapty と Mixpanel を連携して、強力なサブスクリプション分析を実現しましょう。" --- [Mixpanel](https://mixpanel.com/home/) は強力なプロダクト分析サービスです。イベントドリブンのトラッキングソリューションにより、プロダクトチームはさまざまなプラットフォームにおけるユーザー獲得・コンバージョン・リテンション戦略について深い知見を得ることができます。 この連携により、Adapty のすべてのイベントを Mixpanel に送信できます。その結果、サブスクリプションビジネスとユーザー行動をより包括的に把握できるようになります。Adapty はストアからの[サブスクリプションイベント](events)を一か所で追跡できる完全なデータセットを提供します。Adapty を使えば、サブスクライバーの行動を簡単に把握し、好みを理解し、その情報をもとにターゲットを絞った効果的なコミュニケーションを行えます。 ## Mixpanel 連携の設定方法 \{#how-to-set-up-mixpanel-integration\} 1. Adapty ダッシュボードで [Integrations -> Mixpanel](https://app.adapty.io/integrations/mixpanel) ページを開きます。 2. トグルを有効にして **Mixpanel Token** を入力します。すべてのプラットフォームに対してトークンを指定するか、特定のプラットフォームからのみデータを受け取りたい場合はプラットフォームを絞り込むこともできます。 3. **Mixpanel Data Residency** を Mixpanel プロジェクトに合わせて設定します。このフィールドは必須で、デフォルトは **US** です。`api.mixpanel.com` エンドポイントを使用する場合は **US** を、`api-eu.mixpanel.com` を使用する場合は **Europe** を選択してください。 :::warning Mixpanel プロジェクトが EU データレジデンシーを使用している場合、**Mixpanel Data Residency** を **Europe** に設定する必要があります。EU プロジェクトから US エンドポイントに送信されたイベントは Mixpanel によって破棄されます。 ::: <img src="/assets/shared/img/mixpanel.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### Mixpanel トークンの確認方法 \{#finding-your-mixpanel-token\} **Mixpanel Token** を取得するには: 1. [Mixpanel ダッシュボード](https://mixpanel.com/settings/project/)にログインします。 2. **Settings** を開き、**Organization Settings** を選択します。 <img src="/assets/shared/img/mixpanel-settings.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. 左サイドバーから **Projects** に移動し、プロジェクトを選択します。 <img src="/assets/shared/img/mixpanel-project-id.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## 連携の仕組み \{#how-the-integration-works\} Adapty は、ユーザー ID や売上などの関連イベントプロパティを[Mixpanel ネイティブプロパティ](https://docs.mixpanel.com/docs/data-structure/user-profiles)に自動的にマッピングします。これにより、サブスクリプション関連イベントの正確なトラッキングとレポーティングが実現されます。 また、Adapty はユーザーごとに売上データを蓄積し、`subscription state` や `subscription product ID` などの[ユーザープロファイルプロパティ](https://docs.mixpanel.com/docs/data-structure/user-profiles)を更新します。イベントを受信すると、Mixpanel は対応するフィールドをリアルタイムで更新します。 ## イベントとタグ \{#events-and-tags\} 認証情報の下には、Adapty から Mixpanel に送信できるイベントが 3 つのグループに分かれています。必要なものをオンにするだけです。Adapty が提供するイベントの完全な一覧は[こちら](events)をご確認ください。 <img src="/assets/shared/img/mixpanel-events.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Adapty が提供するデフォルトのイベント名を使用することをお勧めします。ただし、必要に応じてイベント名を変更することも可能です。 ## SDK の設定 \{#sdk-configuration\} `.setIntegrationIdentifier()` メソッドを使用して `mixpanelUserId` を設定します。設定しない場合、Adapty はユーザー ID(`customerUserId`)を使用し、それが null の場合は Adapty ID を使用します。アプリから Mixpanel にデータを送信する際に使用するユーザー ID と、Adapty に送信するユーザー ID が同じであることを確認してください。 --- no_index: true --- import Callout from '../../../components/Callout.astro'; <Callout type="note"> サードパーティのユーザーIDをCustomer User IDとして使用する場合、`activate()`の際に渡さないでください。サードパーティSDKがまだIDを生成していない可能性があります。代わりに、まず`activate()`をCUIDなしで呼び出し、次に`setIntegrationIdentifier()`、そして`identify()`にCUIDを渡して呼び出してください。 </Callout> <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS (Swift)" default> ```swift showLineNumbers do { try await Adapty.setIntegrationIdentifier( key: "mixpanel_user_id", value: Mixpanel.mainInstance().distinctId ) } catch { // handle the error } ``` </TabItem> <TabItem value="swift-callback" label="iOS (Swift-Callback)" default> ```swift showLineNumbers let builder = AdaptyProfileParameters.Builder() .with(mixpanelUserId: Mixpanel.mainInstance().distinctId) Adapty.updateProfile(params: builder.build()) ``` </TabItem> <TabItem value="kotlin" label="Android (Kotlin)" default> ```kotlin showLineNumbers Adapty.setIntegrationIdentifier("mixpanel_user_id", mixpanelAPI.distinctId) { error -> if (error != null) { // handle the error } } ``` </TabItem> <TabItem value="flutter" label="Flutter (Dart)" default> ```javascript showLineNumbers final mixpanel = await Mixpanel.init("Your Token", trackAutomaticEvents: true); final distinctId = await mixpanel.getDistinctId(); try { await Adapty().setIntegrationIdentifier( key: "mixpanel_user_id", value: distinctId, ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` </TabItem> <TabItem value="unity" label="Unity (C#)" default> ```csharp showLineNumbers using AdaptySDK; var distinctId = Mixpanel.DistinctId; if (distinctId != null) { Adapty.SetIntegrationIdentifier( "mixpanel_user_id", distinctId, (error) => { // handle the error }); } ``` </TabItem> <TabItem value="rn" label="React Native (TS)" default> ```typescript showLineNumbers // If you already have a shared Mixpanel instance in your app, use that instance instead. const trackAutomaticEvents = true; const mixpanel = new Mixpanel('YOUR_PROJECT_TOKEN', trackAutomaticEvents); await mixpanel.init(); // This is Mixpanel's current distinct_id (auto-generated, or set via mixpanel.identify(...)) const mixpanelUserId = await mixpanel.getDistinctId(); try { await adapty.setIntegrationIdentifier("mixpanel_user_id", mixpanelUserId); } catch (error) { // handle `AdaptyError` } ``` </TabItem> </Tabs> ## Mixpanel イベントの構造 \{#mixpanel-event-structure\} Adapty は `track` メソッドを使用して Mixpanel にイベントを送信します。イベントプロパティの構造は次のとおりです: ```json { "event": "subscription_renewed", "properties": { "ip": 0, "time": 1709294400, "$insert_id": "123e4567-e89b-12d3-a456-426614174000", "vendor_product_id": "yearly.premium.6999", "original_transaction_id": "GPA.3383...", "currency": "USD", "environment": "Production", "store": "app_store", "purchase_date": "2024-03-01T12:00:00.000000+0000" } } ``` 各パラメータの説明: | パラメータ | 型 | 説明 | |:-------------------------------------|:--------|:--------------------------------------------------| | `event` | String | イベント名(Adapty イベントからマッピング)。 | | `properties` | Object | イベントプロパティ。 | | `properties.ip` | Integer | IP アドレス(サーバー間通信では 0 として送信)。 | | `properties.time` | Long | イベントの UNIX タイムスタンプ(秒単位)。 | | `properties.$insert_id` | String | 重複排除用のユニークイベント ID(UUID)。 | | `properties.vendor_product_id` | String | ストアのプロダクト ID。 | | `properties.original_transaction_id` | String | 元のトランザクション ID。 | | `properties.currency` | String | 通貨コード。 | | `properties.store` | String | ストア名(例:「app_store」)。 | | `properties.environment` | String | 環境(「Sandbox」または「Production」)。 | ### ユーザープロファイルの更新 \{#user-profile-updates\} Adapty は `people_set` を使用して、以下のプロパティで Mixpanel ユーザープロファイルも更新します: | パラメータ | 型 | 説明 | |:--------------------------|:-------|:------------------------------------------------------| | `subscription_state` | String | 現在のサブスクリプション状態(例:「subscribed」)。 | | `subscription_product_id` | String | アクティブなサブスクリプションプロダクトの ID。 | --- # File: posthog --- --- title: "PostHog" description: "" --- PostHog は、ユーザー行動のトラッキング、プロダクト利用状況の可視化、リテンション分析などのツールを提供するアナリティクスプラットフォームです。イベントトラッキング、ユーザーフロー、フィーチャーフラグといった機能を備え、プロダクトをより深く理解して改善するために設計されています。 PostHog と Adapty を連携することで、トライアル開始・更新・解約といったサブスクリプション関連イベントをシームレスにトラッキングできます。これらのイベントを PostHog に送信することで、サブスクリプションの変化がユーザー行動に与える影響を分析したり、ペイウォールのパフォーマンスを評価したり、マネタイズ戦略に関するより深いインサイトを得たりできます — すべて既存のアナリティクスワークフロー内で完結します。 ## 連携の特性 \{#integration-characteristics\} | 連携の特性 | 説明 | | -------------------------- | ------------------------------------------------------------ | | スケジュール | リアルタイム。イベントが PostHog ダッシュボードにすぐ表示されない場合があります。 | | データの方向 | Adapty のイベントは Adapty サーバーから PostHog サーバーへ送信されます。 | | Adapty の連携ポイント | <ul><li>モバイルアプリのコード内の PostHog と Adapty SDK</li><li>Adapty サーバー</li></ul> | ## PostHog イベントの構造 \{#posthog-event-structure\} Adapty は、[PostHog 連携ページ](https://app.adapty.io/integrations/posthog)の **Events names** セクションで設定されたイベントを PostHog に送信します。各イベントの構造は以下のとおりです: ```json showLineNumbers { "distinct_id": "john.doe@example.com", "timestamp": "2025-01-08T11:06:12+00:00", "event": "subscription_started", "properties": { "$set": { "email": "user@example.com", "first_name": "John", "last_name": "Doe", "birthday": "1990-01-01", "gender": "male", "os": "iOS" }, "timezone": "America/New_York", "ip_address": "10.168.1.1", "*": "{{other_event_properties}}" } } ``` 各パラメーターの説明: | **パラメーター** | **型** | **説明** | | --------------- | -------------------- | ------------------------------------------------------------ | | **distinct_id** | String | ユーザーの一意識別子(例:`profile.posthog_distinct_user_id`、`customer_user_id`、または `profile_id`)。 | | **timestamp** | ISO 8601 日時 | イベントの日時。 | | **event** | String | [PostHog 設定](https://app.adapty.io/integrations/posthog)の Events names セクションで定義したイベント名。 | | **properties** | Object | [properties.$set](posthog#propertiesset-parameters) と [イベント固有のプロパティ](messaging#event-properties)をすべて含みます。各プロパティはオプションであり、値がない場合は PostHog に送信されません。 | ### properties.$set パラメーター \{#propertiesset-parameters\} `properties.$set` オブジェクトの各パラメーターはオプションであり、値がない場合は PostHog に送信されません。 | **パラメーター** | **型** | **説明** | | --------------- | -------------------- | ------------------------------------------------------------ | | **email** | String | ユーザーのメールアドレス。 | | **first_name** | String | ユーザーの名。 | | **last_name** | String | ユーザーの姓。 | | **birthday** | String (Date) | ユーザーの生年月日。 | | **gender** | String | ユーザーの性別。 | | **os** | String | ユーザーのデバイスのOS。 | ## PostHog 連携の設定 \{#setting-up-posthog-integration\} 1. Adapty ダッシュボードで [Integrations -> PostHog](https://app.adapty.io/integrations/posthog) ページを開き、トグルを有効にします。 <img src="/assets/shared/img/posthog-on.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. [PostHog ダッシュボード](https://posthog.com/)にログインします。 3. **Settings -> Project** に移動します。 <img src="/assets/shared/img/posthog-settings.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **Project** ウィンドウで下にスクロールして **Project ID** セクションを表示し、**Project API key** をコピーします。 5. APIキーを Adapty ダッシュボードの **Project API key** フィールドに貼り付けます。PostHog にはサーバー間連携専用のサンドボックスモードはありません。 6. **PostHog Deployment** を選択します: | オプション | 説明 | | ------ | ------------------------------------------------------------ | | us/eu | PostHog がホストするデフォルトのデプロイメント。 | | Custom | セルフホスト環境向け。**PostHog Instance URL** フィールドにインスタンスのURLを入力します。 | 7. (任意)セルフホストの PostHog デプロイメントを使用している場合は、**PostHog Instance URL** フィールドにデプロイメントのアドレスを入力します。 8. (任意)**Reporting Proceeds**、**Exclude Historical Events**、**Report User's Currency**、**Send Trial Price** などの設定を調整します。これらのオプションの詳細は [Integration settings](configuration#integration-settings) を参照してください。 9. (任意)**Events names** セクションで PostHog に送信するイベントをカスタマイズすることもできます。不要なイベントを無効にしたり、名前を変更したりできます。 10. **Save** をクリックして設定を確定します。 ## SDK の設定 \{#sdk-configuration\} PostHog からアトリビューションデータを受け取るには、以下のように `distinctId` の値を Adapty に渡してください: --- no_index: true --- import Callout from '../../../components/Callout.astro'; <Callout type="note"> サードパーティのユーザーIDをCustomer User IDとして使用する場合、`activate()`の際に渡さないでください。サードパーティSDKがまだIDを生成していない可能性があります。代わりに、まず`activate()`をCUIDなしで呼び出し、次に`setIntegrationIdentifier()`、そして`identify()`にCUIDを渡して呼び出してください。 </Callout> <Tabs groupId="current-os" queryString> <TabItem value="swift" label="Swift" default> ```swift showLineNumbers do { let distinctId = PostHogSDK.shared.getDistinctId() try await Adapty.setIntegrationIdentifier( key: "posthog_distinct_user_id", value: distinctId ) } catch { // handle the error } ``` </TabItem> <TabItem value="kotlin" label="Kotlin" default> ```kotlin showLineNumbers Adapty.setIntegrationIdentifier("posthog_distinct_user_id", PostHog.distinctId()) { error -> if (error != null) { // handle the error } ``` </TabItem> <TabItem value="java" label="Java" default> ```java showLineNumbers Adapty.setIntegrationIdentifier("posthog_distinct_user_id", PostHog.distinctId(), error -> { if (error != null) { // handle the error } }); ``` </TabItem> <TabItem value="flutter" label="Flutter" default> ```javascript showLineNumbers try { final distinctId = await Posthog().getDistinctId(); await Adapty().setIntegrationIdentifier( key: "posthog_distinct_user_id", value: distinctId, ); } catch (e) { // handle the error } ``` </TabItem> <TabItem value="unity" label="Unity" default> Unity 向けの公式 PostHog SDK はありません。 </TabItem> <TabItem value="rn" label="React Native (TS)" default> ```typescript showLineNumbers // ... const posthog = usePostHog(); // ... try { await adapty.setIntegrationIdentifier("posthog_distinct_user_id", posthog.getDistinctId()); } catch (error) { // handle `AdaptyError` } ``` </TabItem> </Tabs> Adapty は PostHog へのイベント送信とアトリビューションの受信を行えるようになりました。 --- # File: splitmetrics --- --- title: "SplitMetrics Acquire" description: "サブスクリプションの A/B テストと最適化のために SplitMetrics と Adapty を使用する。" --- [SplitMetrics Acquire](https://splitmetrics.com/acquire/) との連携により、Apple Search Ads でのサブスクリプション収益を正確に把握できます。また、数か月にわたってユーザーをトラッキングし、広告が長期的にどれだけ収益をもたらすかを確認できます。 さらに、Adapty は [サブスクリプションイベント](events) を SplitMetrics Acquire に送信するため、Apple Search Ads のアトリビューションをもとにカスタムダッシュボードや自動化を構築できます。 ASA から必要なアトリビューションデータはすでに直接取得しているため、Adapty 側にアトリビューションデータが追加されることはありません。 ## SplitMetrics Acquire 連携のセットアップ方法 \{#how-to-set-up-splitmetrics-acquire-integration\} SplitMetrics Acquire を連携するには、[Integrations > SplitMetrics Acquire](https://app.adapty.io/integrations/splitmetrics) に移動して認証情報を設定してください。 <img src="/assets/shared/img/8255349-CleanShot_2023-08-14_at_17.39.422x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> SplitMetrics Acquire のアカウントを開き、いずれかの MMP ロゴにカーソルを合わせて **Settings** ボタンをクリックします。ダイアログの項目 **5** に表示されている Client ID をコピーし、Adapty の **Client ID** フィールドに貼り付けてください。 <img src="/assets/shared/img/4d0b2b6-Adapty.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> <img src="/assets/shared/img/4f8d0b8-AdaptyGuide.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 連携を使用するには Apple App ID の設定も必要です。App ID を確認するには、App Store Connect でアプリのページを開き、**General** セクションの **App Information** ページに移動して、画面左下の **Apple ID** を確認してください。 <img src="/assets/shared/img/61578ee-CleanShot_2022-04-20_at_17.55.03.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## イベントとタグ \{#events-and-tags\} 認証情報の下に、Adapty から SplitMetrics Acquire に送信できる 3 つのイベントグループがあります。必要なものをオンにするだけです。Adapty が提供するイベントの全一覧は[こちら](events)をご確認ください。 <img src="/assets/shared/img/1b0c777-CleanShot_2023-08-11_at_14.56.362x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Adapty が提供するデフォルトのイベント名を使用することをおすすめします。ただし、必要に応じてイベント名を変更することも可能です。Adapty はサーバー間連携を使用してサブスクリプションイベントを SplitMetrics Acquire に送信するため、SplitMetrics ダッシュボードですべてのサブスクリプションイベントを確認できます。 ## SDK の設定 \{#sdk-configuration\} SDK 側での設定は不要ですが、精度向上のために `customerUserId` を Adapty に送信することをおすすめします。 :::warning [Apple Search Ads](apple-search-ads) を Adapty で設定し、[認証情報をアップロード](https://app.adapty.io/settings/apple-search-ads)していることを確認してください。これらがない場合、SplitMetrics Acquire は機能しません。 ::: ## トラブルシューティング \{#troubleshooting\} 正しく設定しているにもかかわらず SplitMetrics Acquire との連携が機能しない場合: - [App Settings -> Apple Search Ads タブ](https://app.adapty.io/settings/apple-search-ads) で **Receive Apple Search Ads attribution in Adapty** トグルが有効になっていること、Adapty で [Apple Search Ads](apple-search-ads) が設定されていること、および[認証情報がアップロード](https://app.adapty.io/settings/apple-search-ads)されていることを確認してください。これらがない場合、SplitMetrics は機能しません。 - プロファイルにオーガニックではない ASA アトリビューションが設定されていることを確認してください。詳細なオーガニックでない ASA アトリビューションを持つプロファイルのみ、イベントが Adapty に配信されます。 ## SplitMetrics Acquire のイベント構造 \{#splitmetrics-acquire-event-structure\} Adapty はクエリパラメーターを使用した GET リクエストで SplitMetrics Acquire にイベントを送信します。各イベントの構造は次のとおりです: ```json { "source": "Apple Search Ads", "app_id": "123456789", "name": "subscription_renewed", "type": "subscription_renewed", "revenue": 9.99, "currency": "USD", "tap_time": "2024-03-01 12:00:00", "open_time": "2024-03-01 12:05:00", "event_time": "2024-03-02 12:00:00", "adaccount_id": "123456", "campaign_id": "123456789", "adgroup_id": "123456789", "keyword_id": "123456789", "creative_set_id": "123456789", "Ad_id": "123456789", "country_or_region": "US", "conversion_type": "Download", "user_id": "user_12345", "att_status": "3", "device_type": "iphone", "app_version": "1.2.3", "sdk_version": "2.10.0", "ios_version": "17.2", "event_value": "{\"vendor_product_id\":\"yearly.premium.6999\",\"original_transaction_id\":\"GPA.3383...\"}", "event_id": "123e4567-e89b-12d3-a456-426614174000" } ``` 各パラメーターの説明: | パラメーター | 型 | 説明 | |:--------------------|:-------|:---------------------------------------------------------------------------------------------------------------| | `source` | String | 常に "Apple Search Ads"。 | | `app_id` | String | Apple App ID。 | | `name` | String | イベント名(Adapty イベントからマッピング)。 | | `type` | String | イベントタイプ(`name` と同じ)。 | | `revenue` | Float | 収益金額。 | | `currency` | String | 通貨コード。 | | `tap_time` | String | 広告タップの日時。 | | `open_time` | String | アプリを開いた(インストールした)日時。 | | `event_time` | String | イベントの日時。 | | `adaccount_id` | String | ASA 組織 ID。 | | `campaign_id` | String | ASA キャンペーン ID。 | | `adgroup_id` | String | ASA 広告グループ ID。 | | `keyword_id` | String | ASA キーワード ID。 | | `creative_set_id` | String | ASA クリエイティブセット ID。 | | `Ad_id` | String | ASA 広告 ID。 | | `country_or_region` | String | ストアの国または地域。 | | `conversion_type` | String | コンバージョンタイプ(例: "Download")。 | | `user_id` | String | カスタマーユーザー ID または Adapty プロファイル ID。 | | `att_status` | String | トラッキング使用状況ステータス(0〜3)。 | | `device_type` | String | デバイスタイプ(例: "iphone"、"ipad")。 | | `app_version` | String | アプリケーションバージョン。 | | `sdk_version` | String | Adapty SDK バージョン。 | | `ios_version` | String | iOS バージョン。 | | `event_value` | String | 利用可能なすべての[イベント詳細](webhook-event-types-and-fields#for-most-event-types)を含む JSON 文字列。 | | `event_id` | String | 一意のイベント ID(UUID)。 | --- # File: braze --- --- title: "Braze" description: "シームレスなカスタマーエンゲージメントとプッシュ通知のために、BrazeとAdaptyを統合します。" --- トップクラスのカスタマーエンゲージメントソリューションのひとつである [Braze](https://www.braze.com/) は、プッシュ通知、メール、SMS、アプリ内メッセージングなど幅広いツールを提供しています。AdaptyとBrazeを統合することで、すべてのサブスクリプションイベントを一箇所で確認でき、それらのイベントをもとに自動コミュニケーションをトリガーできます。 Adaptyは、すべてのストアからの[サブスクリプションイベント](events)を一元管理できる完全なデータセットを提供しており、Brazeのユーザープロファイルの更新に活用できます。Adaptyを使えば、サブスクライバーの行動を把握し、好みを把握して、ターゲットを絞った効果的なコミュニケーションに役立てることができます。この統合により、Brazeダッシュボードでサブスクリプションイベントを追跡し、[獲得キャンペーン](https://www.braze.com/product/journey-orchestration)と紐付けることが可能になります。 Adaptyはサブスクリプションイベントやユーザープロパティ、購入情報をBrazeに送信するため、以下に説明する簡単な統合を行うだけで、Brazeのプッシュ通知を使った顧客向けターゲットコミュニケーションを構築できます。 ## Braze統合のセットアップ方法 \{#how-to-set-up-braze-integration\} Brazeを統合するには、[Integrations → Braze](https://app.adapty.io/integrations/braze) に移動してトグルをオンにし、各フィールドを入力してください。 統合の最初のステップは、BrazeとAdaptyのプロファイルを接続するために必要な認証情報を提供することです。統合を正しく動作させるには、**REST API Key**、**Braze Instance ID**、そしてiOSとAndroidの**App ID**が必要です: <img src="/assets/shared/img/5f1e62c-adapty_braze.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 1. **REST API Key** は **Braze Dashboard** → **Settings** → **API Keys** で作成できます。作成時にキーに `users.track` 権限が付与されていることを確認してください: <img src="/assets/shared/img/b5fdf16-adapty_braze_create_api_key.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> <img src="/assets/shared/img/1e5b4b8-adapty_braze_api_key_users_track.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. **Braze Instance ID** を取得するには、BrazeダッシュボードのURLを確認し、インスタンスIDが記載されている [Braze Docs](https://www.braze.com/docs/api/basics/#endpoints) のセクションを参照してください。US-03、EU-01などの地域形式になっています。 3. iOSおよびAndroidのApp IDは、Braze Dashboard → Settings → API Keys でも確認できます。こちらからコピーしてください: <img src="/assets/shared/img/1e6d21b-adapty_braze_app_ids.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## イベント、ユーザー属性、購入 \{#events-user-attributes-and-purchases\} 認証情報の下には、AdaptyからBrazeに送信できるイベントが3つのグループで表示されています。必要なものをオンにするだけです。Brazeへの送信に合わせてイベント名を変更することもできます。Adaptyが提供するイベントの完全なリストは[こちら](events)で確認できます: <img src="/assets/shared/img/702e628-adapty_braze_events_names.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Adaptyはサブスクリプションイベントとユーザー属性をサーバー間統合でBrazeに送信するため、Brazeダッシュボードで確認してキャンペーンを設定できます。 トライアル転換や更新など収益が発生するイベントについては、Adaptyはその情報を購入としてBrazeに送信します。 Brazeに送信されるイベントプロパティの完全な仕様は[こちら](messaging#event-properties)をご覧ください。 :::note 便利なユーザー属性 AdaptyはBraze統合のためにデフォルトでいくつかのユーザー属性を送信します。ニーズに最適なものを判断するために、以下のリストを参照してください。 ::: | ユーザー属性 | 型 | 値 | |--------------|----|-----| | `adapty_customer_user_id` | String | お客様が定義したユーザーの一意識別子の値を含みます。Adaptyの[ダッシュボード](profiles-crm)とBrazeの両方で確認できます。 | | `adapty_profile_id` | String | Adaptyのユーザープロファイルの一意識別子(Adapty User Profile ID)の値を含みます。Adaptyの[ダッシュボード](profiles-crm)で確認できます。 | | `environment` | String | <p>ユーザーがサンドボックス環境または本番環境のどちらで操作しているかを示します。</p><p></p><p>値は `Sandbox` または `Production` のいずれかです。</p> | | `store` | String | <p>購入に使用したストアの名前を含みます。</p><p></p><p>設定可能な値:</p><p>`app_store` または `play_store`</p> | | `vendor_product_id` | String | <p>Apple/GoogleストアのプロダクトIDの値を含みます。</p><p></p><p>例:org.locals.12345</p> | | `subscription_expires_at` | String | <p>最新のサブスクリプションの有効期限を含みます。</p><p></p><p>値のフォーマット:</p><p>YYYY-MM-DDTHH:mm:ss.SSS+TZ</p><p>例:2023-02-15T17:22:03.000+0000</p> | | `active_subscription` | String | 購入・更新イベント時に `true`、サブスクリプションが期限切れの場合は `false` に設定されます。 | | `period_type` | String | <p>購入または更新の最新の期間タイプを示します。</p><p></p><p>設定可能な値:</p><p>トライアル期間の場合は `trial`、それ以外は `normal`</p> | すべてのfloat値はintに丸められます。文字列はそのまま維持されます。 定義済みのタグリストに加えて、タグを使って[カスタム属性](segments#custom-attributes)を送信することも可能です。これにより、タグに含めるデータの種類の柔軟性が高まり、プロダクトやサービスに関連する特定の情報の追跡に役立ちます。すべてのカスタムユーザー属性は、ユーザーが[統合ページ](https://app.adapty.io/integrations/braze)の **Send user attributes** チェックボックスをオンにすることで、自動的にBrazeに送信されます。 ## SDK設定 \{#sdk-configuration\} AdaptyとBrazeのユーザープロファイルを紐付けるには、Braze SDKをAdaptyと同じカスタマーユーザーIDで設定するか、`.changeUser()` メソッドを使用する必要があります: <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS (Swift)" default> ```swift showLineNumbers let braze = Braze(configuration: configuration) braze.changeUser(userId: "adapty_customer_user_id") ``` </TabItem> <TabItem value="kotlin" label="Android (Kotlin)" default> ```kotlin showLineNumbers Braze.getInstance(context).changeUser("adapty_customer_user_id") ``` </TabItem> </Tabs> --- # File: onesignal --- --- title: "OneSignal" description: "Adapty と OneSignal を連携してプッシュ通知ベースのエンゲージメントを向上させましょう。" --- [OneSignal](https://onesignal.com/) は、プッシュ通知・メール・SMS・アプリ内メッセージングを提供する主要なカスタマーエンゲージメントプラットフォームです。Adapty と OneSignal を連携することで、すべてのサブスクリプションイベントを一か所で確認でき、それらのイベントをトリガーとした自動コミュニケーションを設定できます。 Adapty を使えば、複数のストアにわたる[サブスクリプションイベント](events)を追跡し、ユーザー行動を分析して、よりターゲットを絞ったコミュニケーションに活用できます。この連携により、OneSignal ダッシュボード内でサブスクリプションイベントを監視し、[獲得キャンペーン](https://documentation.onesignal.com/docs/en/automated-messages)にマッピングすることが可能です。 Adapty はサブスクリプションイベントに基づいて OneSignal のタグを更新するため、最小限の設定でパーソナライズされたプッシュ通知を配信できます。 **連携の特性** | 連携の特性 | 説明 | | :------------------------- | :----------------------------------------------------------- | | スケジュール | リアルタイム更新 | | データの方向 | 一方向:Adapty から OneSignal サーバーへ | | Adapty の連携ポイント | <ul><li>モバイルアプリのコード内の OneSignal と Adapty SDK</li><li>Adapty サーバー</li></ul>| ## OneSignal 連携の設定 \{#setting-up-one-signal-integration\} 連携を設定するには: 1. Adapty ダッシュボードの [Integrations → OneSignal](https://app.adapty.io/integrations/onesignal) を開きます。 <img src="/assets/shared/img/onesignal-on.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. 連携トグルを有効にします。 3. **OneSignal App ID** を入力します。 OneSignal との連携を設定するには、Adapty ダッシュボードの [Integrations -> OneSignal](https://app.adapty.io/integrations/onesignal) に移動し、トグルをオンにして連携の認証情報を設定してください。 ## OneSignal App ID の取得 \{#retrieving-your-onesignal-app-id\} **OneSignal App ID** は [OneSignal ダッシュボード](https://dashboard.onesignal.com/login)で確認できます: 1. **Settings** → **Keys & IDs** に移動します。 <img src="/assets/shared/img/onesignal-dashboard.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. **OneSignal App ID** をコピーして、Adapty ダッシュボードの **App ID** フィールドに貼り付けます。 <img src="/assets/shared/img/onesignal-id.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> OneSignal ID の詳細については、[こちらのドキュメント](https://documentation.onesignal.com/docs/en/keys-and-ids)をご覧ください。 ### イベントの設定 \{#configuring-events\} Adapty では、3 つのグループのイベントを OneSignal に送信できます。Adapty ダッシュボードで必要なものをトグルでオンにしてください。利用可能なイベントの完全なリストと詳細な説明は[こちら](events)で確認できます。 <img src="/assets/shared/img/onesignal.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Adapty はサーバー間連携を使用してサブスクリプションイベントを OneSignal に送信するため、OneSignal ですべてのサブスクリプション関連のアクティビティを追跡できます。 :::warning 2023 年 4 月 17 日より、OneSignal の無料プランではこの連携がサポートされなくなりました。**Growth**、**Professional**、およびそれ以上のプランでのみ利用可能です。詳細は [OneSignal Pricing](https://onesignal.com/pricing) をご覧ください。 ::: ## カスタムタグ \{#custom-tags\} この連携では、Adapty ユーザーのさまざまなプロパティをタグとして更新・付与し、OneSignal に送信します。以下のタグ一覧から、ニーズに合ったものをご確認ください。 :::warning OneSignal にはタグの上限があります。これには Adapty が生成するタグと OneSignal に既存するタグの両方が含まれます。上限を超えると、イベント送信時にエラーが発生する可能性があります。 ::: | タグ | 型 | 説明 | |---|----|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `adapty_customer_user_id` | String | アプリ内でのユーザーの一意の識別子。システム、Adapty、OneSignal 全体で一貫している必要があります。 | | `adapty_profile_id` | String | Adapty のユーザープロファイル ID。[Adapty ダッシュボード](profiles-crm)で確認できます。 | | `environment` | String | ユーザーの現在の環境を示す `Sandbox` または `Production`。 | | `store` | String | プロダクトが購入されたストア。選択肢:**app_store**、**play_store**、**stripe**、または[カスタムストア](custom-store)の名前。 | | `vendor_product_id` | String | アプリストアにおけるプロダクト ID(例:`org.locals.12345`)。 | | `subscription_expires_at` | String | 最新のサブスクリプションの有効期限(`YYYY-MM-DDTHH:MM:SS+0000`、例:`2023-02-10T17:22:03.000000+0000`)。 | | `last_event_type` | String | [Adapty イベントリスト](events)における最新のイベントタイプ。<br/> 注意点:<br/>- **Subscription expired** イベントの場合、Adapty は `last_event_type` プロパティを `subscription_cancelled` として送信します。<br/>- **Trial renew canceled** の場合は `auto_renew_off` として送信します。<br/>- **Subscription renew canceled** の場合は `auto_renew_off_subscription` として送信します。 | | `purchase_date` | String | 最後のトランザクション日時(`YYYY-MM-DDTHH:MM:SS+0000`、例:`2023-02-10T17:22:03.000000+0000`)。 | | `active_subscription` | String | ユーザーがアクティブなサブスクリプションを持つ場合は `true`、サブスクリプションが終了している場合は `false`。 | | `period_type` | String | 購入または更新における最新の期間タイプを示します。使用可能な値:試用期間の場合は `trial`、それ以外のすべての場合は `normal`。 | すべての float 値は整数に丸められます。文字列はそのまま変更されません。 事前定義されたタグに加えて、[カスタム属性](segments#custom-attributes)をタグとして送信することで、含めるデータの柔軟性を高めることができます。これは、プロダクトやサービスに関連する特定の詳細を追跡するのに役立ちます。 カスタムユーザー属性は、[連携ページ](https://app.adapty.io/integrations/onesignal)の **Send user attributes** チェックボックスが有効になっている場合、自動的に OneSignal に送信されます。チェックを外した場合、Adapty はちょうど 10 個のタグを送信します。チェックを入れると 10 個を超えるタグを送信でき、より多くのデータをキャプチャできます。 ## SDK の設定 \{#sdk-configuration\} OneSignal と Adapty を連携する方法は 2 つあります: 1. **レガシー(v5 以前):** `playerId` を使用します([OneSignal SDK v5](https://github.com/OneSignal/OneSignal-iOS-SDK/releases/tag/5.0.0) では非推奨)。 2. **現行(v5 以降):** `subscriptionId` を使用します。 :::warning Adapty に `playerId`(OneSignal SDK v5 以前の場合)または `subscriptionId`(OneSignal SDK v5 以降の場合)を必ず送信してください。これを行わないと、OneSignal のタグが更新されず、連携が正しく機能しません。 ::: <Tabs groupId="current-version" queryString> <TabItem value="v5+" label="OneSignal SDK v5+ (current)" default> <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS (Swift)" default> ```swift showLineNumbers // SubscriptionID OneSignal.Notifications.requestPermission({ accepted in Task { // Adapty SDK 4.x try await Adapty.setIntegrationIdentifier(.oneSignalSubscriptionId(OneSignal.User.pushSubscription.id)) // Adapty SDK 3.x try await Adapty.setIntegrationIdentifier( key: "one_signal_subscription_id", value: OneSignal.User.pushSubscription.id ) } }, fallbackToSettings: true) ``` </TabItem> <TabItem value="kotlin" label="Android (Kotlin)" default> ```kotlin showLineNumbers // SubscriptionID val oneSignalSubscriptionObserver = object: IPushSubscriptionObserver { override fun onPushSubscriptionChange(state: PushSubscriptionChangedState) { Adapty.setIntegrationIdentifier("one_signal_subscription_id", state.current.id) { error -> if (error != null) { // handle the error } } } } ``` </TabItem> <TabItem value="java" label="(Android) Java" default> ```java showLineNumbers // SubscriptionID IPushSubscriptionObserver oneSignalSubscriptionObserver = state -> { Adapty.setIntegrationIdentifier("one_signal_subscription_id", state.getCurrent().getId(), error -> { if (error != null) { // handle the error } }); }; ``` </TabItem> <TabItem value="flutter" label="Flutter (Dart)" default> ```javascript showLineNumbers // 1. Since OneSignal.User.pushSubscription.id may return null if called too early, // OneSignal suggests to listen for the updates: OneSignal.User.pushSubscription.addObserver((state) { if (state.current.optedIn) { // now you can try to retrieve subscriptionId } }); // 2. Then you can push subscriptionId to Adapty: final subscriptionId = OneSignal.User.pushSubscription.id; if (subscriptionId != null) { await Adapty().setIntegrationIdentifier(key: "one_signal_subscription_id", value: subscriptionId); } ``` </TabItem> <TabItem value="unity" label="Unity (C#)" default> ```csharp showLineNumbers using AdaptySDK; using OneSignalSDK; var pushUserId = OneSignal.Default.PushSubscriptionState.userId; Adapty.SetIntegrationIdentifier( "one_signal_player_id", pushUserId, (error) => { // handle the error }); ``` </TabItem> <TabItem value="rn" label="React Native (TS)" default> ```typescript showLineNumbers OneSignal.User.pushSubscription.addEventListener('change', (subscription) => { const subscriptionId = subscription.current.id; if (subscriptionId) { adapty.setIntegrationIdentifier("one_signal_subscription_id", subscriptionId); } }); ``` </TabItem> </Tabs> </TabItem> <TabItem value="pre-v5" label="OneSignal SDK v. up to 4.x (legacy)" default> <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS (Swift)" default> ```swift showLineNumbers // PlayerID // in your OSSubscriptionObserver implementation func onOSSubscriptionChanged(_ stateChanges: OSSubscriptionStateChanges) { if let playerId = stateChanges.to.userId { Task { // Adapty SDK 4.x try await Adapty.setIntegrationIdentifier(.oneSignalPlayerId(playerId)) // Adapty SDK 3.x try await Adapty.setIntegrationIdentifier( key: "one_signal_player_id", value: playerId ) } } } ``` </TabItem> <TabItem value="kotlin" label="Android (Kotlin)" default> ```kotlin showLineNumbers // PlayerID val osSubscriptionObserver = OSSubscriptionObserver { stateChanges -> stateChanges?.to?.userId?.let { playerId -> Adapty.setIntegrationIdentifier("one_signal_player_id", playerId) { error -> if (error != null) { // handle the error } } } } ``` </TabItem> <TabItem value="java" label="Java" default> ```java showLineNumbers // PlayerID OSSubscriptionObserver osSubscriptionObserver = stateChanges -> { OSSubscriptionState to = stateChanges != null ? stateChanges.getTo() : null; String playerId = to != null ? to.getUserId() : null; if (playerId != null) { Adapty.setIntegrationIdentifier("one_signal_player_id", playerId, error -> { if (error != null) { // handle the error } }); } }; ``` </TabItem> <TabItem value="flutter" label="Flutter (Dart)" default> ```javascript showLineNumbers // PlayerID (pre-v5 OneSignal SDK) // in your OSSubscriptionObserver implementation func onOSSubscriptionChanged(_ stateChanges: OSSubscriptionStateChanges) { if let playerId = stateChanges.to.userId { Task { try await Adapty.setIntegrationIdentifier( key: "one_signal_player_id", value: playerId ) } } } ``` </TabItem> <TabItem value="rn" label="React Native (TS)" default> ```typescript showLineNumbers OneSignal.addSubscriptionObserver(event => { const playerId = event.to.userId; adapty.setIntegrationIdentifier("one_signal_player_id", playerId); }); ``` </TabItem> </Tabs> </TabItem> </Tabs> OneSignal ドキュメントの詳細はこちらをご覧ください: - [プッシュサブスクリプション ID](https://documentation.onesignal.com/docs/en/mobile-sdk-reference#user-pushsubscription-id) - [プッシュサブスクリプションの変更](https://documentation.onesignal.com/docs/en/mobile-sdk-reference#addobserver-push-subscription-changes) ## 複数デバイスへの対応 \{#dealing-with-multiple-devices\} ユーザーが複数のデバイスを持っている場合、購入イベントやサブスクリプションの追跡が難しくなることがあります。OneSignal では、[external user ID](https://documentation.onesignal.com/docs/en/users) を使ってこの問題に対処できます。 デバイス間でユーザーデータを一貫させるには: 1. **サーバーサイド**で異なるデバイスを照合し、そのデータを OneSignal に送信します。 2. Adapty の [customer_user_id](identifying-users) を OneSignal の [externalUserId](https://documentation.onesignal.com/docs/en/users#external-id) として使用します。アプリに登録システムがない場合は、ユーザーのデバイス間で一貫性を保つ別の一意の識別子の使用を検討してください。 すべてのデバイスでユーザー識別子の一貫性を維持し、ユーザーの ID が変わるたびに OneSignal を更新することが重要です。これにより、ユーザーのアクティビティとサブスクリプションの追跡が簡素化され、一貫したメッセージングが確保されるとともに、より正確な分析とより良いユーザー体験が実現できます。詳細については、OneSignal の [external user ID ドキュメント](https://documentation.onesignal.com/docs/en/users)をご覧ください。 --- # File: pushwoosh --- --- title: "Pushwoosh" description: "AdaptyとPushwooshを統合して、プッシュ通知のトラッキングをシームレスに実現しましょう。" --- Adaptyはサブスクリプションイベントを使用して[Pushwoosh](https://www.pushwoosh.com/)のプロファイルタグを更新します。以下に説明する簡単なインテグレーション設定を行うことで、プッシュ通知を活用した顧客へのターゲットコミュニケーションが可能になります。 ## Pushwoosh インテグレーションの設定方法 \{#how-to-set-up-pushwoosh-integration\} Pushwoosh との連携を設定するには、[**Integrations** -> **Pushwoosh**](https://app.adapty.io/integrations/pushwoosh) に移動してトグルをオンにし、各フィールドを入力してください。 まず、PushwooshとAdaptyのプロファイルを接続するための認証情報を設定します。 Pushwoosh のアプリIDと認証トークンが必要です。 <img src="/assets/shared/img/64e48a1-CleanShot_2023-08-18_at_11.13.212x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 1. **App ID** はPushwooshのダッシュボードで確認できます。 <img src="/assets/shared/img/ee27687-CleanShot_2023-08-18_at_14.37.442x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. **Auth token** はPushwoosh の設定画面にある「API Access」セクションで確認できます。 <img src="/assets/shared/img/50e634b-CleanShot_2023-08-18_at_14.35.022x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## イベントとタグ \{#events-and-tags\} 認証情報の下には、AdaptyからPushwooshに送信できるイベントのグループが3つあります。必要なものをオンにするだけです。Pushwooshに送信するイベント名は変更することもできます。Adaptyが提供するイベントの全リストは[こちら](events)でご確認ください。 <img src="/assets/shared/img/392dc31-screencapture-app-adapty-io-integrations-pushwoosh-2023-08-22-13_31_07.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Adaptyはサーバー間インテグレーションを使用してPushwooshにサブスクリプションイベントを送信するため、Pushwooshダッシュボードですべてのサブスクリプションイベントを確認できます。 :::note カスタムタグ AdaptyではPushwooshインテグレーションにカスタムタグを使用することもできます。以下のタグ一覧を参照して、用途に合ったタグをお選びください。 ::: | タグ | タイプ | 値 | |---|----|-----| | `adapty_customer_user_id` | String | Pushwoosh側で確認できるユーザーの一意の識別子の値を含みます。 | | `adapty_profile_id` | String | Adaptyの[ダッシュボード](profiles-crm)で確認できるユーザーのAdaptyプロファイルIDの値を含みます。 | | `environment` | String | <p>ユーザーがサンドボックス環境または本番環境のいずれで操作しているかを示します。</p><p></p><p>値は `Sandbox` または `Production` のいずれかです。</p> | | `store` | String | <p>購入に使用されたストアの名前を含みます。</p><p></p><p>設定可能な値:</p><p>`app_store` または `play_store`</p> | | `vendor_product_id` | String | <p>Apple/GoogleストアのプロダクトIDの値を含みます。</p><p></p><p>例:org.locals.12345</p> | | `subscription_expires_at` | String | <p>最新のサブスクリプションの有効期限日を含みます。</p><p></p><p>値の形式:</p><p>year-month dayThour:minute:second</p><p>例:2023-02-10T17:22:03.000000+0000</p> | | `last_event_type` | String | インテグレーションで有効化した標準の[Adaptyイベント](events)の中で、最後に受信したイベントの種類を示します。 | | `purchase_date` | String | <p>最後のトランザクション(初回購入または更新)の日付を含みます。</p><p></p><p>値の形式:</p><p>year-month dayThour:minute:second</p><p>例:2023-02-10T17:22:03.000000+0000</p> | | `original_purchase_date` | String | <p>トランザクションに基づく最初の購入日を含みます。</p><p></p><p>値の形式:</p><p>year-month dayThour:minute:second</p><p>例:2023-02-10T17:22:03.000000+0000</p> | | `active_subscription` | String | 購入または更新イベント時に `true`、サブスクリプションが期限切れの場合は `false` に設定されます。 | | `period_type` | String | <p>購入または更新の最新の期間タイプを示します。</p><p></p><p>設定可能な値:</p><p>トライアル期間の場合は `trial`、それ以外は `normal`</p> | すべての浮動小数点値は整数に丸められます。文字列はそのまま維持されます。 定義済みのタグ一覧に加えて、タグを使用して[カスタム属性](segments#custom-attributes)を送信することも可能です。これにより、タグに含めるデータの種類の柔軟性が高まり、プロダクトやサービスに関連する特定の情報のトラッキングに役立ちます。**Send user custom attributes** チェックボックスを[インテグレーションページ](https://app.adapty.io/integrations/pushwoosh)でオンにすると、すべてのカスタムユーザー属性が自動的にPushwooshに送信されます。 ## SDK の設定 \{#sdk-configuration\} AdaptyとPushwooshを連携するには、`HWID` の値を送信する必要があります: <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS (Swift)" default> ```swift showLineNumbers do { try await Adapty.setIntegrationIdentifier( key: "pushwoosh_hwid", value: Pushwoosh.sharedInstance().getHWID() ) } catch { // handle the error } ``` </TabItem> <TabItem value="kotlin" label="Android (Kotlin)" default> ```kotlin showLineNumbers Adapty.setIntegrationIdentifier("pushwoosh_hwid", Pushwoosh.getInstance().hwid) { error -> if (error != null) { // handle the error } } ``` </TabItem> <TabItem value="java" label="Android (Java)" default> ```java showLineNumbers Adapty.setIntegrationIdentifier("pushwoosh_hwid", Pushwoosh.getInstance().getHwid(), error -> { if (error != null) { // handle the error } }); ``` </TabItem> <TabItem value="flutter" label="Flutter (Dart)" default> ```javascript showLineNumbers final hwid = await Pushwoosh.getInstance.getHWID; try { await Adapty().setIntegrationIdentifier( key: "pushwoosh_hwid", value: hwid, ); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` </TabItem> <TabItem value="unity" label="Unity (C#)" default> ```csharp showLineNumbers using AdaptySDK; Adapty.SetIntegrationIdentifier( "pushwoosh_hwid", Pushwoosh.Instance.HWID, (error) => { // handle the error }); ``` </TabItem> <TabItem value="rn" label="React Native (TS)" default> ```typescript showLineNumbers // ... try { await adapty.setIntegrationIdentifier("pushwoosh_hwid", hwid); } catch (error) { // handle `AdaptyError` } ``` </TabItem> </Tabs> --- # File: slack --- --- title: "Slack" description: "Adapty と Slack を連携して、サブスクリプションイベントのリアルタイム通知を受け取りましょう。" --- [Slack](https://slack.com/) は、ビジネス向けメッセンジャー兼生産性プラットフォームです。説明不要でしょう。 この連携を使えば、Adapty が収益イベントを検知するたびに Slack で通知を受け取れるようになります。MRR が上がる瞬間を逃さず確認したい場合や、トライアルのキャンセル・請求エラー・返金などを素早く把握したい場合に特に便利です。 ## Slack 連携の設定方法 \{#how-to-set-up-slack-integration\} 以下の手順が必要です: - Slack ワークスペースにアプリを作成する - メッセージ投稿の権限を付与する - Adapty の [Integrations → Slack](https://app.adapty.io/integrations/slack) に必要な情報を入力する ### 1\. Slack でアプリを作成する \{#1-create-an-app-in-slack\} 1. [Slack API ダッシュボード](https://api.slack.com/apps)にアクセスし、次の手順でアプリを作成します: <img src="/assets/shared/img/f43aedc-CleanShot_2024-01-04_at_18.27.412x.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> <img src="/assets/shared/img/08fa9e6-CleanShot_2024-01-04_at_18.28.142x.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. 任意の名前(例:`Adapty`)を付け、ワークスペースに追加します: <img src="/assets/shared/img/5002bb1-CleanShot_2024-01-04_at_18.29.132x.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### 2\. 投稿権限を付与してトークンを取得する \{#2-give-permission-to-post-and-get-a-token-for-your-app\} アプリのページにリダイレクトされます。 1. 下にスクロールして **Permissions** をクリックします: <img src="/assets/shared/img/9750451-CleanShot_2024-01-04_at_18.48.072x.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. リダイレクト後、**Scopes** までスクロールして **Add an OAuth Scope** をクリックします: <img src="/assets/shared/img/db5b5f4-CleanShot_2024-01-04_at_18.50.262x.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. チャンネルへの投稿とメッセージのカスタマイズに必要な `chat:write`、`chat:write.public`、`chat:write.customize` の権限を付与します: <img src="/assets/shared/img/d97ccb9-CleanShot_2024-01-04_at_18.51.572x.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. ページ上部に戻り、**Install to Workspace** をクリックします: <img src="/assets/shared/img/14608e3-CleanShot_2024-01-04_at_19.17.58.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. **Allow** をクリックします: <img src="/assets/shared/img/143967e-CleanShot_2024-01-04_at_18.53.292x.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> この操作後、同じページにリダイレクトされますが、OAuth トークン(`xoxb-...`)が表示されます。これが設定完了に必要なトークンです: <img src="/assets/shared/img/59b33ee-CleanShot_2024-01-04_at_18.55.222x.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### 3\. Adapty で連携を設定する \{#3-configure-the-integration-in-adapty\} 1. [**Integrations** → **Slack**](https://app.adapty.io/integrations/slack) に移動します: <img src="/assets/shared/img/b4ffd71-CleanShot_2024-01-04_at_19.05.222x.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. 前のステップで取得した `xoxb-...` トークンを貼り付け、投稿先のチャンネルを選択します。本番環境のみ、サンドボックスのみ、または両方でイベントを受け取るよう設定できます。また、通知に使用する通貨(元の通貨または USD 換算)も選択できます。 :::note プライベートチャンネルに Adapty からメッセージを投稿したい場合は、Slack で作成した `Adapty` アプリをそのチャンネルに手動で追加する必要があります。追加しないと正常に動作しません。 ::: 3. 最後に、**Events** で受け取りたいイベントを選択します: <img src="/assets/shared/img/970a7bb-CleanShot_2024-01-04_at_19.09.472x.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> これで設定完了です! 指定したチャンネルにイベントが送信されます。該当する場合は収益も確認でき、Adapty でカスタマープロファイルを参照することもできます: <img src="/assets/shared/img/852b8c8-CleanShot_2024-01-04_at_19.11.332x.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> --- # File: s3-exports --- --- title: "Amazon S3" description: "高度な分析とレポートのためにサブスクリプションデータをS3にエクスポートします。" --- Adapty の Amazon S3 インテグレーションを使用すると、イベントデータとペイウォール訪問データを一か所に安全に保存できます。[サブスクリプションイベント](events)を .csv ファイルとして Amazon S3 バケットに保存することが可能です。 このインテグレーションを設定するには、AWS コンソールと Adapty ダッシュボードでいくつかの簡単な手順を行う必要があります。 :::note スケジュール Adapty はデータを**24時間ごと**、UTC 4:00 に送信します。 各ファイルには、UTC の前日カレンダー全体で作成されたイベントのデータが含まれます。たとえば、3月8日 UTC 4:00 に自動エクスポートされるデータには、3月7日の 00:00:00〜23:59:59(UTC)に作成されたすべてのイベントが含まれます。 ::: ## Amazon S3 インテグレーションの設定方法 \{#how-to-set-up-amazon-s3-integration\} データの受信を開始するには、以下の認証情報が必要です: 1. アクセスキー ID 2. シークレットアクセスキー 3. S3 バケット名 4. S3 バケット内のフォルダ名 :::note ネストされたディレクトリ Amazon S3 バケット名フィールドにネストされたディレクトリを指定できます(例:adapty-events/com.sample-app) ::: Amazon S3 のインテグレーションを設定するには、[**Integrations** -> **Amazon S3**](https://app.adapty.io/integrations/s3) に移動し、トグルをオフからオンに切り替えて、各フィールドに入力してください。 まず、Amazon S3 と Adapty プロファイルの接続を確立するための認証情報を設定します。 <img src="/assets/shared/img/2b1a6e3-CleanShot_2023-03-24_at_14.51.272x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Adapty ダッシュボードでは、接続を設定するために以下のフィールドが必要です: | フィールド | 説明 | | :--------------------------- | :----------------------------------------------------------- | | **Access Key ID** | AWS サービスへのアクセスを認証するために使用される一意の識別子です。ダウンロードした [csv ファイル](s3-exports#how-to-create-amazon-s3-credentials) で確認できます。 | | **Secret Access Key** | Access Key ID と組み合わせて AWS サービスへのアクセスを認証するためのプライベートキーです。ダウンロードした [csv ファイル](s3-exports#how-to-create-amazon-s3-credentials) で確認できます。 | | **S3 Bucket Name** | AWS クラウド内の特定の S3 バケットを識別するグローバルに一意の名前です。S3 バケットはシンプルなストレージサービスで、ファイルや画像などのデータオブジェクトをクラウド上に保存・取得できます。 | | **Folder Inside the Bucker** | 選択した S3 バケット内に作成するフォルダーの名前です。S3 はオブジェクトキーのプレフィックス(実質的にフォルダー名)を使用してフォルダーを疑似的に表現している点にご注意ください。 | ## Amazon S3 認証情報の作成方法 \{#how-to-create-amazon-s3-credentials\} このガイドでは、AWS コンソールで必要な認証情報を作成する手順を説明します。 ### 1\. アクセスポリシーの作成 \{#1-create-access-policy\} まず、AWS コンソールの [IAM ポリシーダッシュボード](https://us-east-1.console.aws.amazon.com/iamv2/home?region=us-east-1#/policies) に移動し、**Create Policy** を選択します。 <img src="/assets/shared/img/7af075c-CleanShot_2023-03-21_at_10.52.002x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> In the Policy editor, paste the following JSON and change `adapty-s3-integration-test` to your bucket name: ```json showLineNumbers title="Json" { "Version": "2012-10-17", "Statement": [ { "Sid": "AllowListObjectsInBucket", "Effect": "Allow", "Action": "s3:ListBucket", "Resource": "arn:aws:s3:::adapty-s3-integration-test" }, { "Sid": "AllowAllObjectActions", "Effect": "Allow", "Action": "s3:*Object", "Resource": [ "arn:aws:s3:::adapty-s3-integration-test/*", "arn:aws:s3:::adapty-s3-integration-test" ] }, { "Sid": "AllowBucketLocation", "Effect": "Allow", "Action": "s3:GetBucketLocation", "Resource": "arn:aws:s3:::adapty-s3-integration-test" } ] } ``` <img src="/assets/shared/img/d4e474a-CleanShot_2023-03-21_at_10.56.212x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ポリシーの設定が完了したら、タグを追加する(任意)かどうかを選択し、**Next** をクリックして最終ステップに進みます。このステップでポリシーに名前を付け、**Create policy** ボタンをクリックするだけで作成が完了します。 <img src="/assets/shared/img/7dcb02f-CleanShot_2023-03-21_at_11.03.372x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### 2\. IAM ユーザーの作成 \{#2-create-iam-user\} Adapty がローデータレポートをバケットにアップロードできるようにするには、対象バケットへの書き込みアクセス権を持つユーザーの Access Key ID と Secret Access Key を提供する必要があります。 手順を進めるには、IAM コンソールにアクセスし、[Users セクション](https://console.aws.amazon.com/iamv2/home#/users)を選択してください。次に、**Add users** ボタンをクリックします。 <img src="/assets/shared/img/bb612c8-CleanShot_2023-03-21_at_11.12.392x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ユーザーに名前を付け、**Access key – Programmatic access** を選択して、権限の設定に進みます。 <img src="/assets/shared/img/467ee4d-j6aoX.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 次のステップでは、**Add user to group** オプションを選択し、**Create group** ボタンをクリックしてください。 <img src="/assets/shared/img/bfd0e80-CleanShot_2023-03-21_at_11.24.592x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 次に、User Group の名前を入力し、先ほど作成したポリシーを選択します。ポリシーを選択したら、**Create group** ボタンをクリックして完了です。 <img src="/assets/shared/img/df29c12-CleanShot_2023-03-21_at_11.28.052x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> グループの作成が完了したら、**それを選択**して次のステップに進んでください。 <img src="/assets/shared/img/1f3722e-CleanShot_2023-03-21_at_11.36.192x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> このセクションの最後のステップなので、**Create User** ボタンをクリックして進んでください。 <img src="/assets/shared/img/ea43722-CleanShot_2023-03-21_at_11.40.462x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 最後に、認証情報を**.csv 形式でダウンロード**するか、ダッシュボードから直接コピー&ペーストすることができます。 <img src="/assets/shared/img/bcf35e1-S3created.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## 手動データエクスポート \{#manual-data-export\} Amazon S3 への自動イベントデータエクスポートに加えて、Adapty では手動ファイルエクスポート機能も提供しています。この機能を使うと、エクスポートするイベントデータの期間を指定し、S3 バケットに手動でエクスポートできます。これにより、エクスポートするデータとそのタイミングをより細かく管理できます。 指定した日付範囲では、Date A の 00:00:00 UTC から Date B の 23:59:59 UTC までに作成されたイベントがエクスポートされます。 <img src="/assets/shared/img/466bd29-CleanShot_2023-03-21_at_12.35.252x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## テーブル構造 \{#table-structure\} AWS S3 連携では、Adapty はトランザクションイベントおよびペイウォール訪問の履歴データを保存するテーブルを提供します。このテーブルには、ユーザープロファイル、収益および収益額、元のストアなど、さまざまなデータが含まれています。基本的に、これらのテーブルはアプリが一定期間に生成したすべてのトランザクションを記録します。 :::warning この構造は、今後私たちまたは連携するサードパーティによって新しいデータが追加され、拡張される可能性があります。この構造を処理するコードは、構造全体に依存するのではなく、特定のフィールドに依存する形で堅牢に作成してください。 ::: 以下はイベントのテーブル構造です。 | カラム | 説明 | |---------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **profile_id** | Adapty ユーザー ID。 | | **event_type** | 小文字のイベント名。イベントの種類については [Events](events) セクションを参照してください。 | | **event_datetime** | ISO 8601 形式の日付。 | | **transaction_id** | 購入や更新などのトランザクションの一意の識別子。 | | **original_transaction_id** | 最初の購入のトランザクション識別子。 | | **subscription_expires_at** | サブスクリプションの有効期限。通常は未来の日時。 | | **environment** | Sandbox または Production。 | | **revenue_usd** | USD での売上。空の場合があります。 | | **proceeds_usd** | USD での収益。空の場合があります。 | | **net_revenue_usd** | USD での純収益(税引き後の収入)。空の場合があります。 | | **tax_amount_usd** | USD での税額。空の場合があります。 | | **revenue_local** | 現地通貨での売上。空の場合があります。 | | **proceeds_local** | 現地通貨での収益。空の場合があります。 | | **net_revenue_local** | 現地通貨での純収益(税引き後の収入)。空の場合があります。 | | **tax_amount_local** | 現地通貨での税額。空の場合があります。 | | **customer_user_id** | 開発者のユーザー ID。たとえば、ユーザーの UUID、メールアドレス、その他の ID を使用できます。設定していない場合は Null。 | | **store** | _app_store_ または _play_store_。 | | **product_id** | Apple App Store、Google Play Store、または Stripe でのプロダクト ID。 | | **base_plan_id** | Google Play Store での [ベースプラン ID](https://support.google.com/googleplay/android-developer/answer/12154973) または Stripe での [価格 ID](https://docs.stripe.com/products-prices/how-products-and-prices-work#use-products-and-prices)。 | | **developer_id** | トランザクションが発生したペイウォールの開発者(SDK)ID。 | | **ab_test_name** | トランザクションが発生した A/B テストの名前。 | | **ab_test_revision** | トランザクションが発生した A/B テストのリビジョン。 | | **paywall_name** | トランザクションが発生したペイウォールの名前。 | | **paywall_revision** | トランザクションが発生したペイウォールのリビジョン。 | | **profile_county** | IP アドレスをもとに Adapty が判定したプロファイルの国。 | | **install_date** | インストールが行われた日付(ISO 8601 形式)。 | | **idfv** | iOS デバイスの [identifierForVendor](https://developer.apple.com/documentation/uikit/uidevice/identifierforvendor) | | **idfa** | iOS デバイスの [advertisingIdentifier](https://developer.apple.com/documentation/adsupport/asidentifiermanager/advertisingidentifier) | | **advertising_id** | Android オペレーティングシステムが割り当てる一意のコードで、広告主がユーザーのデバイスを識別するために使用する広告 ID。 | | **ip_address** | デバイスの IP アドレス(IPv4 または IPv6。利用可能な場合は IPv4 を優先)。デバイスの IP が変わるたびに更新されます。 | | **cancellation_reason** | <p>ユーザーがサブスクリプションをキャンセルした理由。</p><p></p><p>以下の値が設定されます:</p><p>**iOS & Android** _voluntarily_cancelled_、_billing_error_、_refund_</p><p>**iOS** _price_increase_、_product_was_not_available_、_unknown_、_upgraded_</p><p>**Android** _new_subscription_replace_、_cancelled_by_developer_</p> | | **android_app_set_id** | [AppSetId](https://developer.android.com/design-for-safety/privacy-sandbox/reference/adservices/appsetid/AppSetId) — デバイスおよび開発者アカウントごとに一意で、ユーザーがリセット可能な、非収益化広告用途向けの ID。 | | **android_id** | Android 8.0(API レベル 26)以降では、アプリの署名キー、ユーザー、デバイスの組み合わせごとに一意な 64 ビットの数値(16 進数文字列で表現)。詳細は [Android 開発者ドキュメント](https://developer.android.com/reference/android/provider/Settings.Secure#ANDROID_ID) を参照してください。 | | **device** | エンドユーザーに表示されるデバイスのモデル名。 | | **currency** | トランザクションの 3 文字の通貨コード(ISO-4217)。 | | **store_country** | Apple/Google ストアが判定したプロファイルの国。 | | **attribution_source** | アトリビューションソース。 | | **attribution_network_user_id** | アトリビューションソースがユーザーに割り当てた ID。 | | **attribution_status** | organic、non_organic、または unknown。 | | **attribution_channel** | マーケティングチャネル名。 | | **attribution_campaign** | マーケティングキャンペーン名。 | | **attribution_ad_group** | アトリビューションの広告グループ。 | | **attribution_ad_set** | アトリビューションの広告セット。 | | **attribution_creative** | アトリビューションのクリエイティブキーワード。 | | **attributes** | [カスタムユーザー属性](setting-user-attributes#custom-user-attributes) の JSON。モバイルアプリから送信するよう設定したカスタム属性が含まれます。送信するには、[Integrations -> Webhooks](https://app.adapty.io/integrations/customwebhook) ページで **Send User Attributes** オプションを有効にしてください。 | | **integration_ids** | プロファイルに関連付けられたすべてのインテグレーション ID。ディクショナリ形式。例: {'mixpanel_user_id': 'mixpanelUserId-test', 'facebook_anonymous_id': 'facebookAnonymousId-test'} | ここにペイウォール訪問数のテーブル構造を示します: | カラム | 説明 | | :-------------------- | :----------------------------------------------------------------------------------------------------------- | | **profile_id** | Adapty のユーザー ID。 | | **customer_user_id** | 開発者のユーザー ID。例えば、ユーザーの UUID、メールアドレス、その他の ID などを設定できます。未設定の場合は Null。 | | **profile_country** | Apple/Google ストアによって決定されるプロファイルの国。 | | **install_date** | インストールが行われた日時(ISO 8601 形式)。 | | **store** | _app_store_ または _play_store_ のいずれか。 | | **paywall_showed_at** | ペイウォールがユーザーに表示された日時。 | | **developer_id** | トランザクションが発生したペイウォールの開発者(SDK)ID。 | | **ab_test_name** | トランザクションが発生した A/B テストの名前。 | | **ab_test_revision** | トランザクションが発生した A/B テストのリビジョン。 | | **paywall_name** | トランザクションが発生したペイウォールの名前。 | | **paywall_revision** | トランザクションが発生したペイウォールのリビジョン。 | ## イベントとタグ \{#events-and-tags\} インテグレーションで通信するデータを管理できます。このインテグレーションでは、以下の設定オプションを利用できます。 | 設定 | 説明 | | :--------------------------------- | :----------------------------------------------------------- | | **Exclude Historical Events** | Adapty SDK を含むアプリをユーザーがインストールする前に発生したイベントを除外するかどうかを選択します。これにより、イベントの重複を防ぎ、正確なレポートを確保できます。たとえば、ユーザーが 1 月 10 日に月次サブスクリプションを有効化し、3 月 6 日に Adapty SDK を含むアプリにアップデートした場合、Adapty は 3 月 6 日より前のイベントを除外し、以降のイベントのみを保持します。 | | **Include events without profile** | Adapty のユーザープロファイルに紐付いていないトランザクションを含めるかどうかを選択します。これには、Adapty SDK のインストール前に行われた購入や、特定のユーザーにすぐに関連付けられないストアのサーバー通知から受信したトランザクションが含まれる場合があります。 | | **Send User Attributes** | 言語設定などのユーザー固有の属性を送信したい場合で、かつ OneSignal のプランが 10 個を超えるタグをサポートしている場合は、このオプションを選択します。有効にすると、デフォルトの 10 タグを超える追加情報を含めることができます。タグの上限を超えるとエラーが発生する可能性がある点に注意してください。 | <img src="/assets/shared/img/s3-settings.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> インテグレーション設定の下には、Adapty から Amazon S3 にエクスポート・送信・保存できるイベントが3つのグループに分かれています。必要なものをオンにするだけです。Adapty が提供するイベントの全一覧は[こちら](events)をご確認ください。 <img src="/assets/shared/img/fd5ccb9-CleanShot_2023-08-17_at_14.49.282x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> --- # File: google-cloud-storage --- --- title: "Google Cloud Storage" description: "AdaptyとのセキュアなデータストレージのためのGoogle Cloud Storage連携。" --- Google Cloud Storage連携を有効にすると、[サブスクリプションイベント](events)と[ペイウォール訪問データ](paywall-metrics)を一か所、つまりGoogle Cloud Storageバケットに安全に保存できます。 毎日UTC午前4時に、Adaptyは前日のデータを含む.csvファイルをバケットにアップロードします。**イベント**データ、**ペイウォール訪問**データ、または**両方**を受け取るかどうかを選択できます。また、任意の期間のデータをいつでも[手動でエクスポート](#manual-data-export)することもできます。 連携を設定するには、Google Cloud コンソールで[バケットアクセスキーを生成](#create-google-cloud-storage-credentials)し、[Adaptyの設定に追加](#set-up-google-cloud-storage-integration)します。 ## アップロードスケジュールと所要時間 \{#upload-schedule-and-duration\} AdapyはUTC 04:00に24時間ごとにGoogle Cloud Storageへデータをアップロードします。 ファイルには前の暦日(UTC)に作成されたイベントのデータが含まれます。3月8日にアップロードされるファイルには、3月7日の00:00:00〜23:59:59 UTCに作成されたすべてのイベントが含まれます。 キュー内のファイルの総数やご自身がリクエストしたデータ量によっては、処理に数時間かかる場合があります。初回アップロードに過去のデータが含まれる場合、以降の毎日のアップロードより時間がかかります。 ## Google Cloud Storage連携の設定 \{#set-up-google-cloud-storage-integration\} **書き込みアクセス権**を持つ有効なGoogle Cloudサービスアカウントキーが必要です。生成方法については、[認証情報の作成](#create-google-cloud-storage-credentials)セクションの手順に従ってください。 :::warning イベントとペイウォール訪問に対して、それぞれ異なるバケットと認証情報を使用できます。ただし、**いずれか**の認証情報が無効な場合、[**両方のアップロードが失敗します**](#troubleshooting)。 ::: [**Integrations** -> **Google Cloud Storage**](https://app.adapty.io/integrations/google-cloud-storage) に移動し、必要なタブ(**Events** または **Paywall visits**)を開きます。連携を有効にします。 **Google Cloudサービスアカウントキー**を含むファイルをアップロードします。対象の**バケット**と**フォルダー**を指定します。変更を保存します。 ### イベントデータのオプション設定 \{#optional-settings-for-event-data\} レポートに含めるイベントを指定したり、イベントにカスタム名を設定したりできます。利用可能なイベントの全一覧は[イベント](events)の記事をご覧ください。 | 名前 | デフォルト | 説明 | | ------------------------------ | ----------------- | ----------- | | Exclude historical events | true | AdaptySDKをアプリに統合する前に発生したイベントの情報を除外します。<br /> <br />アナリティクスプラットフォームがAdapty導入**前**にサブスクリプションイベントを受け取っていた場合、このオプションによって重複イベントの受信を防げます。<Details summary="実際の例"><p>ユーザーが1月10日に月次サブスクリプションを購入しました。3月1日のアプリアップデートが初めてAdapty SDKを含むものでした。<br /> <br /> この設定が**オン**の場合、レポートには1月の「サブスクリプション開始」イベントも2月の「サブスクリプション更新」イベントも含まれません。3月10日の「サブスクリプション更新」イベント**は**含まれます。</p> </Details> | | Include events without profile | false | ユーザープロファイルに紐付いていない、または特定ユーザーにすぐに関連付けられないトランザクションを含めます。Adapty SDK導入前の購入や、サーバー通知経由で受け取ったトランザクションが該当します。 | | Send user attributes | false | [カスタムユーザー属性](setting-user-attributes)(ユーザーデータやアプリ使用データなど)を含めます。OneSignalのプランが10個以上のタグをサポートしている場合にこのオプションを選択してください。タグ上限を超えるとエラーが発生する場合があります。 | ## Google Cloud Storageの認証情報の作成 \{#create-google-cloud-storage-credentials\} このガイドでは、Google Cloud Platform コンソールで必要な認証情報を作成する方法を説明します。 Adaptyが指定のバケットに生データレポートをアップロードするには、サービスアカウントのキーと、対応するバケットへの書き込みアクセス権が必要です。サービスアカウントのキーを提供してバケットへの書き込みアクセスを付与することで、AdaptyがプラットフォームからストレージEnvironmentへ生データレポートを安全かつ効率的に転送できるようになります。 :::warning サービスアカウントのHMACキー認証のみをサポートしています。Google Cloud Storageへの適切なアクセスを有効にするため、サービスアカウントのHMACキーに「Storage Object Viewer」「Storage Legacy Bucket Writer」「Storage Object Creator」のロールが追加されていることを確認してください。 ::: 1. まず、Google CloudアカウントのIAMセクション([IAM](https://console.cloud.google.com/projectselector2/iam-admin/serviceaccounts))に移動し、関連するプロジェクトを選択するか、新しいプロジェクトを作成します。 1. 次に、「+ CREATE SERVICE ACCOUNT」ボタンをクリックしてAdapty用の新しいサービスアカウントを作成します。 2. 最初のステップのフィールドに入力します(アクセス権は後の段階で付与されます)。このページの詳細については、[こちら](https://docs.cloud.google.com/iam/docs/service-accounts-create)のドキュメントをご覧ください。 3. [プライベートJSONキー](https://docs.cloud.google.com/iam/docs/keys-create-delete)を作成してダウンロードするには、KEYSセクションに移動し、「ADD KEY」ボタンをクリックします。 4. DETAILSセクションで、作成したサービスアカウントに紐付くEmail値を見つけてコピーします。この情報は、アカウントを認証してバケットへの書き込みを許可するための後続手順で必要になります。 5. 次に、Google Cloud Storageの[Buckets](https://console.cloud.google.com/storage/browser)ページに移動し、既存のバケットを選択するか、AdapyのイベントまたはVisitsデータレポートを保存するための新しいバケットを作成します。次にPERMISSIONSセクションに移動し、[GRANT ACCESS](https://docs.cloud.google.com/identity/docs/how-to?hl=en)オプションを選択します。 6. PERMISSIONSセクションで、手順5で取得したサービスアカウントのEmailを入力し、Storage Object Creatorロールを選択します。最後にSAVEをクリックして変更を適用します。 バケット名は後で使用するので控えておいてください。 ## 手動データエクスポート \{#manual-data-export\} Google Cloud Storageへの自動イベントデータエクスポートに加えて、Adaptyでは手動ファイルエクスポート機能も提供しています。この機能を使用すると、イベントデータの特定の時間範囲を選択して、GCSバケットに手動でエクスポートできます。エクスポートするデータとタイミングをより細かく制御できます。 指定した日付範囲は、日付A 00:00:00 UTCから日付B 23:59:59 UTCまでに作成されたイベントのエクスポートに使用されます。 ## データ構造 \{#data-structure\} Adaptyはデータを表形式でエクスポートするために`.csv`ファイルを使用します。 :::warning イベントの内容は、Adaptyまたは連携している3rd partyが新しいデータを追加することで増えることがあります。処理するコードは特定のフィールドに依存させ、構造全体に依存しないよう十分に堅牢にしてください。 ::: ### イベント \{#events\} レポートに含めるイベントの一覧は[変更可能](#optional-settings-for-event-data)です。 | カラム | 説明 | |------|-----------| | **profile_id** | AdapyユーザーID。 | | **event_type** | 小文字のイベント名。イベントタイプについては[Events](events)セクションを参照してください。 | | **event_datetime** | ISO 8601形式の日時。 | | **transaction_id** | 購入や更新などのトランザクションの一意の識別子。 | | **original_transaction_id** | 元の購入のトランザクション識別子。 | | **subscription_expires_at** | サブスクリプションの有効期限。通常は未来の日時。 | | **environment** | SandboxまたはProductionのいずれか。 | | **revenue_usd** | USD換算の収益。空の場合があります。 | | **proceeds_usd** | USD換算の受取額。空の場合があります。 | | **net_revenue_usd** | USD換算の純収益(税引後の収入)。空の場合があります。 | | **tax_amount_usd** | USD換算の税金控除額。空の場合があります。 | | **revenue_local** | 現地通貨での収益。空の場合があります。 | | **proceeds_local** | 現地通貨での受取額。空の場合があります。 | | **net_revenue_local** | 現地通貨での純収益(税引後の収入)。空の場合があります。 | | **tax_amount_local** | 現地通貨での税金控除額。空の場合があります。 | | **customer_user_id** | 開発者のユーザーID。ユーザーのUUID、メールアドレス、その他のIDを設定できます。設定していない場合はNull。 | | **store** | *app_store*または*play_store*のいずれか。 | | **product_id** | Apple App Store、Google Play Store、またはStripeでのプロダクトID。 | | **base_plan_id** | Google Play Storeの[ベースプランID](https://support.google.com/googleplay/android-developer/answer/12154973)、またはStripeの[価格ID](https://docs.stripe.com/products-prices/how-products-and-prices-work#use-products-and-prices)。 | | **developer_id** | トランザクションが発生したペイウォールの開発者(SDK)ID。 | | **ab_test_name** | トランザクションが発生したA/Bテストの名前。 | | **ab_test_revision** | トランザクションが発生したA/Bテストのリビジョン。 | | **paywall_name** | トランザクションが発生したペイウォールの名前。 | | **paywall_revision** | トランザクションが発生したペイウォールのリビジョン。 | | **profile_country** | IPアドレスに基づいてAdapyが判定したプロファイルの国。 | | **install_date** | インストールが発生したISO 8601形式の日時。 | | **idfv** | iOSデバイスの[identifierForVendor](https://developer.apple.com/documentation/uikit/uidevice/identifierforvendor) | | **idfa** | iOSデバイスの[advertisingIdentifier](https://developer.apple.com/documentation/adsupport/asidentifiermanager/advertisingidentifier) | | **advertising_id** | Androidオペレーティングシステムが広告主向けに割り当てる、デバイスを一意に識別するための広告ID | | **ip_address** | デバイスのIPアドレス(IPv4またはIPv6、利用可能な場合はIPv4優先)。デバイスのIPが変わるたびに更新されます | | **cancellation_reason** | <p>ユーザーがサブスクリプションをキャンセルした理由。</p><p></p><p>使用可能な値:</p><p>**iOS & Android** — *voluntarily_cancelled*, *billing_error*, *refund*</p><p>**iOSのみ** — *price_increase*, *product_was_not_available*, *unknown*, *upgraded*</p><p>**Androidのみ** — *new_subscription_replace*, *cancelled_by_developer*</p> | | **android_app_set_id** | [AppSetId](https://developer.android.com/design-for-safety/privacy-sandbox/reference/adservices/appsetid/AppSetId) — 非収益化広告用途向けの、デバイスごと・開発者アカウントごとにリセット可能な一意のID。 | | **android_id** | Android 8.0(APIレベル26)以降では、アプリの署名キー、ユーザー、デバイスの組み合わせごとに一意な64ビットの数値(16進数文字列として表現)。詳細は[Androidデベロッパードキュメント](https://developer.android.com/reference/android/provider/Settings.Secure#ANDROID_ID)を参照してください。 | | **device** | エンドユーザーに表示されるデバイスモデル名。 | | **currency** | トランザクションの3文字通貨コード(ISO-4217)。 | | **store_country** | Apple/Google Storeが判定したプロファイルの国。 | | **attribution_source** | アトリビューションソース。 | | **attribution_network_user_id** | アトリビューションソースがユーザーに割り当てたID。 | | **attribution_status** | organic、non_organic、unknownのいずれか。 | | **attribution_channel** | マーケティングチャネル名。 | | **attribution_campaign** | マーケティングキャンペーン名。 | | **attribution_ad_group** | アトリビューションの広告グループ。 | | **attribution_ad_set** | アトリビューションの広告セット。 | | **attribution_creative** | アトリビューションのクリエイティブキーワード。 | | **attributes** | [カスタムユーザー属性](setting-user-attributes#custom-user-attributes)のJSON。モバイルアプリから送信するよう設定したカスタム属性が含まれます。送信するには、[Integrations -> Webhooks](https://app.adapty.io/integrations/customwebhook)ページで**Send User Attributes**オプションを有効にしてください。 | | **integration_ids** | プロファイルに関連付けられたすべての連携ID。ディクショナリ形式。例:{'mixpanel_user_id': 'mixpanelUserId-test', 'facebook_anonymous_id': 'facebookAnonymousId-test'} | ### ペイウォール訪問 \{#paywall-visits\} | カラム | 説明 | | :-------------------- | :----------------------------------------------------------------------------------------------------------- | | **profile_id** | AdapyユーザーID。 | | **customer_user_id** | 開発者のユーザーID。ユーザーのUUID、メールアドレス、その他のIDを設定できます。設定していない場合はNull。 | | **profile_country** | Apple/Google Storeが判定したプロファイルの国。 | | **install_date** | インストールが発生したISO 8601形式の日時。 | | **store** | *app_store*または*play_store*のいずれか。 | | **paywall_showed_at** | ペイウォールが顧客に表示された日時。 | | **developer_id** | トランザクションが発生したペイウォールの開発者(SDK)ID。 | | **ab_test_name** | トランザクションが発生したA/Bテストの名前。 | | **ab_test_revision** | トランザクションが発生したA/Bテストのリビジョン。 | | **paywall_name** | トランザクションが発生したペイウォールの名前。 | | **paywall_revision** | トランザクションが発生したペイウォールのリビジョン。 | ## トラブルシューティング \{#troubleshooting\} Adaptyはアップロードを開始する**前に**アクセスキーの有効性を確認します。Google Cloud Storageのキーが1つでも無効な場合、Adaptyは**アップロードを中断**してエラーをスローします。 アップロードが中断されないよう、キーの有効期限が切れる前に更新してください。**イベント**のキーを更新した場合は、**ペイウォール訪問**のキーも忘れずに更新してください(逆も同様です)。 --- # File: webhook-event-types-and-fields --- --- title: "Webhookイベントタイプとフィールド" description: "" --- Adaptyはサブスクリプションイベントに応じてWebhookを送信します。このセクションでは、イベントタイプと各Webhookに含まれるデータを説明します。 ## Webhookイベントタイプ \{#webhook-event-types\} すべてのイベントタイプをWebhookに送信するか、一部のみを選択して送信できます。受信データの内容やビジネスロジックの構築方法については、[イベントフロー](event-flows)を参照してください。不要なイベントタイプは、[Webhook連携の設定](set-up-webhook-integration#configure-webhook-integration-in-the-adapty-dashboard)時に無効化できます。また、必要に応じてAdaptyのデフォルトイベントIDを独自のIDに置き換えることも可能です。 | イベント名 | 説明 | |:-----------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | subscription_started | トライアル期間なしで有料サブスクリプションを開始したとき(つまり即座に課金されたとき)にトリガーされます。 | | subscription_renewed | サブスクリプションが更新され、ユーザーに課金されたときに発生します。このイベントはトライアルあり・なしを問わず、2回目以降の請求から記録されます。 | | subscription_renewal_cancelled | ユーザーがサブスクリプションの自動更新をオフにしました。有料サブスクリプション期間が終了するまでプレミアム機能へのアクセスは継続されます。 | | subscription_renewal_reactivated | ユーザーがサブスクリプションの自動更新を再度有効にしたときにトリガーされます。 | | subscription_expired | キャンセルされたサブスクリプションが完全に終了したときにトリガーされます。たとえば、12月12日にサブスクリプションをキャンセルしても12月31日まで有効な場合、イベントは12月31日に記録されます。 | | subscription_paused | ユーザーが[サブスクリプションの一時停止](https://developer.android.com/google/play/billing/lifecycle/subscriptions#pause)を有効にしたときに発生します(Android のみ)。 | | subscription_deferred | サブスクリプションの購入が[延期](https://adapty.io/glossary/subscription-purchase-deferral/)され、ユーザーが支払いを先送りしながらプレミアム機能へのアクセスを維持できる場合にトリガーされます。この機能は Google Play Developer API を通じて利用可能で、無料トライアルや支払いが困難なユーザーへの対応に活用できます。 | | non_subscription_purchase | 永続アクセスやゲーム内コインなどの消耗型アイテムといった、サブスクリプション以外のすべての購入。 | | trial_started | ユーザーがトライアルサブスクリプションを開始したときにトリガーされます。 | | trial_converted | トライアルが終了してユーザーに課金されたとき(初回購入)に発生します。たとえば、1月14日までトライアル期間があるにもかかわらず1月7日に課金された場合、イベントは1月7日に記録されます。 | | trial_renewal_cancelled | トライアル期間中にユーザーがサブスクリプションの自動更新をオフにしました。トライアルが終了するまでプレミアム機能へのアクセスは継続されますが、課金やサブスクリプションの開始は行われません。 | | trial_renewal_reactivated | トライアル期間中にユーザーがサブスクリプションの自動更新を再度有効にしたときに発生します。 | | trial_expired | サブスクリプションに転換されずにトライアルが終了したときにトリガーされます。 | | entered_grace_period | 支払い試行が失敗し、ユーザーがグレース期間(有効な場合)に入ったときに発生します。この期間中もユーザーはプレミアム機能にアクセスできます。 | | billing_issue_detected | 課金試行中に請求エラーが発生したとき(例:カード残高不足)にトリガーされます。 | | subscription_refunded | サブスクリプションが返金されたとき(例:Apple サポートによる返金)にトリガーされます。 | | non_subscription_purchase_refunded | サブスクリプション以外の購入が返金されたときにトリガーされます。 | | access_level_updated | ユーザーのアクセスレベルが更新されたときに発生します。 | :::note `subscription_renewal_reactivated` は、ユーザーがキャンセルした時点でアクティブだったプロダクト ID(**以前の**プロダクト ID)を保持します。これは、ユーザーが別のプロダクトを購入して再アクティブ化した場合でも同様です。Apple はキャンセル → 再アクティブ化の一連の流れを通じて同じ `original_transaction_id` を維持するため、このイベントは元のプロダクトを反映します。新しいプロダクトは、新しいプロダクトの課金が開始される次の `subscription_renewed` イベントで確認できます。 ::: ## Webhookイベントの構造 \{#webhook-event-structure\} Adaptyは、[Integrations -> Webhooks](https://app.adapty.io/integrations/customwebhook)ページの**Events names**セクションで選択したイベントのみを送信します。 Webhookイベントは JSON 形式でシリアライズされます。サーバーへの `POST` リクエストのボディには、以下の構造でラップされたシリアライズ済みイベントが含まれます。すべてのイベントは同じ構造に従いますが、フィールドの内容はイベントタイプ、ストア、および設定内容によって異なります。ユーザー属性は、設定した[カスタムユーザー属性](setting-user-attributes#custom-user-attributes)であるため、設定した内容が反映されます。アトリビューションデータのフィールドはすべてのイベントタイプで共通ですが、アトリビューションのリストはモバイルアプリで使用しているアトリビューションソースによって異なります。イベントの例を以下に示します: ```json title="Json" showLineNumbers { "profile_id": "00000000-0000-0000-0000-000000000000", "customer_user_id": "UserIdInYourSystem", "idfv": "00000000-0000-0000-0000-000000000000", "idfa": "00000000-0000-0000-0000-000000000000", "advertising_id": "00000000-0000-0000-0000-000000000000", "profile_install_datetime": "2000-01-31T00:00:00.000000+0000", "user_agent": "ExampleUserAgent/1.0 (Device; OS Version) Browser/Engine", "email": "john.doe@company.com", "event_type": "subscription_started", "event_datetime": "2000-01-31T00:00:00.000000+0000", "event_properties": { "store": "play_store", "currency": "USD", "price_usd": 4.99, "profile_id": "00000000-0000-0000-0000-000000000000", "cohort_name": "All Users", "environment": "Production", "price_local": 4.99, "base_plan_id": "b1", "developer_id": "onboarding_placement", "ab_test_name": "onboarding_ab_test", "ab_test_revision": 1, "paywall_name": "UsedPaywall", "proceeds_usd": 4.2315, "variation_id": "00000000-0000-0000-0000-000000000000", "purchase_date": "2024-11-15T10:45:36.181000+0000", "store_country": "AR", "event_datetime": "2000-01-31T00:00:00.000000+0000", "proceeds_local": 4.2415, "tax_amount_usd": 0, "transaction_id": "0000000000000000", "net_revenue_usd": 4.2415, "profile_country": "AR", "paywall_revision": "1", "profile_event_id": "00000000-0000-0000-0000-000000000000", "tax_amount_local": 0, "net_revenue_local": 4.2415, "vendor_product_id": "onemonth_no_trial", "profile_ip_address": "10.10.1.1", "consecutive_payments": 1, "rate_after_first_year": false, "original_purchase_date": "2000-01-31T00:00:00.000000+0000", "original_transaction_id": "0000000000000000", "subscription_expires_at": "2000-01-31T00:00:00.000000+0000", "profile_has_access_level": true, "profile_total_revenue_usd": 4.99, "promotional_offer_id": null, "store_offer_category": null, "store_offer_discount_type": null }, "event_api_version": 1, "profiles_sharing_access_level": [{"profile_id": "00000000-0000-0000-0000-000000000000", "customer_user_id": "UserIdInYourSystem"}], "attributions": { "appsflyer": { "ad_set": "Keywords 1.12", "status": "non_organic", "channel": "Google Ads", "ad_group": null, "campaign": "Social media influencers - Rest of the world", "creative": null, "created_at": "2000-01-31T00:00:00.000000+0000" } }, "user_attributes": {"Favourite_color": "Violet", "Pet_name": "Fluffy"}, "integration_ids": {"firebase_app_instance_id": "val1", "branch_id": "val2", "one_signal_player_id": "val3"}, "play_store_purchase_token": { "product_id": "product_123", "purchase_token": "token_abc_123", "is_subscription": true } } ``` ### イベントフィールド \{#event-fields\} イベントパラメーターはすべてのイベントタイプで共通です。 | **フィールド** | **型** | **説明** | |---|---|---| | **advertising_id** | UUID | 広告ID(Android のみ)。 | | **attributions** | JSON | [アトリビューションデータ](webhook-event-types-and-fields#attributions)。[Webhook 設定](https://app.adapty.io/integrations/customwebhook)で **Send Attribution** が有効な場合に含まれます。 | | **customer_user_id** | String | [ユーザーの識別](ios-quickstart-identify)時にアプリコードで設定したアプリ側のユーザー ID(UUID、メールアドレス、その他の ID)。アプリコードでユーザーを識別していない場合、または該当ユーザーが匿名(未ログイン)の場合は `null` になります。 | | **email** | String | Adapty SDK の [`updateProfile`](setting-user-attributes) メソッド、またはサーバーサイド API でプロファイルを作成・更新する際に設定したユーザーのメールアドレス。`email` の値を SDK や API メソッドに渡していない場合は `null` になります。 | | **event_api_version** | Integer | Adapty API のバージョン(現在: `1`)。 | | **event_datetime** | ISO 8601 | イベントのビジネス上の有効時刻。購入イベントなら購入日時、有効期限イベントなら有効期限など、Adapty がイベントを受信・送信した時刻ではありません。[ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) 形式(例: `2020-07-10T15:00:00.000000+0000`)。順序については下記の注記を参照してください。 | | **event_properties** | JSON | [イベントプロパティ](webhook-event-types-and-fields#event-properties)。 | | **event_type** | String | Adapty 形式のイベント名。全リストは[Webhook イベントタイプ](webhook-event-types-and-fields#webhook-event-types)を参照してください。 | | **idfa** | UUID | 広告識別子(Apple のみ)。[Adapty ダッシュボード](https://app.adapty.io/profiles/users)のプロファイルに表示される **IDFA**。トラッキング制限、キッズモード、プライバシー設定により利用できない場合は `null` になる場合があります。 | | **idfv** | UUID | ベンダー識別子(IDFV)。開発者ごとに一意の値。[Adapty ダッシュボード](https://app.adapty.io/profiles/users)のプロファイルに表示される **IDFV**。 | | **integration_ids** | JSON | Adapty SDK の `setIntegrationIdentifier` メソッド、またはサーバーサイド API でプロファイルを作成・更新する際に設定したユーザーのインテグレーション ID。利用できない場合またはインテグレーションが無効な場合は `null`。 | | **play_store_purchase_token** | JSON | [Play Store 購入トークン](webhook-event-types-and-fields#play-store-purchase-token)。[Webhook 設定](https://app.adapty.io/integrations/customwebhook)で **Send Play Store purchase token** が有効な場合に含まれます。 | | **profile_id** | UUID | Adapty が各プロファイルに対して自動生成するプロファイル ID。ユーザーを識別しない場合やログイン前に購入を許可している場合、1 つの Apple/Google ID が異なるプロファイル ID と紐付く可能性があります。詳しくは[Adapty の親プロファイルと継承プロファイルの仕組み](how-profiles-work#parent-and-inheritor-profiles)を参照してください。 | | **profile_install_datetime** | ISO 8601 | [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) 形式のインストール日時(例: `2020-07-10T15:00:00.000000+0000`)。 | | **profiles_sharing_access_level** | JSON | 現在のユーザープロファイルを除く、[アクセスレベルを共有している](general#6-sharing-paid-access-between-user-accounts)ユーザーの一覧。アプリでアクセスレベルの共有が有効になっている場合、同じ Apple/Google ID で使用されている他のプロファイルが含まれます。<br/>形式: <ul><li>**profile_id**: (UUID)Adapty ID</li><li>**customer_user_id**: (String)設定されている場合のカスタマーユーザー ID</li></ul> | | **user_agent** | String | デバイスのブラウザユーザーエージェント。 | | **user_attributes** | JSON | アプリ固有の情報でユーザープロファイルを拡充するために設定できるカスタムデータ。ユーザーの設定(テーマ、言語など)や行動フラグ(オンボーディング完了、機能の使用状況)のトラッキングに主に使用します。<br/>キーが文字列、値が文字列または数値のキーバリューペアで表されます(例: `{"Favourite_color": "Violet", "Pet_name": "Fluffy"}`)。<br/>カスタム属性は、Adapty ダッシュボードで個別のプロファイルに対して手動で設定するか、Adapty SDK の `updateProfile` メソッドを使ってプログラムから設定するか、サーバーサイド API でプロファイルを作成・更新する際に設定できます。<br/>[Webhook 設定](https://app.adapty.io/integrations/customwebhook)で **Send User Attributes** が有効な場合に含まれます。 <p>モバイルアプリコードではカスタム属性値を float または文字列として設定できますが、サーバーサイド API や過去データのインポートで受け取った属性は異なる形式で届く場合があります。その場合、boolean と integer の値は float に変換されます。</p> | :::note `event_datetime` はサブスクリプションのライフサイクルでイベントが発生した日時を表しており、Adapty が処理または配信した日時ではありません。そのため、複数のイベントが同じ `event_datetime` を持つ場合や、時系列順とは異なる順序で届く場合があります。たとえば、`subscription_expired` イベントの `event_datetime` が、それより前に配信された `subscription_renewal_cancelled` イベントの `event_datetime` より早い場合があります。イベントの順序付けに `event_datetime` を使用しないでください。代わりに、受信時刻を基準にイベントを並べ替え、`profile_event_id` またはトランザクション ID を使って重複を排除してください。 ::: ### アトリビューション \{#attributions\} アトリビューションデータを送信するには、[Integrations -> Webhooks](https://app.adapty.io/integrations/customwebhook) ページで **Send Attribution** オプションを有効にしてください。アトリビューションデータの送信を有効にしており、[アトリビューション連携](attribution-integration)を設定済みの場合、以下のデータがすべてのソースのイベントに付与されて送信されます。同じアトリビューションデータはすべてのイベントタイプに送信されます。 ```json title="Json" showLineNumbers { "attributions": { "appsflyer": { "ad_set": "sample_ad_set_123", "status": "non_organic", "channel": "sample_channel", "ad_group": "sample_ad_group_456", "campaign": "sample_ios_campaign", "creative": "sample_creative_789", "created_at": "2000-01-31T00:00:00.000000+0000", "network_user_id": "0000000000000-0000000" } } } ``` | フィールド名 | フィールド型 | 説明 | | :------------------ | :------------ | :------------------------------------------------- | | **ad_set** | String | アトリビューションの広告セット。 | | **status** | String | `organic`、`non_organic,`、または `unknown` のいずれか。 | | **channel** | String | マーケティングチャネル名。 | | **ad_group** | String | アトリビューションの広告グループ。 | | **campaign** | String | マーケティングキャンペーン名。 | | **creative** | String | アトリビューションのクリエイティブキーワード。 | | **created_at** | ISO 8601 date | アトリビューションレコードの作成日時。 | | **network_user_id** | String | アトリビューションソースがユーザーに割り当てたID。 | ### インテグレーション ID \{#integration-ids\} 現在、イベントで使用されているインテグレーション ID は以下のとおりです: - `adjust_device_id` - `airbridge_device_id` - `amplitude_device_id` - `amplitude_user_id` - `appmetrica_device_id` - `appmetrica_profile_id` - `appsflyer_id` - `branch_id` - `facebook_anonymous_id` - `firebase_app_instance_id` - `mixpanel_user_id` - `pushwoosh_hwid` - `one_signal_player_id` - `one_signal_subscription_id` - `tenjin_analytics_installation_id` - `posthog_distinct_user_id` ### Play Store の購入トークン \{#play-store-purchase-token\} このフィールドには、必要に応じて購入を再検証するために必要なすべてのデータが含まれています。[Webhookインテグレーションの設定](https://app.adapty.io/integrations/customwebhook)で **Send Play Store purchase token** オプションが有効になっている場合にのみ送信されます。 | Field | Type | Description | | :------------------ | :------ | :----------------------------------------------------------- | | **product_id** | String | Play Store で購入したプロダクトの一意識別子(SKU)。 | | **purchase_token** | String | この購入トランザクションを一意に識別するために Google Play が生成するトークン。 | | **is_subscription** | Boolean | 購入したプロダクトがサブスクリプション(`true`)か買い切り購入(`false`)かを示します。 | ### イベントプロパティ \{#event-properties\} イベントプロパティは、イベントの種類によって、また同じ種類のイベント間でも異なる場合があります。たとえば、App Store から発生したイベントには、`base_plan_id` のような Android 固有のプロパティは含まれません。 [アクセスレベル更新](webhook-event-types-and-fields#for-access-level-updated-event)イベントには固有のプロパティがあるため、専用セクションを設けています。同様に、[追加の税・収益イベントプロパティ](webhook-event-types-and-fields#additional-tax-and-revenue-event-properties)も特定のイベントタイプのみに該当するため、別セクションに分けています。 #### ほとんどのイベントタイプに共通 \{#for-most-event-types\} ほとんどのイベントタイプのイベントプロパティは共通です(**Access Level Updated** イベントを除く。このイベントについては専用のセクションで説明します)。以下は、各プロパティと、それが特定のイベントに属するかどうかを示す一覧表です。 | フィールド | 型 | 説明 | |:------------------------------|:--------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **ab_test_name** | String | トランザクションが発生した [Adapty A/B テスト](ab-tests) の名前。 | | **ab_test_revision** | Integer | トランザクションが発生した A/B テストのリビジョン。 | | **base_plan_id** | String | Google Play ストアの [ベースプラン ID](https://support.google.com/googleplay/android-developer/answer/12154973)、または Stripe の [price ID](https://docs.stripe.com/products-prices/how-products-and-prices-work#use-products-and-prices)。 | | **cancellation_reason** | String | <p>キャンセル理由の候補: `voluntarily_cancelled`、`billing_error`、`price_increase`、`product_was_not_available`、`refund`、`cancelled_by_developer`、`new_subscription_replace`、`upgraded`、`unknown`、`adapty_revoked`。</p><p>以下のイベントタイプに含まれます:</p>`subscription_cancelled`、`subscription_refunded`、`trial_cancelled`。 | | **cohort_name** | String | ユーザーに表示するペイウォールを決定した [オーディエンス](audience) の名前。 | | **consecutive_payments** | Integer | ユーザーが中断なくサブスクリプションを継続している期間数。現在の期間を含む。 | | **currency** | String | 現地通貨。 | | **developer_id** | String | トランザクションが発生した [プレースメント](placements) の ID。 | | **environment** | String | 取り得る値は `Sandbox` または `Production`。 | | **event_datetime** | ISO 8601 date | イベントの日時。イベントのルートレベルと同じ値。 | | **original_purchase_date** | ISO 8601 date | 定期サブスクリプションの場合、初回購入はチェーンの最初のトランザクションであり、そのIDはオリジナルトランザクション IDと呼ばれ更新チェーンを連結します。以降のトランザクションはその延長です。オリジナル購入日とは、この最初のトランザクションの日時を指します。 | | **original_transaction_id** | String | <p>定期サブスクリプションの場合、これは更新チェーンを連結するオリジナルトランザクション ID です。オリジナルトランザクションはチェーンの最初のものであり、以降のトランザクションはその延長です。</p><p>延長がない場合、`original_transaction_id` は store_transaction_id と一致します。</p> | | **paywall_name** | String | トランザクションが発生したペイウォールの名前。 | | **paywall_revision** | String | トランザクションが発生したペイウォールのリビジョン。デフォルト値は 1。 | | **price_local** | Float | Apple/Google の手数料控除前のプロダクト価格(現地通貨)。 | | **price_usd** | Float | Apple/Google の手数料控除前のプロダクト価格(USD)。 | | **profile_country** | String | プロファイルの IP アドレスをもとに Adapty が判定した国。 | | **profile_event_id** | UUID | 重複排除に使用できる一意のイベント ID。 | | **profile_has_access_level** | Boolean | プロファイルがアクティブなアクセスレベルを持つかどうかを示す Boolean 値。 | | **profile_id** | UUID | Adapty が生成したプロファイル ID。イベントのルートレベルと同じ値。 | | **profile_ip_address** | String | プロファイルの IP アドレス(IPv4 または IPv6。利用可能な場合は IPv4 優先)。[アプリ設定](https://app.adapty.io/settings/general) で **Collect users' IP addresses** が無効の場合は `null`。 | | **profile_total_revenue_usd** | Float | プロファイルの累計収益(返金分を差し引いた値)。 | | **promotional_offer_id** | String | 使用された [プロモーションオファー](offers) の Adapty ID。ダッシュボードでオファーを作成する際に設定します。 | | **purchase_date** | ISO 8601 date | プロダクト購入の日時。 | | **rate_after_first_year** | Boolean | 1 年間継続して更新されたサブスクリプションが、手数料率の引き下げ(通常 15%)の対象となるかどうかを示す Boolean 値。手数料率はプログラムの適用条件や国によって異なります。詳細は [ストア手数料と税金](controls-filters-grouping-compare-proceeds#display-gross-or-net-revenue) を参照してください。 | | **store** | String | プロダクトが購入されたストア。標準値: **app_store**、**play_store**、**stripe**、**paddle**。<br/>サーバーサイド API で [カスタムストアトランザクション](api-adapty/operations/setTransaction) を設定した場合は、**store** パラメーターの値が使用されます。 | | **store_country** | String | アプリストアから送信された国情報。 | | **store_offer_category** | String | 適用されたオファーカテゴリー。取り得る値は `introductory`、`promotional`、`winback`。 | | **store_offer_discount_type** | String | 適用されたオファータイプ。取り得る値は `free_trial`、`pay_as_you_go`、`pay_up_front`。 | | **subscription_expires_at** | ISO 8601 date | サブスクリプションの有効期限。通常は将来の日時。 | | **transaction_id** | String | トランザクションの一意識別子。 | | **trial_duration** | String | トライアル期間の日数。`"{} days"` 形式(例: `"7 days"`)で送信されます。トライアル関連イベントタイプ(`trial_started`、`trial_converted`、`trial_cancelled`)にのみ含まれます。 | | **variation_id** | UUID | 購入が行われたペイウォールの一意 ID。 | | **vendor_product_id** | String | <p>Apple App Store、Google Play ストア、または Stripe におけるプロダクト ID。</p><p>実際のストアトランザクションなしでアクセスが付与された場合、`vendor_product_id` は以下のいずれかになります:</p><ul><li>`adapty_server_side_product` — [サーバーサイド API](api-adapty/operations/grantAccessLevel) 経由で付与。</li><li>`adapty_dashboard_product` — Adapty ダッシュボードで [手動付与](give-access-level-to-specific-customer)。</li><li>`adapty_promotion` — レガシー。</li></ul> | #### 税金と収益に関する追加イベントプロパティ \{#additional-tax-and-revenue-event-properties\} 以下の税金と収益に関するイベントプロパティは、特定のイベントタイプにのみ適用される追加フィールドです。つまり、ここに列挙されているイベントタイプには、[ほとんどのイベントタイプ共通のイベントプロパティ](webhook-event-types-and-fields#for-most-event-types)に加えて、以下の追加フィールドが含まれます。 税金と収益に関するイベントプロパティを持つイベントタイプ: - `subscription_renewed` - `subscription_initial_purchase`(`subscription_started` とも呼ばれる — 同じイベント) - `subscription_refunded` - `non_subscription_purchase` | フィールド | 型 | 説明 | | :-------------------- | :---- | :----------------------------------------------------------- | | **net_revenue_local** | Float | ローカル通貨でのネット収益(Apple/Google の手数料および税金控除後の収入)。 | | **net_revenue_usd** | Float | USD でのネット収益(Apple/Google の手数料および税金控除後の収入)。 | | **proceeds_local** | Float | ローカル通貨での Apple/Google 手数料控除後のプロダクト価格。 | | **proceeds_usd** | Float | Apple/Google 手数料控除後のプロダクト価格(USD)。 | | **tax_amount_local** | Float | ローカル通貨での控除税額。 | | **tax_amount_usd** | Float | USD での控除税額。 | #### `non_subscription_purchase` のペイロード例 \{#non-subscription-purchase-example-payload\} `non_subscription_purchase` はサブスクリプションイベントと同じ構造に従いますが、買い切り購入または消耗型アイテムの購入を反映します。サブスクリプション専用フィールドは適用されません。`cancellation_reason`、`will_renew`、`is_in_grace_period`、`is_refund`、`is_lifetime`、`trial_duration` は存在しません。`subscription_expires_at` は含まれますが `null` になります。税金および収益フィールド(`net_revenue_*`、`proceeds_*`、`tax_amount_*`)は含まれます。 <details> <summary>ペイロード例(クリックして展開)</summary> ```json title="Json" showLineNumbers { "profile_id": "00000000-0000-0000-0000-000000000000", "customer_user_id": "UserIdInYourSystem", "event_type": "non_subscription_purchase", "event_datetime": "2000-01-31T00:00:00.000000+0000", "event_properties": { "store": "app_store", "currency": "USD", "price_usd": 4.99, "price_local": 4.99, "proceeds_usd": 4.2415, "proceeds_local": 4.2415, "net_revenue_usd": 4.2415, "net_revenue_local": 4.2415, "tax_amount_usd": 0, "tax_amount_local": 0, "profile_id": "00000000-0000-0000-0000-000000000000", "environment": "Production", "vendor_product_id": "100coins", "transaction_id": "0000000000000000", "original_transaction_id": "0000000000000000", "purchase_date": "2024-11-15T10:45:36.181000+0000", "original_purchase_date": "2024-11-15T10:45:36.181000+0000", "subscription_expires_at": null, "store_country": "US", "profile_country": "US", "profile_ip_address": "10.10.1.1", "profile_has_access_level": false, "profile_total_revenue_usd": 4.99, "consecutive_payments": 1, "rate_after_first_year": false, "profile_event_id": "00000000-0000-0000-0000-000000000000" }, "event_api_version": 1 } ``` </details> #### アクセスレベル更新イベントについて \{#for-access-level-updated-event\} **Access Level Updated** イベントは、Webhook インテグレーションが有効であり、このイベントタイプが有効になっている場合にのみ生成される特定の Webhook イベントです。有効になっている場合、設定済みの Webhook に送信され、**Event Feed** に表示されます。有効になっていない場合、イベントは作成されません。 [アクセスレベルの共有](general#6-sharing-paid-access-between-user-accounts)を有効にしている場合、**access level updated** イベントはアクセスレベルを共有しているすべてのプロファイルに対して送信されます。 :::tip このイベントを使用して、データベース内のユーザーのアクセスレベルを更新し、バックエンドでプレミアム機能を付与または取り消し、デバイスやプラットフォーム間でアクセスを同期させましょう。 ::: | プロパティ | タイプ | 説明 | | ---------------------------------- | ------------- | ------------------------------------------------------------ | | **ab_test_name** | String | トランザクションが発生した A/B テストの名前。 | | **access_level_id** | String | アクセスレベルの ID。 | | **activated_at** | ISO 8601 date | アクセスが最後にアクティブ化された日時。 | | **active_introductory_offer_type** | String | 適用された初回オファーのタイプ。指定可能な値は `free_trial`、`pay_as_you_go`、`pay_up_front`。 | | **active_promotional_offer_id** | String | Adapty ダッシュボードの Product セクションに記載されたプロモーションオファーの ID。 | | **active_promotional_offer_type** | String | 適用されたプロモーションオファーのタイプ。指定可能な値は `free_trial`、`pay_as_you_go`、`pay_up_front`。 | | **base_plan_id** | String | Google Play ストアの[ベースプラン ID](https://support.google.com/googleplay/android-developer/answer/12154973)、または Stripe の[価格 ID](https://docs.stripe.com/products-prices/how-products-and-prices-work#use-products-and-prices)。 | | **billing_issue_detected_at** | ISO 8601 date | 請求問題が発生した日時。 | | **cancellation_reason** | String | キャンセル理由として考えられる値: `voluntarily_cancelled`、`billing_error`、`price_increase`、`product_was_not_available`、`refund`、`cancelled_by_developer`、`new_subscription_replace`、`upgraded`、`unknown`、`adapty_revoked`。 | | **cohort_name** | String | プロファイルが属するオーディエンスの名前。 | | **currency** | String | ローカル通貨(デフォルトは USD)。 | | **developer_id** | String | トランザクションが発生したプレースメントの ID。 | | **environment** | String | 指定可能な値は `Sandbox` または `Production`。 | | **event_datetime** | ISO 8601 date | イベントの日時。 | | **expires_at** | ISO 8601 date | アクセスが失効する日時。 | | **is_active** | Boolean | アクセスレベルがアクティブかどうかを示す Boolean 値。 | | **is_in_grace_period** | Boolean | プロファイルがグレース期間中かどうかを示す Boolean 値。 | | **is_lifetime** | Boolean | アクセスレベルが永続アクセスかどうかを示す Boolean 値。 | | **is_refund** | Boolean | トランザクションが返金かどうかを示す Boolean 値。 | | **original_purchase_date** | ISO 8601 date | 自動更新サブスクリプションの場合、最初のトランザクションが「オリジナル購入」となり、その ID(オリジナルトランザクション ID)が以降の更新トランザクションのチェーンをつなぐ。以降のトランザクションはこの最初のトランザクションの延長である。オリジナル購入日はこの最初のトランザクションの日時。 | | **original_transaction_id** | String | <p>自動更新サブスクリプションの場合、更新チェーンをつなぐオリジナルトランザクション ID。オリジナルトランザクションはチェーンの最初のもので、以降のトランザクションはその延長である。</p><p>延長がない場合、`original_transaction_id` は store_transaction_id と一致する。</p>最初の購入のトランザクション識別子。 | | **paywall_name** | String | トランザクションが発生したペイウォールの名前。 | | **paywall_revision** | String | トランザクションが発生したペイウォールのリビジョン。デフォルト値は 1。 | | **profile_country** | String | プロファイルの IP を基に Adapty が判定した国。 | | **profile_event_id** | UUID | 重複排除に使用できる一意のイベント ID。 | | **profile_has_access_level** | Boolean | プロファイルにアクティブなアクセスレベルがあるかどうかを示す Boolean 値。 | | **profile_id** | UUID | Adapty の内部ユーザープロファイル ID。 | | **profile_ip_address** | String | プロファイルの IP アドレス(IPv4 または IPv6。利用可能な場合は IPv4 が優先される)。[アプリ設定](https://app.adapty.io/settings/general)で **Collect users' IP addresses** が無効になっている場合は `null`。 | | **profile_total_revenue_usd** | Float | プロファイルの累計収益(返金を含む)。 | | **purchase_date** | ISO 8601 date | プロダクトを購入した日時。 | | **renewed_at** | ISO 8601 date | アクセスが更新される日時。 | | **starts_at** | ISO 8601 date | アクセスレベルが開始する日時。 | | **store** | String | プロダクトを購入したストア。標準値: **app_store**、**play_store**、**stripe**、**paddle**。<br/>サーバーサイド API で[カスタムストアトランザクション](api-adapty/operations/setTransaction)を設定した場合は、**store** パラメータの値が使用される。 | | **store_country** | String | アプリストアから Adapty に送信された国。 | | **subscription_expires_at** | ISO 8601 date | サブスクリプションの有効期限。 | | **transaction_id** | String | トランザクションの一意の識別子。 | | **trial_duration** | String | トライアル期間の日数(例:「7 days」)。 | | **variation_id** | UUID | バリアントの識別子。購入をこのペイウォールに紐付けるために使用される。 | | **vendor_product_id** | String | <p>ストア(Apple / Google / Stripe)内のプロダクト ID。</p><p>実際のストアトランザクションなしでアクセスが付与された場合、`vendor_product_id` は以下のいずれかになる:</p><ul><li>`adapty_server_side_product` — [サーバーサイド API](api-adapty/operations/grantAccessLevel) 経由で付与された。</li><li>`adapty_dashboard_product` — Adapty ダッシュボードで[手動付与](give-access-level-to-specific-customer)された。</li><li>`adapty_promotion` — レガシー。</li></ul> | | **will_renew** | Boolean | 有料アクセスレベルが更新されるかどうかを示す値。 | :::warning この構造は、私たちまたは連携するサードパーティによって新しいデータが追加されることで、今後拡張される可能性があります。この構造を処理するコードは、構造全体ではなく特定のフィールドに依存するよう、十分に堅牢に実装してください。 ::: --- # File: set-up-webhook-integration --- --- title: "Webhook連携の設定" description: "AdaptyでWebhook連携を設定してイベントトラッキングを自動化します。" --- Adaptyの[webhook連携](webhook)は、以下のステップで構成されています。 <img src="/assets/shared/img/webhook-setup.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '300px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> <p> </p> 1. **エンドポイントを設定する:** 1. サーバーが **Content-Type** ヘッダーを `application/json` に設定したAdaptyリクエストを処理できることを確認します。 2. サーバーがAdaptyの検証リクエストを受信し、任意の `2xx` ステータスとJSONボディで応答するよう設定します。 3. 接続が確認されたら、[サブスクリプションイベントを処理します](#subscription-events)。 2. **[Adapty ダッシュボード](#configure-webhook-integration-in-the-adapty-dashboard)でwebhook連携を設定して有効化します。** [Adaptyのイベントをカスタムイベント名にマッピング](#configure-webhook-integration-in-the-adapty-dashboard)することもできます。本番環境に切り替える前に、**Sandbox環境**でテストすることをおすすめします。 3. **Adaptyがサーバーに検証リクエストを送信します。** 4. **サーバーが** `2XX` ステータスとJSONボディで**応答します。** 5. **Adaptyが有効なレスポンスを受信すると、サブスクリプションイベントの送信を開始します。** ## Adaptyリクエストを処理するサーバーを設定する \{#set-up-your-server-to-process-adapty-requests\} AdaptyはWebhookエンドポイントに2種類のリクエストを送信します。 1. [検証リクエスト](#verification-request): 接続が正しく設定されているか確認するための初回リクエストです。このリクエストにはイベントは含まれず、Adapty ダッシュボードのWebhook連携で **Save** ボタンをクリックした瞬間に送信されます。エンドポイントが検証リクエストを正常に受信したことを確認するため、エンドポイントは検証レスポンスを返す必要があります。 2. [サブスクリプションイベント](#subscription-events): Adaptyサーバーでイベントが作成されるたびに送信される標準リクエストです。サーバーは特定のレスポンスを返す必要はありません。Adaptyサーバーが必要とするのは、メッセージを正常に受信した場合に標準の200コードHTTPレスポンスを受け取ることだけです。 ### 検証リクエスト \{#verification-request\} Adapty ダッシュボードでwebhook連携を有効にすると、Adaptyは空のJSONオブジェクト `{}` をボディとして含むPOST検証リクエストを送信します。 エンドポイントの **Content-Typeヘッダー** が `application/json` になるよう設定してください。つまり、サーバーのエンドポイントは受信するWebhookリクエストのペイロードがJSON形式でフォーマットされることを想定している必要があります。 サーバーは2xxステータスコードで応答し、以下のような有効なJSONレスポンスを返す必要があります。 ```json title="Json" {} ``` Adaptyが正しい形式かつ2xxステータスコードの検証レスポンスを受信すると、AdaptyのWebhook連携は完全に設定された状態になります。 ### サブスクリプションイベント \{#subscription-events\} サブスクリプションイベントは **Content-Type** ヘッダーが `application/json` に設定された状態で送信され、JSON形式のイベントデータが含まれます。可能なイベントタイプとリクエスト構造については、[Webhookイベントの種類とフィールド](webhook-event-types-and-fields)を参照してください。 ## Adapty ダッシュボードでWebhook連携を設定する \{#configure-webhook-integration-in-the-adapty-dashboard\} Adaptyでは、本番イベントとApple・Sandbox環境またはGoogleテストアカウントから受信するテストイベントに対して、別々のフローを設定できます。 :::tip Adaptyは環境(本番とサンドボックス)ごとに1つのWebhook URLをサポートしています。複数のサービスにイベントを配信するには、Webhookを自分のバックエンドに向けてそこからファンアウトしてください。 ::: 本番イベントには、コールバックの送信先URLを指定する **Production endpoint URL** フィールドを使用します。また、**Authorization header value for production endpoint** フィールドも設定してください。これはサーバーがAdaptyイベントを認証するためのヘッダーです。**Authorization header value for production endpoint** フィールドに指定した値は、変更や追加なしにそのまま `Authorization` ヘッダーとして使用されることにご注意ください。 テストイベントには、**Sandbox endpoint URL** と **Authorization header value for sandbox endpoint** フィールドをそれぞれ使用します。 Webhook連携を設定するには: 1. Adapty ダッシュボードで [Integrations -> Webhook](https://app.adapty.io/integrations/customwebhook) を開きます。 <img src="/assets/shared/img/webhook_integration.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. トグルをオンにして連携を開始します。 4. 連携フィールドに入力します。 | フィールド | 説明 | | ------------------------------------------------------ | ------------------------------------------------------------ | | **Production endpoint URL** | AdaptyがHTTP POSTリクエストを本番環境のイベントとして送信するURL。 | | **Authorization header value for production endpoint** | <p>本番環境でサーバーがAdaptyからのリクエストを認証するためのヘッダー。このフィールドに指定した値は、変更や追加なしにそのまま `Authorization` ヘッダーとして使用されることにご注意ください。</p><p></p><p>必須ではありませんが、セキュリティ強化のために強くお勧めします。</p> | サンドボックス環境でのテスト用に、さらに2つのフィールドが利用可能です。 | テストフィールド | 説明 | | --------------------------------------------------- | ------------------------------------------------------------ | | **Sandbox endpoint URL** | AdaptyがサンドボックスHTTP POSTリクエストを送信するURL。 | | **Authorization header value for sandbox endpoint** | <p>サンドボックス環境でのテスト中にサーバーがAdaptyからのリクエストを認証するためのヘッダー。このフィールドに指定した値は、変更や追加なしにそのまま `Authorization` ヘッダーとして使用されることにご注意ください。</p><p></p><p>必須ではありませんが、セキュリティ強化のために強くお勧めします。</p> | 4. (任意)受信するイベントを選択して名前をマッピングします。様々な状況でどのイベントが発生するかは、[イベントフロー](event-flows)をご確認ください。 イベントIDがAdaptyで使用されているものと異なる場合は、システム内のIDをそのまま維持し、[Integrations -> Webhooks](https://app.adapty.io/integrations/customwebhook) ページの **Events names** セクションでデフォルトのAdaptyイベントIDをご自身のIDに置き換えてください。 イベントIDには任意の文字列を使用できます。Webhookを処理するサーバーのイベントIDと、Adapty ダッシュボードに入力したIDが一致していることを確認してください。有効なイベントのイベントIDを空のままにすることはできません。 <img src="/assets/shared/img/86942b8-event_names_renaming.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. その他のフィールドや設定は任意です。必要に応じて使用してください。 | 設定 | 説明 | | :--------------------------------- | :----------------------------------------------------------- | | **Send Trial Price** | 有効にすると、Adaptyは **Trial Started** イベントの `price_local` と `price_usd` フィールドにサブスクリプション価格を含めます。 | | **Exclude Historical Events** | ユーザーがAdapty SDKを含むアプリをインストールする前に発生したイベントを除外するオプションです。これによりイベントの重複を防ぎ、正確なレポートを確保します。例えば、ユーザーが1月10日に月次サブスクリプションを有効化し、3月6日にAdapty SDK付きのアプリにアップデートした場合、Adaptyは3月6日より前のイベントを省略し、以降のイベントを保持します。 | | **Send user attributes** | このオプションを有効にすると、言語設定などのユーザー固有の属性が送信されます。これらの属性は `user_attributes` フィールドに表示されます。詳細については、[イベントフィールド](webhook-event-types-and-fields#event-fields)を参照してください。 | | **Send attribution** | このオプションをオンにすると、`attributions` フィールドにアトリビューション情報(AppsFlierデータなど)が含まれます。詳細は[アトリビューションデータ](webhook-event-types-and-fields#attributions)セクションを参照してください。 | | **Send Play Store purchase token** | このオプションをオンにすると、必要に応じて購入の再検証に必要なPlay Storeトークンを受け取れます。有効にすると、イベントに `play_store_purchase_token` パラメータが追加されます。その内容の詳細については、[Play Store購入トークン](webhook-event-types-and-fields#play-store-purchase-token)セクションを参照してください。 | 6. **Save** ボタンをクリックして変更を確定することを忘れないでください。 **Save** ボタンをクリックした瞬間、Adaptyは検証リクエストを送信し、サーバーからの検証レスポンスを待ちます。 ### 送信するイベントを選択してイベント名をマッピングする \{#choose-events-to-send-and-map-event-names\} 受信したいイベントの横にあるトグルを有効にして、サーバーで受信するイベントを選択します。Adaptyで使用されているイベント名と異なる名前を使用していて、そのままの名前を維持したい場合は、[Integrations -> Webhooks](https://app.adapty.io/integrations/customwebhook) ページの **Events names** セクションでデフォルトのAdaptyイベント名をご自身のものに置き換えてマッピングを設定できます。 <img src="/assets/shared/img/86942b8-event_names_renaming.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> イベント名には任意の文字列を使用できます。有効なイベントのフィールドを空のままにすることはできません。誤ってAdaptyのイベント名を削除してしまった場合は、[サードパーティ連携に送信するイベント](events)のトピックからいつでも名前をコピーできます。 ## Webhookイベントを処理する \{#handle-webhook-events\} Webhookは通常、イベント発生後5〜60秒以内に配信されます。ただし、キャンセルイベントはユーザーがサブスクリプションをキャンセルしてから最大2時間後に配信される場合があります。 サーバーのレスポンスステータスコードが200〜404の範囲外の場合、Adaptyは指数バックオフで再送を試みます。最初の再試行は初回の失敗からおよそ**1分後**に行われ、その後は試行ごとに間隔が倍になり、最大9回の再試行が24時間にわたって行われます。Adaptyが応答する前にイベントボディの基本的な検証のみを行うようWebhookを設定することをお勧めします。サーバーがイベントを処理できず、Adaptyに再試行させたくない場合は、200〜404の範囲内のステータスコードを使用してください。また、時間のかかるタスクは非同期で処理し、Adaptyに素早く応答するようにしてください。Adaptyが10秒以内にレスポンスを受信しない場合、その試行は失敗とみなされ、再試行が行われます。 --- # File: test-webhook --- --- title: "Webhookインテグレーションのテスト" description: "AdaptyでWebhookインテグレーションをテストし、サブスクリプションイベントの追跡を自動化します。" --- インテグレーションを設定したら、次はテストを行いましょう。サンドボックスと本番のどちらのインテグレーションもテストできます。まずサンドボックスから始めて、以下の項目を十分に検証することをおすすめします: - イベントが送信され、正常に配信されること。 - 過去のイベント、**Trial started** イベントのサブスクリプション価格、アトリビューション、ユーザー属性、Google Play ストアの購入トークンについて、送信・非送信のオプションが正しく設定されていること。 - イベント名が正しくマッピングされており、サーバーで処理できること。 ## テスト方法 \{#how-to-test\} インテグレーションのテストを始める前に、以下が完了していることを確認してください: 1. [Webhookインテグレーションの設定](set-up-webhook-integration)のトピックに従ってWebhookインテグレーションを設定済みであること。 2. [Apple App StoreでのIn-App Purchaseのテスト](test-purchases-in-sandbox)および[Google Play StoreでのIn-App Purchaseのテスト](testing-on-android)のトピックに従って環境を設定済みであること。テストアプリが本番環境ではなくサンドボックス環境でビルドされていることを確認してください。 3. Webhookに送信するよう選択したイベントを発生させる購入・トライアル開始・返金などを実行済みであること。例えば、**Subscription started** イベントを取得するには、新しいサブスクリプションを購入します。 ## 結果の検証 \{#validation-of-the-result\} ### イベント送信成功時の結果 \{#successful-sending-events-result\} インテグレーションが正常に機能した場合、イベントはインテグレーションの **Last sent events** セクションに表示され、**Success** ステータスになります。 <img src="/assets/shared/img/6ccc3bb-webhook_integration_success.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### イベント送信失敗時の結果 \{#unsuccessful-sending-events-result\} | 問題 | 解決策 | |-----|--------| | イベントが表示されない | 購入が完了しなかったため、イベントが作成されませんでした。解決策については[テスト購入のトラブルシューティング](troubleshooting-test-purchases)のトピックを参照してください。 | | イベントが表示され、**Sending failed** ステータスになっている | <p>配信可否はHTTPステータスに基づいて判定し、**200〜399の範囲外**はすべて失敗とみなします。</p><p>詳しい原因を確認するには、以下に示すように失敗したイベントの **Sending failed** ステータスにマウスを重ねてください。</p> | <img src="/assets/shared/img/12ff189-hover_sending_failed.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> --- # File: handle-integration-errors --- --- title: "インテグレーションのエラーを処理する" description: "インテグレーションのエラーを処理する" --- アトリビューション、メッセージング、またはアナリティクスのインテグレーションを使用する際に、いくつかの一般的なエラーが発生することがあります。トラブルシューティングのケースについては、このガイドを参照してください。 ## データの不一致 \{#data-discrepancy\} **原因**: Adapty SDK が含まれているアプリバージョンを使用していないユーザーが存在するために発生する可能性があります。 **解決策**: データの一貫性を確保するために、ユーザーに Adapty SDK が含まれているバージョンへのアップデートを促すことができます。 ## ネットワークエラー \{#network-errors\} **原因**: Adapty サーバーとインテグレーションサーバー間のインターネット接続が途切れた可能性が高いです。 **解決策**: このような問題は通常長く続かず、影響を受けるイベントの数もごく少数です。 ## インテグレーションサーバーがイベントの処理に失敗した \{#integration-server-failed-to-process-the-event\} **原因**: インテグレーションが正しく設定されていません。 **解決策**: ドキュメントのインテグレーションに関する記事を参照してください。Adapty ダッシュボード、サードパーティツール側、およびアプリコードの両方で、すべてのセットアップ手順を完了していることを確認してください。 ## インテグレーションデータが不足している \{#missing-integration-data\} **原因**: プロファイルにインテグレーション固有の ID が含まれていません。これはアプリコードでインテグレーションが正しく設定されていない場合に発生することがあります。 **解決策**: ドキュメントのインテグレーションに関する記事を参照してください。アプリコードにコードスニペットのメソッドを実装し、それらのメソッドが実際にユーザープロファイルと連携していることを確認してください。 ## インテグレーションの認証情報が不足している \{#missing-integration-credentials\} **原因**: インテグレーションの一部の認証情報が不足しているか、正しくありません。 **解決策**: Adapty ダッシュボードでそのインテグレーションの認証情報をすべて確認してください。バージョンまたは環境の不一致が原因で問題が発生することがあります。 ## イベントの有効期限が切れた \{#the-event-has-expired\} **原因**: インテグレーション設定で **Exclude historical events** オプションが有効になっており、イベントの作成日がシステム内のプロファイル作成日より前になっています。 これは、数年前に開始されたトランザクションのチェーンが、最近作成されたプロファイルのレシート検証を通じて Adapty に届いた場合に発生することがあります。 **解決策**: 新しいイベントでこれが発生しないようにしてください。過去のイベントをインテグレーションに送信したい場合は、**Exclude historical events** を無効にしてください。 ## 無効/未対応のイベントタイプ \{#disabledunsupported-event-type\} **原因**: このインテグレーションでイベントがサポートされていないか、インテグレーションのセットアップ時に無効にされています。たとえば、`access_level_updated` イベントはほとんどのインテグレーションでサポートされていません。 **解決策**: インテグレーションのドキュメントで、そのインテグレーションがこのイベントタイプをサポートしているか確認してください。サポートされている場合は、Adapty ダッシュボードでそのイベントタイプがインテグレーション設定で有効になっていることを確認してください。 --- # File: manage-adapty-with-ai --- --- title: "Manage Adapty with AI agents and coding tools" description: "Every way to use Adapty with AI — integrate the SDK with a coding agent, pull analytics with an LLM, and feed Adapty docs to your AI tool." --- Adapty works with AI coding tools and agents. Use them to integrate the SDK, ask about your analytics, or look up Adapty docs without leaving your editor. This page lists what's available and who each tool is for. ## Integrate the Adapty SDK with AI Two ways to add the Adapty SDK to your app with an AI coding tool. Both work with Cursor, Claude, and other AI assistants. ### Skill-based integration The Adapty SDK integration skill runs the whole integration from your AI coding tool in one command. Use it when you want a guided, automated setup. Choose your platform: [iOS](adapty-sdk-integration-skill) · [Android](adapty-sdk-integration-skill-android) · [React Native](adapty-sdk-integration-skill-react-native) · [Flutter](adapty-sdk-integration-skill-flutter) · [Unity](adapty-sdk-integration-skill-unity) · [Kotlin Multiplatform](adapty-sdk-integration-skill-kmp) · [Capacitor](adapty-sdk-integration-skill-capacitor) ### Step-by-step integration Walk your AI tool through the integration stage by stage, feeding it the right docs in order. Use it when you want to review each step as you go. Choose your platform: [iOS](adapty-cursor) · [Android](adapty-cursor-android) · [React Native](adapty-cursor-react-native) · [Flutter](adapty-cursor-flutter) · [Unity](adapty-cursor-unity) · [Kotlin Multiplatform](adapty-cursor-kmp) · [Capacitor](adapty-cursor-capacitor) ## Manage Adapty from the command line The [Adapty Developer CLI](developer-cli-quickstart) lets you manage your Adapty entities — apps, access levels, products, paywalls, and placements — from the terminal, without opening the dashboard. Because it's a command-line tool, your AI coding agent can run it directly. ## Ask about your data Point an AI coding agent at the Export Analytics API to query your metrics in plain language — revenue, retention, LTV, and more. No MCP server required. [Ask AI about your analytics data](export-analytics-with-ai) ## Give your AI tool the Adapty docs ### Plain-text docs Every Adapty doc is available as Markdown — add `.md` to the page URL, or click **Copy for LLM** under the title. For broader context, give your tool the [`llms.txt`](https://adapty.io/docs/llms.txt) index or a platform-specific subset such as [`ios-llms.txt`](https://adapty.io/docs/ios-llms.txt). ### Context7 [Context7](https://context7.com/adaptyteam/adapty-docs) is an MCP server that serves Adapty docs to your AI tool, but it indexes only code snippets — not the full prose. Use it for quick code examples; for complete guidance, give your tool the plain-text docs above. Context7 works with Cursor, Claude Code, Windsurf, and other MCP-compatible tools. --- # File: export-analytics-with-ai --- --- title: "AI にアナリティクスデータについて質問する" description: "Export Analytics API を使用して、AIコーディングエージェントで Adapty アナリティクスを自然言語でクエリします。" --- Ask an AI coding agent about your Adapty analytics in plain language — revenue, conversions, retention, LTV — and let it pull the numbers for you. Point a tool that can make API calls at the [Export Analytics API](https://adapty.io/docs/ja/export-analytics-api.md), and it queries your metrics on demand. ## 質問できる内容 \{#what-you-can-ask-about\} Export Analytics API は、Adapty ダッシュボードのチャートで確認できる指標と同じものを返します。各指標には固有のオペレーションがあります。 | 指標 | カバー範囲 | オペレーション | | --- | --- | --- | | Revenue、MRR、ARR、ARPU | 期間・国・キャンペーン別にグループ化された収益 | [retrieveAnalyticsData](https://adapty.io/docs/ja/api-export-analytics/operations/retrieveAnalyticsData.md) | | コホートリテンション | 特定のコホートのサブスクライバーが支払いを継続する期間 | [retrieveCohortData](https://adapty.io/docs/ja/api-export-analytics/operations/retrieveCohortData.md) | | コンバージョン率 | あるステップやチャネルから次のステップに進むユーザー数 | [retrieveConversionData](https://adapty.io/docs/ja/api-export-analytics/operations/retrieveConversionData.md) | | チャーンとファネル | ユーザーが離脱する箇所と解約スピード | [retrieveFunnelData](https://adapty.io/docs/ja/api-export-analytics/operations/retrieveFunnelData.md) | | ライフタイムバリュー(LTV) | 時間経過によるユーザーセグメントあたりの平均収益 | [retrieveLTVData](https://adapty.io/docs/ja/api-export-analytics/operations/retrieveLTVData.md) | | リテンション | 一定日数後もアクティブなユーザーの割合 | [retrieveRetentionData](https://adapty.io/docs/ja/api-export-analytics/operations/retrieveRetentionData.md) | APIパラメーターとフィルターの全一覧については、[APIリファレンス](https://adapty.io/docs/ja/api-export-analytics.md)をご覧ください。 ## 始める前に \{#before-you-start\} 次の3つが必要です: - **データのある Adapty アカウント**: この API はダッシュボードのチャートと同じ指標を返すため、アプリがすでにアナリティクスを収集している必要があります。 - **シークレット API キー**: [App settings → General](https://app.adapty.io/settings/general) の **Secret key** フィールドで確認できます。キーはアプリごとに異なるため、アプリごとに別々のキーを使用してください。エージェントがチャットに貼り付けずに読み取れるよう、環境変数(例: `ADAPTY_SECRET_KEY`)に保存してください。 - **API を呼び出せる AI ツール**: Claude Code、Cursor、またはフェッチツールを備えた Claude Desktop などが使えます。claude.ai や ChatGPT のような通常のチャットツールは直接 API を呼び出せません。 ## エージェントにAPI仕様を提供する \{#give-your-agent-the-api-spec\} [OpenAPI仕様](https://adapty.io/docs/ja/api-specs/export-analytics-api.yaml)には、すべてのエンドポイント、認証ヘッダー、リクエストボディ、レスポンス例が記載されています。エージェントがこの仕様を参照することで、コードを書かなくても正しいリクエストを構築できます。 エージェントにURLで仕様を渡す: - **URLを貼り付ける**: エージェントがURLを取得できる場合は、`https://adapty.io/docs/ja/api-specs/export-analytics-api.yaml` を渡して仕様を読むよう指示してください。 - **フェッチツールを使用する**: エージェントにURLを取得するツール(例:MCP フェッチサーバー)がある場合は、同じURLを指定してください。 仕様にはベースURLとして `https://api-admin.adapty.io` が設定されているため、キーが環境に設定されていれば、エージェントは必要なものをすべて揃えています。 ## データについて質問する \{#ask-about-your-data\} スペックを読み込み、APIキーを環境変数に設定したら、取得したい指標を平易な言葉で説明してください。 プロンプトの例: ``` What was my MRR at the end of each month this year, and how does it compare to last year? Show my trial-to-paid conversion rate for the last 90 days, broken down by product. Which countries drive the most revenue from my yearly subscription? Top 10. How is week-1 retention trending for subscribers who started in the last 6 months? What's the refund rate on my annual plan since launch, by month? Compare LTV for paid-campaign users vs. organic over the last year, and export it as CSV. ``` エージェントはリクエストを適切なオペレーションにマッピングし、環境変数からキーを読み取ってデータを返します。レスポンスはデフォルトでJSONです。スプレッドシートに適したファイルが必要な場合はCSVをリクエストしてください — エージェントはリクエストボディの `format` を `csv` に設定します。 :::warning シークレットキーは環境変数に保存してください — チャットに貼り付けたり、ルールファイルにコミットしたりしないでください。キーはアプリ固有のため、漏洩した場合は **Settings → General** でローテーションしてください。[APIキーのローテーション](https://adapty.io/docs/ja/export-analytics-api-authorization.md)を参照してください。 ::: ## セッションをまたいで再利用するための初期設定 \{#set-up-once-for-repeated-use\} 毎回セットアップを繰り返さなくて済むよう、エージェントが再利用できる場所にスペックとキーを保存しておきましょう。 - **スペックリンクを保存する**: スペックのURLをエージェントのルールやメモリファイル(例:`CLAUDE.md`やCursorのルールファイル)に追加しておくと、毎セッションで自動的に読み込まれます。 - **キーを環境変数に保存する**: `ADAPTY_SECRET_KEY`をシェルプロファイルやツールのシークレットストアに保存しておけば、二度と貼り付ける手間がかかりません。 - **よく使うプロンプトを保存するか、カスタムスキルを作成する**: よく使う質問を保存済みプロンプトとして管理するか、カスタムスキルやスラッシュコマンドとしてまとめておくと、オンデマンドでレポートを実行できます。 ## 制限事項 \{#limits\} 以下の制約に注意してください。 - **レート制限**: APIはAPIキーごとに1秒あたり2リクエストまで許可されています。超過すると`429 Too Many Requests`エラーが返ります。`429`が返ったときは待ってからリトライするようエージェントに伝えてください。 - **アプリごとのキー**: 各キーは1つのアプリにのみ有効です。複数アプリのデータを取得する場合は、アプリごとに対応するキーを提供してください。 - **出力フォーマット**: レスポンスはデフォルトでJSON形式です。CSVでエクスポートするには、リクエストボディで`format`を`csv`に設定してください。 認証とリクエストのルールの詳細は、[認証とリクエスト形式](export-analytics-api-authorization)を参照してください。 --- # File: handle-webhooks-with-ai --- --- title: "ウェブフックでAdaptyのサブスクリプションイベントを処理する" description: "ウェブフックを使ってサーバーでAdaptyのサブスクリプションイベントを受信・処理する方法 — エンドポイントの設定、認証、ペイロード、テストを1ページで解説。" --- Webhookを使うと、サーバーがAdaptyのサブスクリプションイベント(購入、更新、キャンセル、請求エラー、返金)をリアルタイムで受信できます。アクセス権の付与、バックエンドとの同期、ワークフローのトリガーなどに活用できます。このガイドでは、エンドポイントの設定から検証済みの統合テストまでを1ページで説明し、AIコーディングエージェントを使ってハンドラーを自動生成する方法も紹介します。 :::tip AIコーディングエージェントを使っていますか?タイトル下の **Copy for LLM** をクリックして、このページ全体をエージェントに貼り付けてください。セットアップ、ペイロード、ハンドラーロジックがすべて含まれています。 ::: ## Adapty ウェブフックの仕組み \{#how-adapty-webhooks-work\} - **一方向かつリアルタイム**: イベントが発生すると、Adapty がサーバーに HTTP `POST` を送信します。ポーリング不要です。 - **2 種類のリクエスト**: インテグレーション保存時に送信される一回限りの確認リクエストと、継続的なサブスクリプションイベントの 2 種類があります。 - **環境ごとに 1 つの URL**: 本番環境とサンドボックス環境それぞれに別々のエンドポイントを設定します。 - **各リクエストへの応答が必要**: `2xx` ステータスをすばやく返してください。失敗した場合、Adapty はリトライします。 ## エンドポイントを構築する \{#build-your-endpoint\} 2種類のリクエストを処理する公開HTTPSエンドポイントを作成します。 - **確認リクエスト**: インテグレーションを保存したときに1回送信されます。JSONボディは空(`{}`)です。`2xx` ステータスとJSONボディを返してください。 - **サブスクリプションイベント**: イベントをボディに含む継続的な `POST` リクエストです。10秒以内に `200` を返し、重い処理は非同期で行ってください。 シークレット文字列を選んで環境変数(例:`ADAPTY_WEBHOOK_SECRET`)として保存してください。リクエストのたびに `Authorization` ヘッダーがその値と一致するか検証し、一致しない場合はリクエストを拒否します。この同じシークレットを、次のステップでダッシュボードに入力します。 ```javascript title="webhook.js" const app = express(); app.use(express.json()); const WEBHOOK_SECRET = process.env.ADAPTY_WEBHOOK_SECRET; app.post("/adapty/webhook", (req, res) => { // 1. Verify the shared secret Adapty echoes back. if (req.get("Authorization") !== WEBHOOK_SECRET) { return res.sendStatus(401); } // 2. Acknowledge fast, then process asynchronously. res.status(200).json({}); // 3. The verification request has an empty body — nothing to handle. const event = req.body; if (!event.event_type) return; switch (event.event_type) { case "subscription_started": case "subscription_renewed": case "trial_converted": // Grant or extend access. break; case "subscription_expired": case "subscription_refunded": // Revoke access. break; default: break; } }); app.listen(3000); ``` Adaptyはエンドポイントを保存した瞬間に検証リクエストを送信するため、インテグレーションを設定する前にエンドポイントをパブリックなHTTPS URLにデプロイしておいてください。 ### 主なイベントとペイロード \{#key-events-and-the-payload\} すべてのイベントは同じエンベロープを共有しています。フィールドはイベントタイプ、ストア、有効にしたオプションによって異なります。以下は `subscription_started` イベントの簡略版です。 ```json title="Example event" { "profile_id": "00000000-0000-0000-0000-000000000000", "customer_user_id": "UserIdInYourSystem", "event_type": "subscription_started", "event_datetime": "2024-11-15T10:45:36.181000+0000", "event_properties": { "store": "play_store", "currency": "USD", "price_usd": 4.99, "vendor_product_id": "onemonth_no_trial", "transaction_id": "0000000000000000", "original_transaction_id": "0000000000000000", "subscription_expires_at": "2024-12-15T10:45:36.181000+0000", "profile_event_id": "00000000-0000-0000-0000-000000000000" }, "event_api_version": 1 } ``` 最もよく扱うイベント: | イベントタイプ | 発火タイミング | | --- | --- | | `subscription_started` | ユーザーが有料サブスクリプションを開始したとき | | `subscription_renewed` | サブスクリプションが正常に更新・課金されたとき | | `subscription_renewal_cancelled` | ユーザーが自動更新をオフにしたとき(アクセスは有効期限まで継続) | | `subscription_expired` | 更新されなかったサブスクリプションの有効期限が切れてアクセスが終了したとき | | `trial_started` | ユーザーが無料トライアルを開始したとき | | `trial_converted` | トライアルが有料サブスクリプションに転換したとき | | `billing_issue_detected` | 更新時の支払いが失敗したとき | | `subscription_refunded` | サブスクリプションの購入が返金されたとき | 全イベントの一覧とフィールドの詳細については、[Webhookイベントのタイプとフィールド](https://adapty.io/docs/ja/webhook-event-types-and-fields.md)を参照してください。 :::warning `event_datetime` でイベントを並べないでください。これはイベントのビジネス上の発生時刻であるため、イベントが順序どおりに届かなかったり、同じタイムスタンプを持つ場合があります。並べ替えには自分の受信時刻を使用し、`profile_event_id` またはトランザクションIDを使って重複を排除してください。 ::: ## Adapty でウェブフックを設定する \{#configure-the-webhook-in-adapty\} 1. Adapty ダッシュボードで [Integrations → Webhook](https://app.adapty.io/integrations/customwebhook) を開きます。 2. インテグレーションをオンにします。 3. **Production endpoint URL** に、デプロイしたエンドポイントの HTTPS URL を入力します。 4. **Authorization header value for production endpoint** に、エンドポイントが検証に使用するシークレットと同じ値を入力します。Adapty はすべてのリクエストの `Authorization` ヘッダーにこの値を付与して送信します。省略可能ですが、強く推奨されます。 5. 先にサンドボックスでテストする場合は、**Sandbox endpoint URL** とその **Authorization header value** も入力します。 6. **Save** をクリックします。Adapty はすぐにエンドポイントへ検証リクエストを送信し、エンドポイントが `2xx` を返すとセットアップが完了します。 送信するイベントの選択、イベント名のマッピング、オプションフィールド(トライアル価格、過去のイベント、アトリビューション、ユーザー属性、Play Store トークン)の有効化については、[Webhook インテグレーションの設定](https://adapty.io/docs/ja/set-up-webhook-integration.md)をご参照ください。 ## AIコーディングエージェントで構築する \{#build-it-with-your-ai-coding-agent\} このガイドとリファレンスドキュメントをMarkdown形式(任意のページURLに`.md`を追加)でAIコーディングエージェントに渡し、使用しているスタックを伝えて、ハンドラーのひな形を生成させましょう。 - [Webhookイベントの種類とフィールド](https://adapty.io/docs/ja/webhook-event-types-and-fields.md) - [Webhook連携のセットアップ](https://adapty.io/docs/ja/set-up-webhook-integration.md) プロンプトの例: ``` Read these Adapty webhook docs, then write a webhook handler for my Express app: verify the Authorization header against ADAPTY_WEBHOOK_SECRET, answer the verification request, acknowledge events with 200, and grant or revoke access based on event_type. ``` The agent writes the handler code, but it can't deploy your endpoint or configure the dashboard — host the endpoint yourself and set the URL and secret in **Integrations → Webhook**. ## Webhookをテストする \{#test-your-webhook\} 本番環境に移行する前に、サンドボックスでテストしましょう: 1. 上記の手順に従って、サンドボックス用のエンドポイントとシークレットを設定します。 2. サンドボックスアプリで、購入・トライアル開始・返金などを行い、イベントをトリガーします。 3. インテグレーションの **Last sent events** セクションを開きます。正常に配信されたイベントには **Success** ステータスが表示されます。 **Sending failed** と表示されている場合、サーバーが200〜399の範囲外のステータスを返しています。ステータスにカーソルを合わせると詳細を確認できます。テストの詳細な手順については、[Webhookインテグレーションのテスト](https://adapty.io/docs/ja/test-webhook.md)をご覧ください。 ## 制限事項 \{#limits\} - **10秒以内に応答すること**: 時間内にレスポンスが返らない場合、Adapty はその試みを失敗とみなして再試行します。 - **再試行**: ステータスが 200〜404 の範囲外の場合、Adapty は指数バックオフで再試行します — 24時間以内に最大 9 回まで。 - **キャンセルの遅延**: キャンセルイベントは届くまで最大 2 時間かかる場合があります。 - **環境ごとに URL は 1 つ**: 複数のサービスにイベントを配信したい場合は、自分のバックエンドに Webhook を向け、そこからファンアウトしてください。 --- # File: server-side-api-with-ai --- --- title: "バックエンドからサブスクリプションアクセスを確認・付与する" description: "Adapty のサーバーサイド API を使って、ユーザーのサブスクリプションがアクティブかどうかを確認し、手動でアクセスを付与する方法を AI コーディングエージェントとともに解説します。" --- バックエンドから Adapty のサーバーサイド API を使って、ユーザーのアクティブなサブスクリプションを確認したり、アクセスを手動で付与したりできます。このガイドでは、最もよく使われる 2 つの呼び出し — `getProfile` と `grantAccessLevel` — を取り上げ、AI コーディングエージェントを使って自分のスタック向けに統合を実装する方法を説明します。 :::tip AI コーディングエージェントを使っていますか?タイトル下の **Copy for LLM** をクリックして、このページ全体をエージェントに貼り付けてください。必要な呼び出し、フィールド、注意点がすべて含まれています。 ::: ## 始める前に \{#before-you-start\} - **シークレット API キー**: [App settings → General](https://app.adapty.io/settings/general) の **Secret key** フィールドで確認できます。キーはアプリごとに異なります。環境変数(例: `ADAPTY_SECRET_KEY`)に保存し、`Authorization: Api-Key {key}` の形式で送信してください。 - **ベース URL**: すべてのリクエストは `https://api.adapty.io` に送信します。 - **ユーザーの識別方法**: `adapty-customer-user-id`(独自のユーザー ID — アプリでユーザーを識別している場合のみ使用可能)または `adapty-profile-id`(Adapty のプロファイル ID)のいずれかを送信します。どちらも同じように使えるので、どちらか一方を使用してください。 ## サブスクリプションを確認する \{#check-a-subscription\} ステータスを確認するには、`getProfile` を `GET` で呼び出し、ユーザー識別子をヘッダーとして渡します。リクエストボディは不要です。 ```javascript title="check-access.js" const res = await fetch("https://api.adapty.io/api/v2/server-side-api/profile/", { headers: { "Authorization": `Api-Key ${process.env.ADAPTY_SECRET_KEY}`, "adapty-customer-user-id": userId, }, }); const { data } = await res.json(); function hasActiveAccess(profile, accessLevelId = "premium") { const level = profile.access_levels?.find(a => a.access_level_id === accessLevelId); if (!level) return false; if (level.is_in_grace_period) return true; if (!level.expires_at) return true; // lifetime / non-expiring return new Date(level.expires_at) > new Date(); // not expired yet } if (hasActiveAccess(data)) { // unlock premium features } ``` SDKのプロファイルとは異なり、サーバーサイドのレスポンスには **`is_active` フィールドがありません**。ステータスは `access_levels[].expires_at` から自分で判定してください。`null` の場合は永続アクセス、未来の日付の場合はアクティブ、過去の日付の場合は期限切れです。`is_in_grace_period` はアクティブとして扱ってください。プロファイルおよびアクセスレベルのフィールドの詳細については、[getProfile](https://adapty.io/docs/ja/api-adapty/operations/getProfile.md) を参照してください。 ## アクセスレベルを手動で付与する \{#grant-access-manually\} 購入なしで有料機能を解放したい場合(プロモーションコード、投資家・ベータアクセス、サポート対応など)は、`grantAccessLevel` を `POST` で呼び出します。 ```javascript title="grant-access.js" await fetch("https://api.adapty.io/api/v2/server-side-api/purchase/profile/grant/access-level/", { method: "POST", headers: { "Authorization": `Api-Key ${process.env.ADAPTY_SECRET_KEY}`, "adapty-customer-user-id": userId, "Content-Type": "application/json", }, body: JSON.stringify({ access_level_id: "premium" }), // 一時的なアクセスには "expires_at" を追加 }); ``` - **アクセスレベルはダッシュボード(**Access levels**)に事前に存在している必要があります** — `access_level_id` はその識別子であり、新しい名前ではありません。 - **手動付与はアナリティクスに表示されません**。Webhook インテグレーションと Event Feed にのみ配信されるため、収益やコンバージョンのチャートには反映されません。 リクエストとレスポンスの詳細については、[grantAccessLevel](https://adapty.io/docs/ja/api-adapty/operations/grantAccessLevel.md) を参照してください。 ## AIコーディングエージェントで構築する \{#build-it-with-your-ai-coding-agent\} このガイドとAPIスペックをMarkdown形式(任意のページURLに`.md`を追加)でAIコーディングエージェントに渡し、使用するスタックを伝えれば、あとはエージェントがAPIコールを書いてくれます: - [OpenAPI仕様](https://adapty.io/docs/ja/api-specs/adapty-api.yaml) - [getProfile](https://adapty.io/docs/ja/api-adapty/operations/getProfile.md) - [grantAccessLevel](https://adapty.io/docs/ja/api-adapty/operations/grantAccessLevel.md) プロンプト例: ``` Using the Adapty server-side API spec, write backend functions to check whether a user has an active "premium" access level (GET /profile/, derive status from expires_at — there's no is_active field) and to grant it (grantAccessLevel). Authenticate with ADAPTY_SECRET_KEY and identify users by adapty-customer-user-id. ``` The agent writes the code, but it can't run your backend or set your keys — you provide the secret key and the user identifiers. ## 制限 \{#limits\} - **レート制限**: アプリごとに1分あたり最大40,000リクエスト。 - **アプリ固有のキー**: 各キーは1つのアプリにのみ使用可能です。アプリごとに対応するキーを使用してください。 - **識別子の必須指定**: すべてのリクエストには `adapty-customer-user-id` または `adapty-profile-id` が必要です。 --- # File: test-purchases-in-sandbox --- --- title: "サンドボックステスト" description: "サンドボックス環境で購入をテストして、スムーズなトランザクションを確認しましょう。" --- Adapty ダッシュボードとモバイルアプリの設定が完了したら、アプリ内課金のテストを実施しましょう。 **注意:** テストツールはいずれも、プロダクトの購入テスト時にユーザーへの課金は行いません。App Store はテスト環境での購入や返金に関するメールを送信しません。 --- no_index: true --- import Callout from '../../../components/Callout.astro'; <Callout type="note"> **サンドボックスのトランザクションはすべてのアナリティクスチャートから除外されます。** 個々のプロファイルページやイベントフィードには引き続き表示されます。 </Callout> :::info アプリ内課金テストを進めるにあたり、以下を確認してください。 - ストア連携、プロダクトの追加、Adapty SDK の連携に関する[クイックスタート](quickstart)ガイドが完了していること。 - プロダクトが App Store Connect で [**Ready to submit**](InvalidProductIdentifiers#step-2-check-products) としてマークされていること。 ::: ## サンドボックステスト \{#sandbox-testing\} <div style={{ maxWidth: '560px', margin: '0 auto 2rem', position: 'relative', aspectRatio: '16/9', width: '100%' }}> <iframe style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%' }} src="https://www.youtube.com/embed/hq4PRU-vuik?si=m5F5Sj6iLEJ-2q6n" title="YouTube video player" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerPolicy="strict-origin-when-cross-origin" allowFullScreen /> </div> :::info アプリ内課金のテストは実機で行うことをお勧めします。サンドボックス購入はシミュレーターでも実行できますが、支払いダイアログや生体認証プロンプトを含むすべてのフローを完全にテストするには実機が必要です。 ::: アプリ内課金のテスト方法は主に 2 つあります。 - **Xcode でビルドしてテストデバイスで実行する**: 開発者や QA エンジニアに適しています。 - **TestFlight でサンドボックステストアカウントを使用する**: その他の方に適しています。 どちらの方法も以下のガイドで説明しています。 ### ステップ 1. App Store Connect でサンドボックステストアカウントを作成する \{#step-1-create-sandbox-test-account-in-app-store-connect\} :::warning 購入履歴をクリーンな状態に保つため、新しいサンドボックステストアカウントを作成してください。既存のアカウントを再利用すると、以前に購入したプロダクトが引き続き利用可能なため、それらのプロダクトの購入テストが行えません。 ::: 新しいサンドボックステストアカウントは数クリックで作成できます。 1. App Store Connect の [**Users and Access** > **Sandbox** > **Test Accounts**](https://appstoreconnect.apple.com/access/users/sandbox) に移動し、**+** をクリックします。 <img src="/assets/shared/img/add-sandbox-user.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. テストユーザーの詳細を入力します。テストする **Country or Region** を必ず設定してください。これはリージョンのプロダクト利用可否や購入通貨に影響します。 :::tip - Gmail や iCloud をお使いの場合は、[プラス記号サブアドレッシング](https://www.wikihow.com/Use-Plus-Addressing-in-Gmail)を使って既存のメールアドレスを再利用できます。 - 実際には存在しないランダムなメールアドレスも使用できますが、後でテストデバイスにサインインする際に 2 段階認証(2FA)を拒否するようにしてください。 ::: <img src="/assets/shared/img/57c3a7c-apple_new_test_account.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. **Create** をクリックします。 ### ステップ 2. デベロッパーモードを有効にする \{#step-2-enable-the-developer-mode\} :::note テストデバイスでデベロッパーモードが**すでに有効になっている**場合、または **Mac デバイスをお持ちでない**場合は、このステップをスキップしてください。 ::: Xcode がインストールされた Mac とテストデバイスのケーブルが必要です。 1. Mac で Xcode を開きます。TestFlight でアプリ内課金をテストする場合は、Xcode がインストールされていれば十分で、アプリを開く必要はありません。 2. ケーブルを使ってテストデバイスを Mac に接続します。 3. テストデバイスで **Settings > Privacy & Security > Developer Mode** に移動し、**Developer Mode** をオンにします。 ### ステップ 3. TestFlight からアプリをダウンロードする \{#step-3-download-the-app-from-testflight\} :::info このステップは TestFlight でテストする場合にのみ適用されます。Xcode でアプリをビルドする場合はスキップしてください。 ::: TestFlight へのアプリの提出については、[Apple のドキュメント](https://developer.apple.com/documentation/StoreKit/testing-in-app-purchases-with-sandbox#Prepare-for-sandbox-testing)を参照してください。 TestFlight アプリをダウンロードする前に、テストデバイスで本番の Apple アカウントにサインインしていることを確認してください。その後、TestFlight からテストするアプリをダウンロードします。 :::danger ダウンロードしたらアプリを開かないでください。次のステップに進んでください。 誤って開いてしまった場合は、テストデバイスからアプリを削除して再度ダウンロードしてください。そうしないと購入履歴がクリーンな状態にならず、アプリ内課金のテストでエラーが発生する可能性があります。 ::: ### ステップ 4. サンドボックステストアカウントに切り替える \{#step-4-switch-to-sandbox-test-account\} <Details> <summary>Mac をお使いでない方へ</summary> macOS をお使いでない場合、Xcode を使ってサンドボックスアカウントに切り替えることはできません。ただし、テストデバイス上で直接切り替えることができます。 1. テストデバイスで **Settings > Your Apple Account > Media & Purchases** に移動します。 2. ポップアップメニューから **Sign Out** を選択します。 3. TestFlight からダウンロードしたアプリを開き、プロダクトを購入しようとします。 4. サインインを求められたら、サンドボックスアカウントの認証情報を入力してサンドボックス環境に切り替えます。 </Details> サンドボックスアカウントに切り替えるには: 1. テストデバイスで **Settings > Your Apple Account > Media & Purchases** に移動します。 2. ポップアップメニューから **Sign Out** を選択します。 3. **Settings > Developer** に移動します。**Developer** オプションが表示されない場合は、[ステップ 2 で有効にしているか](#step-2-enable-the-developer-mode)確認してください。 <img src="/assets/shared/img/devmode.png" style={{ border: '1px solid #727272', /* border width and color */ width: '400px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **Sandbox Apple Account** セクションまでスクロールし、**Sign In** をタップします。 <img src="/assets/shared/img/sandbox-acc.png" style={{ border: '1px solid #727272', /* border width and color */ width: '400px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. サンドボックス Apple アカウントの認証情報でサインインします。 ### ステップ 5. 購入履歴をクリアする \{#step-5-clear-purchase-history\} 新しいサンドボックステストアカウントを作成して切り替えたばかりの場合は、このステップをスキップできます。このステップは同じサンドボックステストアカウントを使って繰り返しテストする場合にのみ適用されます。 1. テストデバイスで **Settings > Developer > Sandbox Apple Account** に移動します。 2. ポップアップメニューから **Manage** を選択します。 3. **Account Settings** に移動し、**Clear Purchase History** をタップします。 :::danger このステップは同じサンドボックステストアカウントを使ってテストを繰り返すたびに必要です。この場合、[サンドボックステストアカウントからサインアウト](#step-4-switch-to-sandbox-test-account)した後、再度サインインしてテストデバイス上の購入履歴キャッシュをクリアする必要があります。 ::: ### ステップ 6. Xcode でビルドして実行する \{#step-6-build-in-xcode-and-run\} :::info このステップは Xcode ビルドでテストする場合にのみ適用されます。TestFlight を使用する場合はスキップしてください。 ::: 1. テストデバイスを Mac に接続します。 2. Xcode を開きます。 3. ツールバーの **Run** をクリックするか、**Product > Run** を選択して、接続されたデバイスでアプリをビルドして実行します。 ビルドが成功すると、Xcode はデバイス上でアプリを起動し、デバッグエリアにデバッグセッションを開きます。 これでデバイス上でのテストの準備が整いました。 ### ステップ 7. テスト購入を行う \{#step-7-make-test-purchase\} アプリを開き、ペイウォールからテスト購入を行います。 完了したら、[テスト購入の検証](validate-test-purchases)の記事で結果を確認してください。 ### ステップ 8. テストを続ける \{#step-8-keep-testing\} テスト環境の準備が整いました。再度テストしたい場合は、[サンドボックスアカウントの購入履歴をクリア](https://developer.apple.com/help/app-store-connect/test-in-app-purchases/manage-sandbox-apple-account-settings/)してください。 ## テストに関する問題 \{#testing-issues\} 以下はアプリテスト時によく発生する問題です。 ### TestFlight の問題 \{#testflight-issues\} **サンドボックステストアカウントなしで TestFlight を使用している場合**は購入履歴をクリアできないため、さまざまな問題や誤ったテスト結果が生じます。 誤って[サンドボックステストアカウントへの切り替え](#step-4-switch-to-sandbox-test-account)を忘れてアプリを一度でも開いてしまうと、TestFlight は購入履歴を本番の Apple アカウントに紐付けてしまい、予期せぬ問題が発生します。 修正するには、以下の手順に従ってください。 1. テストデバイスからアプリを削除します。 2. [サンドボックステスト](#sandbox-testing)の手順に従います。 :::note アプリを再インストールするだけでなく、サンドボックステストアカウントに切り替え、購入履歴をクリアし、サンドボックステストアカウントを使ってアプリを起動することが重要です。 ::: ### 共有アクセスレベルの問題 \{#shared-access-levels-issues\} 同じサンドボックステストアカウントを使って繰り返しテストすると、テストユーザーの[共有アクセスレベル](sharing-paid-access-between-user-accounts)で予期しない動作が発生することがあります。 ユーザーが継承されたアクセスレベルを持っているか確認するには、Adapty ダッシュボードの [Profiles & Segments](https://app.adapty.io/profiles/users) からユーザーのプロファイルを開いてください。 <img src="/assets/shared/img/profile-access-level-origin.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ユーザーが継承されたアクセスレベルを持っている場合は、正確なテスト結果を得るために以下の手順に従ってください。 1. 親プロファイルを削除します。 2. テストデバイスからアプリを削除します。 3. [TestFlight からアプリをダウンロードします](#step-3-download-the-app-from-testflight)。 4. [サンドボックステストアカウントに切り替えます](#step-4-switch-to-sandbox-test-account)。 5. [購入履歴をクリアします](#step-5-clear-purchase-history)。 6. [アプリを開いてテスト購入を行います](#step-6-make-test-purchase)。 :::note 購入履歴のクリアがストア側の購入をリセットします。親プロファイルの削除は Adapty 側の記録を削除するだけです。再利用したアカウントがアクセスを保持し続ける理由と、実際に機能するリセット方法については、[テスターのサブスクリプションのリセット](#resetting-a-testers-subscription)を参照してください。 ::: ### TestFlight でのアプリの更新 \{#updating-app-in-testflight\} TestFlight アプリが更新された場合: 1. テストデバイスからアプリを削除します。 2. [TestFlight からアプリをダウンロードします](#step-3-download-the-app-from-testflight)。 3. [サンドボックステストアカウントに切り替えます](#step-4-switch-to-sandbox-test-account)。 4. [購入履歴をクリアします](#step-5-clear-purchase-history)。 5. [アプリを開いてテスト購入を行います](#step-6-make-test-purchase)。 ## テスターのサブスクリプションのリセット \{#resetting-a-testers-subscription\} サンドボックス環境では、購入は Adapty プロファイルではなく **Apple サンドボックスアカウント**に紐付けられます。プロファイルに対して行う操作(削除やアクセスレベルの編集)は、ストアアカウントから購入を削除しません。次回の再インストールや同期時に、SDK は同じトランザクションを再紐付けし、テスターは再びアクセスを得ます。 以下の表は、各リセット操作が何を変更するか、またその後テスターがどうなるかを示しています。 | 操作 | Adapty プロファイル | Apple サンドボックスアカウント | テスターのその後のアクセス | | :--- | :--- | :--- | :--- | | Adapty ダッシュボードでプロファイルを削除 | 削除済み | 変更なし | **復元される** — 再インストール時に新しいプロファイルが同じトランザクションチェーンを再紐付け | | [Delete profile API](api-adapty/operations/deleteProfile) でプロファイルを削除 | 削除済み | 変更なし | **復元される** — ダッシュボードでの削除と同じ | | **Add access level** で過去の有効期限を追加 | 次の同期時に上書き | 変更なし | 次の更新時に**復元される** — 有効なサブスクリプションが将来の有効期限を再適用 | | [Revoke access level API](api-adapty/operations/revokeAccessLevel) を呼び出す | 即時失効、`access_level_updated`(`is_active=false`)が発火 | 変更なし | 次の更新や再インストール時に**復元される** — サンドボックスのリセットとして信頼性が低い | | サンドボックスアカウントでサブスクリプションをキャンセル | 直接変更なし | サブスクリプションキャンセル済み | 更新が停止し、現在の期間が終了するとアクセスが終了。テスターは再度プロダクトを購入可能 | | 新しい Apple サンドボックスアカウントでサインイン | 新しいプロファイル | 新しい空のアカウント | **クリーン** — 繰り返しテストに推奨 | ### テスターをクリーンな状態にリセットする \{#reset-a-tester-to-a-clean-state\} 購入フローの繰り返しテストには、テストごとに新しい Apple サンドボックスアカウントを使用してください。アカウントの作成は[ステップ 1](#step-1-create-sandbox-test-account-in-app-store-connect)、デバイスでの切り替えは[ステップ 4](#step-4-switch-to-sandbox-test-account) に従ってください。既存のサンドボックスアカウントを再利用する場合は、先に[購入履歴をクリア](#step-5-clear-purchase-history)してください。Adapty プロファイルを削除してもクリアされません。 ### 既存テスターのアクセスを削除する \{#remove-access-from-an-existing-tester\} テスターのアクセスを削除するには、有効期限を過去に設定したり Revoke access level API を呼び出したりしないでください。サンドボックスでは、サブスクリプションは数分ごとに自動更新されます。更新のたびに同じトランザクションチェーンに将来の有効期限が復元されるため、アクセスは自動的に復活します。Revoke access level API は `access_level_updated`(`is_active=false`)イベントを発火しますが、次の更新でそれが上書きされます。 アクセスを実際に停止するには、ストア側でサブスクリプションをキャンセルしてください。テストデバイスで **Settings > Developer > Sandbox Apple Account** に移動し、**Manage** を選択して、サブスクリプションをキャンセルします。更新が停止し、現在の期間が終了するとアクセスが終了します。 ### プロファイルを削除するとアクセスが復活する理由 \{#why-deleting-the-profile-brings-access-back\} テスターがアプリを再インストールすると、Adapty はサンドボックスアカウントの購入履歴を受け取り、新しいインストールを既存の購入に紐付けます。購入は削除したプロファイルではなく、ストアアカウントに紐付いています。 - **匿名プロファイル**: `customer_user_id` なしで再インストールすると、[有料アクセス共有](sharing-paid-access-between-user-accounts)の設定に関わらず、常にストアアカウントのアクセスレベルを継承します。 - **識別済みプロファイル**: アクセスが新しい `customer_user_id` に引き継がれるかどうかは、有料アクセス共有の設定によります。 Adapty がこれらのプロファイルをチェーンとして紐付ける仕組みについては、[プロファイルの仕組み](how-profiles-work#parent-and-inheritor-profiles)を参照してください。 ## テストサブスクリプション \{#test-subscriptions\} サンドボックステストアカウントを使ってアプリをテストする際、サンドボックス内の各テスターのサブスクリプション更新レートを設定できます。サブスクリプション更新レートの編集について詳しくは、[Apple の公式ドキュメント](https://developer.apple.com/help/app-store-connect/test-in-app-purchases/manage-sandbox-apple-account-settings)を参照してください。 デフォルトでは、サブスクリプションは停止するまで最大 12 回更新されます。スケジュールは以下の通りです。 | サブスクリプション期間 | 1 週間 | 1 ヶ月 | 2 ヶ月 | 3 ヶ月 | 6 ヶ月 | 1 年 | | :--- | :--- | :--- | :--- | :--- | :--- | :--- | | サブスクリプション更新速度 | 3 分 | 5 分 | 10 分 | 15 分 | 30 分 | 1 時間 | | 請求リトライ期間 | 10 分 | 10 分 | 10 分 | 10 分 | 10 分 | 10 分 | | 請求グレース期間 | 3 分 | 5 分 | 5 分 | 5 分 | 5 分 | 5 分 | :::note テストトランザクションが [Event feed](validate-test-purchases) に表示されるまで最大 10 分かかることに注意してください。 ::: サンドボックスは、更新・請求リトライ・グレース期間のアプリとバックエンドの処理を確認するために使用してください。本番環境の更新タイミングを予測するためのものではありません。上記の加速・上限付きスケジュールは本番環境とは異なります。バックエンドテスト用にサーバーでトランザクションを再実行するには、[Set transaction API](api-adapty/operations/setTransaction) を使用してください。 ## テストオファー \{#test-offers\} オファーのテストでは、適格性が正しく機能するために、すべてのユーザーレシートを削除する必要があります。 オファーをテストする最も確実な方法は、まったく新しい[サンドボックステストアカウント](#step-1-create-sandbox-test-account-in-app-store-connect)を使用することです。同じサンドボックステストアカウントを使って繰り返しテストすると、予期しない動作が発生する可能性があります。 :::danger 同じサンドボックステストアカウントを使って繰り返しテストする場合は、適格性関連の問題を避けるため、必ず[購入履歴をクリア](#step-5-clear-purchase-history)してください。 ::: --- # File: local-sk-files --- --- title: "XcodeでのStoreKitテスト" description: "サンドボックス環境でアプリ内課金をテストして、スムーズなトランザクションを確認しましょう。" --- XcodeでのStoreKitテストを使用すると、サンドボックスアカウントを設定することなく、アプリ内課金をローカルでテストできます。 このテストを行うには、次の手順が必要です: 1. [Adaptyでプロダクトを作成し](quickstart-products)、**App Store product ID** を割り当てます。 2. Xcodeで、ローカルの [StoreKit設定ファイル](https://developer.apple.com/documentation/xcode/setting-up-storekit-testing-in-xcode) を作成し、プロダクトを追加します。プロダクトIDは、AdaptyのApp Store product IDと同じである必要があります。 3. StoreKit設定ファイルをビルドスキーマに追加し、アプリをビルドします。エミュレータまたはデバイスで起動してください。 ## XcodeでのStoreKitテストを使うべきか? \{#should-i-use-storekit-testing-in-xcode\} このテスト方法は、ビルドをその場でテストしたい、またはXcodeの機能を使ってさまざまな購入シナリオをテストしたいアプリ開発者に最も便利です。 ただし、このテストはローカルで行われるため、Adaptyダッシュボードには変更が表示されないことを覚えておいてください。本番環境でアプリを公開する前に、[サンドボックス環境](test-purchases-in-sandbox)を使用して[プロファイルの操作](ios-quickstart-identify)をテストすることをおすすめします。 StoreKitテストを**使うべき**場合: - 購入ロジックをテストしたい - Xcodeのツールを使ってさまざまな購入シナリオを再現したい(例:キャンセルされた支払いや返金) - エミュレータを使ってテストしたい StoreKitテストを**使うべきでない**場合: - プロファイル関連のロジックをテストしたい - アプリ内での操作がAdaptyダッシュボードに反映されるか確認したい - 開発チーム以外とアプリを共有してテストしたい ## ステップ1. StoreKit設定ファイルを作成する \{#step-1-create-a-storekit-configuration-file\} StoreKit設定ファイルを作成するには、Xcodeで以下の手順を実行します: 1. **File > New > File from template** をクリックします。次に、**StoreKit Configuration File** を選択して **Next** をクリックします。 2. ファイル名を入力します。次に、App Store Connectにすでにプロダクトがあるかどうかに応じて: - **Sync this file with an app in App Store Connect** を選択:App Store Connectのすべてのプロダクトを含む設定ファイルを作成し、ローカルでテストできるようにします。 - **Sync this file with an app in App Store Connect** を選択しない:空の設定ファイルを作成し、プロダクトを手動で追加する必要があります。 **Next** をクリックします。 3. アプリをターゲットとして追加しないでください。そのまま進んでください。App Store Connectから同期されたプロダクトを使用している場合は、[ステップ2](#step-2-add-the-configuration-file-to-the-build-scheme)に進んでください。 4. App Store Connectからプロダクトを同期していない場合は、左下の **+** をクリックして、プロダクトタイプを選択します。 5. サブスクリプショングループ名を入力し、**Next** をクリックします。 6. 参照名を入力します。**Product ID** フィールドに、AdaptyのプロダクトのApp Store product IDを入力します。 7. 設定ファイルで価格、オファー、その他のプロダクト設定を構成します。または、さらにプロダクトを追加します。 ## ステップ2. 設定ファイルをビルドスキームに追加する \{#step-2-add-the-configuration-file-to-the-build-scheme\} この設定ファイルを使ってアプリをビルドするには、ビルドスキームに追加する必要があります。テスト用と本番用のスキームを分けるのがベストプラクティスなので、テスト用に新しいスキームを作成することをおすすめします: 1. 上部のアプリ名をクリックして、**New scheme** を選択します。 2. スキームの名前を入力し、**OK** をクリックします。 3. アプリ名を再度クリックし、**Edit scheme** を選択します。**StoreKit configuration** でローカルの設定ファイルを選択すると、ビルド時に使用されます。 ## ステップ3. ビルドとテスト \{#step-3-build--test\} これで、App Storeバックエンドに接続することなくアプリをビルドし、アプリ内課金をテストできます。プロダクトを購入し、ローカルでアクセスレベルを取得できます。これらの変更はAdaptyダッシュボードには反映されませんが、有料機能のアンロックをローカルでテストすることは引き続き可能です。 XcodeでのStoreKitテストで利用できる他の機能については、[こちら](https://developer.apple.com/documentation/xcode/testing-in-app-purchases-with-storekit-transaction-manager-in-code)をご覧ください。 --- # File: testing-on-android --- --- title: "Google Play StoreでのIn-App Purchaseのテスト" description: "AdaptyでAndroidのサブスクリプション購入をテストする方法。" --- AndroidアプリのIn-App Purchase(IAP)テストは、アプリを一般公開する前の重要なステップです。サンドボックステストは、ユーザーに実際の料金を請求することなく、IAPを安全かつ効率的にテストできる方法です。このガイドでは、Google Play StoreでAndroid向けにIAPのサンドボックステストを行う手順を説明します。 --- no_index: true --- import Callout from '../../../components/Callout.astro'; <Callout type="note"> **サンドボックスのトランザクションはすべてのアナリティクスチャートから除外されます。** 個々のプロファイルページやイベントフィードには引き続き表示されます。 </Callout> ## テスト環境 \{#testing-environment\} Androidアプリの最適なパフォーマンスを確認するには、エミュレーターではなく実機でテストすることを推奨します。エミュレーターでのテストに成功した実績もありますが、Googleは実機の使用を推奨しています。 エミュレーターを使用する場合は、Google Playがインストールされていることを確認してください。これにより、アプリが正常に動作しているかどうかを確認しやすくなります。 ## 1. アプリテスト用のテストアカウントを設定する \{#1-set-up-test-account-for-app-testing\} 開発の後半段階でスムーズにテストを行うため、アプリ内課金テスト用のテストユーザーを事前に設定しておく必要があります。このユーザーは、Androidテストデバイスで最初にログインするアカウントになります。 Androidデバイスのプライマリアカウントは、端末の初期化(すべてのデータが消去されます)を行わないと変更できません。そのため、初期化が必要にならないよう、テストユーザーアカウントを適切に設定することが重要です。 :::important テストアカウントの設定方法は、使用するデバイスによって異なります。 - テスト専用デバイスがある場合は、**別のテストアカウント(新しいGmailアカウント)**を作成してください。 - テスト専用デバイスがない場合は、**個人アカウント**を使用し、一時的に**ライセンステスト**を有効にすることができます。 - Androidデバイスをまったく持っていない場合は、**別のテストアカウントを作成してエミュレーターで使用**できます。ただし、この方法では実機固有の問題をすべて検出できるわけではないため、推奨はしません。 ::: ## 2. ライセンステストを有効にする \{#2-enable-license-testing\} テストユーザーアカウントを設定したら、アプリのライセンステストを設定する必要があります。以下の手順に従ってください。 1. Google Play Consoleのサイドバーで **Settings** に移動し、**Monetization** セクションの **License testing** を選択します。 <img src="/assets/shared/img/android-license-testing.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. 既存のライセンステスターリストを選択するか、新しいリストを作成します。 <img src="/assets/shared/img/android-testers.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. テストに使用するアカウントをリストに追加して変更を保存します。チームメンバーもテストを行う場合は、メールアドレスをリストに追加することでグループ全体にアクセスを付与できます。 <img src="/assets/shared/img/android-list.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## 3. クローズドトラックを作成してテストアカウントを追加する \{#3-create-closed-track-and-add-test-account-to-it\} テストを開始するには、署名済みバージョンのアプリをクローズドトラックに公開する必要があります。 1. アプリを開き、メニューから **Test and release > Testing > Closed testing** を選択します。そこで **Create track** をクリックします。 <img src="/assets/shared/img/android-closed-testing.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. クローズドテストトラック名を入力し、**Create track** をクリックします。 3. テスタリストをトラックに追加します。 4. **How testers join your test** セクションからリンクをコピーし、テストアカウントでログインしているデバイスに送信します。テストデバイスでリンクを開き、そのユーザーをテスターとして登録します。 <img src="/assets/shared/img/android-link.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> :::warning テストを正常に行うために、以下の点に注意してください。 - オプトインURLを開くと、Playアカウントがテストモードとしてマークされます。この手順を完了しないと、プロダクトが読み込まれません。 - 開発者がテストビルドに異なるアプリケーションIDを使用することがよくありますが、Google Play ServicesはアプリケーションIDを使用してアプリ内課金を検索するため、問題が発生します。 - テストデバイスにPINが設定されていない場合、テストユーザーが消耗型アイテムを購入できるにもかかわらず、サブスクリプションを購入できないケースがあります。この場合、「Something went wrong」という不明なメッセージが表示されることがあります。テストデバイスにPINが設定されており、Google Play Storeにログインしていることを確認してください。 ::: ## 4. 署名済みAPKをクローズドトラックにアップロードする \{#4-upload-a-signed-apk-to-the-closed-track\} 署名済みAPKを生成するか、Android App Bundleを使用して、先ほど作成したクローズドトラックに署名済みAPKをアップロードします。リリースをロールアウトする必要はありません。APKをアップロードするだけです。詳細については、[こちら](https://support.google.com/googleplay/android-developer/answer/9859348?visit_id=638929100639477968-3849460621&rd=1)のサポート記事を参照してください。 :::important アプリが新しい場合は、自分の国や地域でアプリを利用可能にする必要があるかもしれません。そのためには、**Testing > Closed testing** に移動し、テストトラックをクリックして、**Countries/regions** で希望する国や地域を追加してください。 ::: ## 5. アプリ内課金をテストする \{#5-test-in-app-purchases\} APKをアップロードしたら、リリースの処理が完了するまで数分お待ちください。その後、テストデバイスを開き、テスタリストに追加したメールアカウントでサインインします。本番アプリと同様にアプリ内課金をテストできます。 <img src="/assets/shared/img/a8d2da9-image.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## 関連情報 \{#read-more\} AndroidアプリのIn-App Purchaseテストについて詳しく知るには、以下のリソースをご覧ください。 - [サンドボックスでの更新期間](https://developer.android.com/google/play/billing/test#subs) - [買い切り購入のテスト](https://developer.android.com/google/play/billing/test#one-time) --- # File: validate-test-purchases --- --- title: "テスト購入の検証" description: "Adaptyでテスト購入を検証し、スムーズなトランザクションを確保しましょう。" --- モバイルアプリを本番環境にリリースする前に、アプリ内課金を十分にテストすることが重要です。詳しいテスト手順については、[Apple App Storeでのアプリ内課金のテスト](test-purchases-in-sandbox)および[Google Play Storeでのアプリ内課金のテスト](testing-on-android)をご参照ください。テストを開始したら、テスト購入が成功しているかどうかを確認する必要があります。 モバイルデバイスでテスト購入を行うたびに、Adapty ダッシュボードの[**Event Feed**](https://app.adapty.io/event-feed)で対応するトランザクションを確認してください。購入が **Event Feed** に表示されない場合、Adaptyによってトラッキングされていません。 ## テスト購入が成功した場合 \{#test-purchase-is-successful\} テスト購入が成功すると、そのトランザクションイベントが **Event Feed** に表示されます。 <img src="/assets/shared/img/9ade2d5-event_feed_sandbox.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> トランザクションが期待どおりに動作している場合は、[リリースチェックリスト](release-checklist)に進み、その後アプリのリリースを行ってください。 ## テスト購入が成功しなかった場合 \{#test-purchase-is-not-successful\} 10分以内にトランザクションイベントが表示されない場合や、モバイルアプリでエラーが発生した場合は、[トラブルシューティング](troubleshooting-test-purchases)およびエラーハンドリングに関する記事([iOS向け](ios-sdk-error-handling)、[Android向け](android-sdk-error-handling)、[React Native向け](react-native-handle-errors)、[Flutter向け](error-handling-on-flutter-react-native-unity)、[Unity向け](unity-handle-errors)、[Kotlin Multiplatform向け](kmp-handle-errors))を参照して、解決策を探してください。 <img src="/assets/shared/img/31a79b2-no_events.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> --- # File: troubleshooting-test-purchases --- --- title: "テスト購入のトラブルシューティング" description: "Adaptyでのテスト購入をトラブルシューティングし、アプリ内トランザクションに関する一般的な問題を解決する方法を解説します。" --- トランザクションの問題が発生した場合は、まず[リリースチェックリスト](release-checklist)に記載されているすべての手順を完了しているかご確認ください。すべての手順を完了しても問題が解決しない場合は、以下のガイダンスに従って対処してください。 ## モバイルアプリでエラーが返される \{#an-error-is-returned-in-the-mobile-app\} お使いのプラットフォームのエラーリストをご参照ください: [iOS向け](ios-sdk-error-handling)、[Android向け](android-sdk-error-handling)、[React Native向け](react-native-troubleshoot-purchases)、[Flutter](error-handling-on-flutter-react-native-unity)、[Unity](unity-troubleshoot-purchases)。記載の推奨事項に従って問題を解決してください。 ## モバイルアプリでエラーが返されないのにイベントフィードにトランザクションが表示されない \{#transaction-is-absent-from-the-event-feed-although-no-error-is-returned-in-the-mobile-app\} この問題を解決するには、以下の点をご確認ください。 1. **iOS の場合**: シミュレーターではなく実機を使用していることを確認してください。 2. アプリの `Bundle ID`/`Package name` が [**App settings**](https://app.adapty.io/settings/general) に設定されているものと一致していることを確認してください。 3. アプリ内の `PUBLIC_SDK_KEY` が Adapty ダッシュボードの **Public SDK key** と一致していることを確認してください: [**App settings** -> **General** タブ -> **API keys** セクション](https://app.adapty.io/settings/general)。 4. サンドボックスアカウントを使用していることを確認してください([ローカル StoreKit 設定ファイル](local-sk-files)ではなく)。以前にローカル StoreKit 設定ファイルをテストに使用していた場合は、現在のビルドでそれを使用していないことを確認してください。 ## テスト用プロファイルにイベントが表示されない \{#no-event-is-present-in-my-testing-profile\} これは正常な動作です。新しいユーザープロファイルレコードは、以下のタイミングで Adapty に自動作成されます。 - ユーザーが初めてアプリを起動したとき - ユーザーがアプリからログアウトしたとき **この動作の理由:** すべてのトランザクションとイベントは、最初のトランザクションを生成したプロファイルに紐付けられます。これにより、トランザクション履歴全体(トライアル、購入、更新)が同じプロファイルにリンクされ続けます。 **表示される内容:** 新しいプロファイルレコード(「非オリジナルプロファイル」と呼ばれます)はイベントなしで表示されることがありますが、アクセスレベルは保持されます。`access_level_updated` イベントが表示される場合があります。これは期待される動作です。 **テスト時の注意:** 複数のプロファイルが作成されないようにするため、アプリを再インストールするたびに新しいテストアカウント(サンドボックス Apple ID)を作成してください。 詳細については、[プロファイルの作成](how-profiles-work#profile-creation)をご覧ください。 以下は非オリジナルプロファイルの例です。**User history** にイベントがなく、アクセスレベルが設定されていることに注目してください。 <img src="/assets/shared/img/98d0dad-non-original_profile.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## App Store Connect で設定した実際の価格が反映されない \{#prices-do-not-reflect-the-actual-prices-set-in-app-store-connect\} サンドボックスおよびアプリ内課金にサンドボックス環境を使用する TestFlight では、価格の正確さよりも購入フローが正しく機能しているかどうかを確認することが重要です。Apple の API は、デバイスやアカウントに異なる地域が設定されている場合など、不正確なデータを返すことがあります。価格はストアから直接取得されるものであり、Adapty のバックエンドは購入価格に一切影響を与えないため、Adapty を通じた購入テスト中の価格の不正確さは無視していただいて構いません。 そのため、価格の正確さよりも購入フロー自体のテストを優先し、意図した通りに機能していることを確認してください。 ## イベントフィードのトランザクション時刻が正しくない \{#the-transaction-time-in-the-event-feed-is-incorrect\} **Event Feed** は **App Settings** で設定されたタイムゾーンを使用します。イベントのタイムゾーンをローカル時刻に合わせるには、[**App settings** -> **General** タブ](https://app.adapty.io/settings/general)で **Reporting timezone** を変更してください。 ## ペイウォールとプロダクトの読み込みに時間がかかる \{#paywalls-and-products-take-a-long-time-to-load\} この問題は、テストアカウントのトランザクション履歴が長い場合に発生することがあります。[App Store Connect でサンドボックステストアカウント(サンドボックス Apple ID)を作成する](test-purchases-in-sandbox#step-1-create-sandbox-test-account-in-app-store-connect)セクションに記載の通り、毎回新しいテストアカウントを作成することを強くお勧めします。 新しいアカウントを作成できない場合は、iOS デバイスで以下の手順に従って現在のアカウントのトランザクション履歴を消去できます。 1. **設定**を開き、**App Store** をタップします。 2. **サンドボックス Apple ID** をタップします。 3. ポップアップで **管理** を選択します。 4. **アカウント設定**ページで **購入履歴を消去** をタップします。 詳細については、[Apple Developer ドキュメント](https://developer.apple.com/documentation/storekit/testing-in-app-purchases-with-sandbox)をご覧ください。 --- # File: test-devices --- --- title: "テストデバイス" description: "Adaptyでテストデバイスを管理し、アプリのテストを効率化する方法を学びましょう。" --- テスト目的で、自分のデバイスをテストデバイスとして登録できます。これによりキャッシュが無効化され、変更がすぐに反映されるようになります。 :::note テストデバイスは以下の SDK バージョン以降でサポートされています。 - iOS: 2.11.1 - Android: 2.11.3 - React Native: 2.11.1 Flutter および Unity のサポートは後日追加される予定です。 ::: ## デバイスをテストデバイスとして登録する \{#mark-your-device-as-test\} 1. Adapty ダッシュボードで [**App settings**](https://app.adapty.io/settings/general) を開きます。 2. **General** タブの **Test devices** セクションまでスクロールします。 <img src="/assets/shared/img/14c581d-test_device_add.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. **Add test device** ボタンをクリックします。 <img src="/assets/shared/img/f86d5e2-test_users_add_device.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **Add test device** ウィンドウで以下を入力します。 | フィールド | 説明 | |:-----------------------------------------| :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Test device name** | 参照用のテストデバイス名。 | | **ID used to identify this test device** | テストデバイスの識別に使用する識別子の種類を選択します。最適な選択肢については、下記の [使用すべき識別子](test-devices#which-identifier-you-should-use) セクションの推奨事項を参照してください。 | | **ID value** | 識別子の値を入力します。 | 5. **Add test device** ボタンをクリックして変更を保存することを忘れないでください。 ## 使用すべき識別子 \{#which-identifier-you-should-use\} デバイスの識別には複数の識別子を使用できます。以下の方法を推奨します。 - <InlineTooltip tooltip="Adapty でユーザーを識別する">[iOS](identifying-users)、[Android](android-identifying-users)、[React Native](react-native-identifying-users)、[Flutter](flutter-identifying-users)、[Unity](unity-identifying-users)</InlineTooltip> の場合、iOS・Android どちらのデバイスでも **Customer User ID** が最適です。特に 1 つのアカウントに対して複数のテストデバイスを使用している場合に適しています。**ID used to identify this test device** として Customer User ID を使用すると、そのアカウントに紐づくすべてのデバイスがテストデバイスとしてマークされます。 - **IDFA(iOS)** および **Advertising ID(Android)**:これらの広告識別子は、ユーザーへの同意リクエストをすでに行っている場合に、それぞれ iOS・Android デバイスに最適な選択肢です。Customer User ID があっても、テスト中にアプリ内でアカウントを切り替える場合は広告識別子が便利です。また、同じアカウントにテスト用デバイスと個人用デバイスの両方があり、個人用デバイスをテストデバイスとしてマークしたくない場合にも有効です。 Adapty Profile ID、IDFV、Android ID などのオプションもあります。これらは利便性では劣りますが、Customer User ID・IDFA・Advertising ID が使えない場合に利用できます。 以下では、すべての選択肢を詳しく説明します。 ### すべてのプラットフォームで使用できる識別子 \{#identifiers-for-all-platforms\} | 識別子 | 使用方法 | |----------|-----| | Customer User ID | <p>ユーザーをシステム内で識別するために設定する一意の識別子。メールアドレス、内部 ID、その他の文字列などが使えます。このオプションを使用するには、<InlineTooltip tooltip="Adapty でユーザーを識別する">[iOS](identifying-users)、[Android](android-identifying-users)、[React Native](react-native-identifying-users)、[Flutter](flutter-identifying-users)、[Unity](unity-identifying-users)</InlineTooltip> でユーザーを識別している必要があります。</p><p></p><p>特に同じアカウントで複数のデバイスを使用している場合に、テストデバイスの識別として最適な選択肢です。このアカウントを持つすべてのデバイスがテスト用とみなされます。</p> | | Adapty profile ID | <p>Adapty における[ユーザープロファイル](profiles-crm)の一意の識別子。</p><p></p><p>Customer User ID・iOS の IDFA・Android の Advertising ID が使用できない場合にご利用ください。なお、アプリを再インストールしたり再ログインしたりすると Adapty Profile ID が変わる場合があります。</p> | #### Customer User ID と Adapty Profile ID の取得方法 \{#how-to-obtain-customer-user-id-and-adapty-profile-id\} どちらの識別子も Adapty ダッシュボードの **Profile** 詳細から取得できます。 1. [**Adapty Profiles** -> **Event feed** タブ](https://app.adapty.io/event-feed)でユーザーのプロファイルを見つけます。 :::note 正確なプロファイルを見つけるには、珍しい種類のトランザクションを実行してください。そうすることで、[**Event Feed**](https://app.adapty.io/event-feed) にトランザクションが表示されたときにすぐに特定できます。 ::: 2. プロファイル詳細の **Customer user ID** と **Adapty ID** フィールドの値をコピーします。 <img src="/assets/shared/img/345d308-test_users_CUID_adapty_ID.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### Apple の識別子 \{#apple-identifiers\} | 識別子 | 使用方法 | |----------|-----| | IDFA | <p>IDFA(Identifier for Advertisers)は、Apple がユーザーのデバイスに割り当てる一意のデバイス識別子です。</p><p></p><p>自動的に変わることがないため(手動でリセットは可能)、iOS デバイスに最適です。</p><p>**注意**:iOS 14.5 以降、広告主は IDFA にアクセスするためにユーザーの同意を求める必要があります。アプリ内で同意を求めていること、テストデバイスで同意を付与済みであることを確認してください。</p> | | IDFV | IDFV(Identifier for Vendors)は、同一パブリッシャー/ベンダーの全アプリに対して Apple が 1 つのデバイスに割り当てる一意の英数字識別子です。アプリを再インストールまたはアップデートすると変わる場合があります。 | #### IDFA の取得方法 \{#how-to-obtain-the-idfa\} Apple はデフォルトで IDFA を提供していません。Adapty ダッシュボードのプロファイルのアトリビューションから取得してください。 1. [**Adapty Profiles** -> **Event feed** タブ](https://app.adapty.io/event-feed)でユーザーのプロファイルを見つけます。 :::note 正確なプロファイルを見つけるには、珍しい種類のトランザクションを実行してください。そうすることで、[**Event Feed**](https://app.adapty.io/event-feed) にトランザクションが表示されたときにすぐに特定できます。 ::: 2. プロファイル詳細を開き、**Attributes** セクションの **IDFA** フィールドの値をコピーします。 <img src="/assets/shared/img/ce4a63f-test_users_idfa.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> または、[App Store で IDFA を表示してくれるアプリを探す](https://www.apple.com/us/search/idfa?src=globalnav)こともできます。 #### Identifier for Vendors(IDFV)の取得方法 \{#how-to-obtain-the-identifier-for-vendors-idfv\} IDFV を取得するには、開発者に以下のメソッドを使ってアプリ内でリクエストし、取得した識別子をログまたはデバッグパネルに表示するよう依頼してください。 ```swift showLineNumbers title="Swift" UIDevice.current.identifierForVendor ``` ### Google の識別子 \{#google-identifiers\} | 識別子 | 使用方法 | |----------|-----| | Advertising ID | <p>Advertising ID は、Google がユーザーのデバイスに割り当てる一意のデバイス識別子です。</p><p>自動的に変わることがないため(手動でリセットは可能)、Android デバイスに最適です。</p><p>**注意**:使用するには、Android 12 以上の場合、**Ads** 設定の **Opt out of Ads Personalization** をオフにしてください。</p>| | Android ID | Android ID は、アプリの署名キー・ユーザー・デバイスの組み合わせごとに固有の識別子です。Android 8.0 以上で利用できます。 | #### Advertising ID の取得方法 \{#how-to-obtain-advertising-id\} デバイスの Advertising ID を確認するには: 1. Android デバイスで **Settings** アプリを開きます。 2. **Google** をタップします。 3. **Services** の下にある **Ads** を選択します。画面下部に Advertising ID が表示されます。 #### Android ID の取得方法 \{#how-to-obtain-android-id\} Android ID を取得するには、開発者に以下のメソッドを使って [ANDROID_ID](https://developer.android.com/reference/android/provider/Settings.Secure#ANDROID_ID) をアプリ内でリクエストし、取得した識別子をログまたはデバッグパネルに表示するよう依頼してください。 ```kotlin showLineNumbers title="Kotlin/Java" android.provider.Settings.Secure.getString(contentResolver, android.provider.Settings.Secure.ANDROID_ID); ``` --- # File: release-checklist --- --- title: "リリースチェックリスト" description: "Adaptyのリリースチェックリストに従って、スムーズなアプリのアップデートプロセスを確保しましょう。" --- Adaptyをご利用いただきありがとうございます!実装がうまくいったことを願っています。このガイドでは、アプリをストアに公開する準備が整っているか確認するための手順を説明します。これにより、マネタイゼーションフローが正しく機能していることを安心して確認できます。 ## 事前確認事項 \{#pre-flight-essentials\} バリデーションを始める前に必要なもの: - サンドボックスアカウントを持つ実機デバイス - Adapty ダッシュボードへのアクセス - App Store Connect / Google Play Console へのアクセス :::note サンドボックス購入はシミュレーターでも実行できますが、支払いダイアログや生体認証プロンプトを含むすべてのフローを完全にテストするには実機デバイスが必要です。 ::: <Button id="test-purchases-in-sandbox"> App Store向けテストガイド </Button> <Button id="testing-on-android"> Google Play向けテストガイド </Button> ## 共通バリデーション \{#universal-validations\} - [ ] **ストア接続**: AdaptyをApp StoreおよびGoogle Playに接続していることを確認してください: - [ ] [App Store](initial_ios) - [ ] [Google Play](initial-android) - [ ] **サブスクリプションイベントの配信**: サーバー通知が設定されていることを確認してください: - [ ] [App Serverサーバー通知](enable-app-store-server-notifications) - [ ] [リアルタイム開発者通知(RTDN)](enable-real-time-developer-notifications-rtdn) - [ ] **プロファイルの識別**: ユーザー識別ロジックを検証し、購入が正しいプロファイルに紐付けられていることを確認してください: - [ ] [アプリコードの識別ロジックがユースケースに合っているか確認する](ios-quickstart-identify) - [ ] [ユーザープロファイル間で有料アクセスを共有するための親/継承ロジックを理解しているか確認する](sharing-paid-access-between-user-accounts) - [ ] **オファー**: アプリにApp Storeのプロモーションオファーがある場合、[アプリ内購入キー](app-store-connection-configuration#step-4-for-trials-and-special-offers--set-up-promotional-offers)をメインフィールドと **App Store promotional offers** セクションの両方に追加していることを確認してください。 - [ ] **データ収集**: プライバシーへの準拠を確保してください: - [ ] GDPRやCCPAなどのプライバシー規制に準拠する必要がある場合、またはアプリが子供向けの場合は、[IDFAおよびIPの収集と共有を有効にするかどうか](sdk-installation-ios#data-policies)を制御してください。 - [ ] アプリがAppTrackingTransparencyを使用している場合は、[認証ステータスをAdaptyに送信](ios-deal-with-att)していることを確認してください。 - [ ] **プライバシーラベル**: Adaptyが収集するデータとレビューに必要なフラグについては、[詳細はこちら](apple-app-privacy)をご覧ください。 ## 購入バリデーション \{#purchase-validations\} --- no_index: true --- import Callout from '../../../components/Callout.astro'; <Callout type="tip"> ご質問やお困りのことがあれば、[サポートフォーラム](https://adapty.featurebase.app/)をご覧ください。よくある質問への回答を見つけたり、ご自身の質問を投稿することができます。チームとコミュニティがサポートいたします! </Callout> 公開前に、アプリ内購入が正しく機能し、ペイウォールがストアレビューの準備ができていることを確認してください。 アプリ内購入のバリデーション方法は、実装方法によって異なります: - Adapty ペイウォールビルダーで作成したペイウォールを表示する - 独自のペイウォールを実装し、その中で `makePurchase` メソッドを使用して購入を処理する - オブザーバーモードでAdaptyを使用する(Adapty ペイウォールビルダーまたはカスタムペイウォールのどちらでも) <Tabs groupId="paywall" queryString> <TabItem value="builder" label="Adapty Paywall Builder" default> **目標**: Adaptyがペイウォールをレンダリングし、ユーザーがプロダクトを購入でき、アクセスがアンロックされ、購入復元フローが機能すること。 - [ ] アプリが[ペイウォールを表示する](ios-present-paywalls)際、実際にリリースするのと同じプレースメントを使用している。 - [ ] ペイウォールが画面に表示される。読み込みに時間がかかりすぎる場合(不安定なインターネット環境など)は、[フェッチポリシーの調整](get-pb-paywalls#fetch-paywall-designed-with-paywall-builder)を検討してください。 - [ ] ペイウォールが期待するバリアント(該当する場合はオーディエンス/ロケール)と一致している。必要に応じて[オーディエンスの優先順位を変更](change-audience-priority)できます。 - [ ] プロダクトと価格がペイウォールに表示される。テスト中(特に異なるリージョン設定の場合)にAppleのAPIが不正確な価格を提供することがあります。AdaptyはStoreの価格に影響を与えないため、価格の正確さよりも購入フローの機能テストを優先してください。 - [ ] サンドボックス購入が正常に完了する。購入成功のコールバックが受信される。 - [ ] アクセスがアンロックされ、維持される。[現在のAdaptyプロファイルに基づいて有料アクセスが付与されていること](ios-check-subscription-status#connect-profile-with-paywall-logic)を確認する。 - [ ] 購入後、Adaptyプロファイルにアクティブなアクセスレベルがある。 - [ ] プロファイルにそのアクセスレベルが含まれている場合に有料機能がアンロックされる(購入コールバックだけでなく)。 - [ ] 購入の復元が機能する。アプリを再インストールするか新しいデバイスにインストールした場合、[有料アクセスの共有](sharing-paid-access-between-user-accounts)設定に従って購入の自動復元が機能する。バックエンド認証がない場合は、設定に関係なく購入が自動的に復元される。それ以外の場合は、アプリの再インストール後にユーザーが購入を復元できることを確認する。 - [ ] ストアレビュー要件: - [ ] **Restore purchases** ボタンがペイウォールに表示されている。ペイウォールビルダーで追加でき、タップ時に購入復元を自動的に処理します。 - [ ] 利用規約とプライバシーポリシーがペイウォール画面からアクセスでき、これらのリンクをクリックするとブラウザで開く。 </TabItem> <TabItem value="makepurchase" label="カスタムペイウォール(makePurchase)" default> **目標**: UIをレンダリングし、AdaptyがPurchase処理、プロファイル更新、および復元を担当する。 - [ ] プロダクトIDがアプリコードにハードコードされていない。ハードコードするのは[プレースメント](placements)IDのみ。 - [ ] アプリが[プロダクトを取得する](fetch-paywalls-and-products)際、実際にリリースするのと同じプレースメントを使用している。 - [ ] プロダクトリストが正常に読み込まれる。読み込みに時間がかかりすぎる場合(不安定なインターネット環境など)は、[フェッチポリシーの調整](fetch-paywalls-and-products#fetch-paywall-information)を検討してください。 - [ ] 取得したプロダクトが期待するバリアント(該当する場合はオーディエンス/ロケール)と一致している。必要に応じて[オーディエンスの優先順位を変更](change-audience-priority)できます。 - [ ] プロダクトと価格がペイウォールに表示される。テスト中(特に異なるリージョン設定の場合)にAppleのAPIが不正確な価格を提供することがあります。AdaptyはStoreの価格に影響を与えないため、価格の正確さよりも購入フローの機能テストを優先してください。 - [ ] [makePurchase](making-purchases)を使用したサンドボックス購入が正常に完了する: - [ ] 購入成功の結果が処理される。 - [ ] 保留中/失敗/キャンセルの結果が適切に処理される。 - [ ] [リモートコンフィグを使用する](present-remote-config-paywalls)場合、その値がペイウォールに正しく反映されている。 - [ ] ペイウォールが表示されたとき、[`logShowFlow`(iOS SDK v4+)/ `logShowPaywall` メソッド](present-remote-config-paywalls#track-paywall-view-events)が呼び出される。 - [ ] サンドボックス購入が正常に完了する。購入成功のコールバックが受信される。 - [ ] アクセスがアンロックされ、維持される。[現在のAdaptyプロファイルに基づいて有料アクセスが付与されていること](ios-check-subscription-status#connect-profile-with-paywall-logic)を確認する。 - [ ] 購入後、Adaptyプロファイルにアクティブなアクセスレベルがある。 - [ ] プロファイルにそのアクセスレベルが含まれている場合に有料機能がアンロックされる(購入コールバックだけでなく)。 - [ ] 購入の復元が機能する。アプリを再インストールするか新しいデバイスにインストールした場合、[有料アクセスの共有](sharing-paid-access-between-user-accounts)設定に従って購入の自動復元が機能する。バックエンド認証がない場合は、設定に関係なく購入が自動的に復元される。それ以外の場合は、アプリの再インストール後にユーザーが購入を復元できることを確認する。 - [ ] ストアレビュー要件: - [ ] **Restore purchases** ボタンがアクセス可能で、[購入復元を処理](restore-purchase)している。 - [ ] 利用規約とプライバシーポリシーがペイウォール画面からアクセスでき、これらのリンクをクリックするとブラウザで開く。 </TabItem> <TabItem value="observer" label="オブザーバーモード"> **目標**: 購入処理、プロファイル更新、復元を自身で行い、Adaptyがトランザクションレポートを受け取る。 - [ ] **アプリが独自の購入フロー(StoreKit / BillingClient / バックエンド)を使用して購入を完了する**: - [ ] サンドボックス購入がストアUIで成功する。 - [ ] 保留中/失敗/キャンセルの結果がアプリ内で適切に処理される。 - [ ] **トランザクションがAdaptyに報告される**。 - [ ] オブザーバーモードが[アプリコードで有効になっている](implement-observer-mode)。 - [ ] 購入がAdaptyのイベントフィードに表示される。 - [ ] 更新、キャンセル、返金が時間の経過とともに反映される(該当する場合)。 - [ ] **ペイウォールビューが追跡される**。ペイウォールが表示されたとき、[`logShowFlow`(iOS SDK v4+)/ `logShowPaywall` メソッド](present-remote-config-paywalls#track-paywall-view-events)が呼び出される。 - [ ] **実装に合わせた購入復元が機能する**。アプリの再インストールやデバイスの切り替えで、アクセスが正しく復元される。 - [ ] **ストアレビュー要件**: - [ ] **Restore purchases** アクションがアクセス可能で、独自の復元フローがトリガーされる。 - [ ] 利用規約とプライバシーポリシーがペイウォールまたは購入画面からアクセスでき、ブラウザで開く。 </TabItem> </Tabs> Adapty SDKの統合についてご不明な点がある場合は、右下のAIチャットボットをご利用いただくか、[support@adapty.io](mailto:support@adapty.io)までお問い合わせください。 --- # File: submit-app-to-app-store --- --- title: "iOSアプリをApp Storeに申請する" description: "ビルドをApp Store Connectにアップロードし、iOSサブスクリプションアプリをAppleのレビューに申請します。" --- Adaptyのインテグレーションのテストができたら、ビルドをApp Store Connectにアップロードして、アプリをAppleのレビューに申請しましょう。 :::tip 申請前に、[リリースチェックリスト](release-checklist)を確認して、Adaptyインテグレーション、購入フロー、ストアのレビュー要件を検証してください。 ::: ## ビルドをApp Store Connectにアップロードする \{#upload-your-build-to-app-store-connect\} ### ステップ1. XcodeでアプリをアーカイブしてApp Store Connectにアップロードする \{#step-1-archive-your-app-in-xcode-and-upload-it-to-app-store-connect\} 1. Xcodeで、ビルド先を **Any iOS Device (arm64)** に設定します。 <img src="/assets/shared/img/build-target.webp" style={{ border: '1px solid #727272', width: '700px', display: 'block', margin: '0 auto' }} /> 2. メニューバーから **Product** > **Archive** を選択します。 <img src="/assets/shared/img/xcode-archive.webp" style={{ border: '1px solid #727272', width: '500px', display: 'block', margin: '0 auto' }} /> 3. アーカイブ処理が完了するまで待ちます。**Organizer** ウィンドウが自動的に開きます。アーカイブを選択して **Distribute App** をクリックします。 <img src="/assets/shared/img/distribute-app.webp" style={{ border: '1px solid #727272', width: '700px', display: 'block', margin: '0 auto' }} /> 4. 配布方法として **App Store Connect** を選択します。画面の指示に従ってアップロードを完了させます。 :::note アプリアイコンや起動画面など、必要なアセットが不足している場合はアップロードが失敗することがあります。Xcodeのエラーログで詳細を確認してください。 ::: <img src="/assets/shared/img/distribution-method.webp" style={{ border: '1px solid #727272', width: '700px', display: 'block', margin: '0 auto' }} /> ### ステップ2. App Store Connectでビルドを確認する \{#step-2-check-the-build-in-app-store-connect\} 1. [App Store Connect](https://appstoreconnect.apple.com) にアクセスしてアプリを開きます。 2. **Build** セクションまでスクロールし、アップロードしたビルドが表示されていることを確認します。 :::note アップロード後、ビルドがApp Store Connectに表示されるまで数分かかる場合があります。 ::: <img src="/assets/shared/img/app-store-build.webp" style={{ border: '1px solid #727272', width: '700px', display: 'block', margin: '0 auto' }} /> ## アプリとプロダクトをレビューに申請する \{#submit-your-app-and-products-for-review\} **Build** セクションにビルドが表示されたら、アプリ内サブスクリプションを添付してAppleのレビューに申請します。 ### ステップ1. 申請にプロダクトを添付する \{#step-1-attach-products-to-the-submission\} 各サブスクリプションは、添付できるようになる前にApp Store Connectで **Ready to Submit** ステータスになっている必要があります。サブスクリプションがドラフト状態だったりメタデータが不足していたりすると、リストに表示されません。 1. 同じページで、**In-App Purchases and Subscriptions** セクションまでスクロールします。 2. **Select in-app purchases or subscriptions** をクリックします。 <img src="/assets/shared/img/app-store-select-products.webp" style={{ border: '1px solid #727272', width: '700px', display: 'block', margin: '0 auto' }} /> 3. この申請に含めたいプロダクトをすべて選択して **Done** をクリックします。 ### ステップ2. レビューに申請する \{#step-2-submit-for-review\} 1. ページ上の必須項目(説明文、スクリーンショット、キーワードなど)をすべて入力します。 2. **App Store Version Release** セクションで、承認後にアプリを自動リリースするか、手動でリリースするか、スケジュール設定でリリースするかを選択します。 3. **Add for Review** をクリックし、次に **Submit to App Review** をクリックします。 Appleのレビューは通常1〜2日以内に完了しますが、レビュー期間は変動することがあります。 ## 本番環境でアプリを確認する \{#verify-your-app-in-production\} Appleがアプリを承認したら: 1. 実際に購入を行います(または最初のユーザーが購入するのを待ちます)。 2. Adapty ダッシュボードの [**Event Feed**](https://app.adapty.io/event-feed) を開き、本番トランザクションイベントが表示されていることを確認します。 3. サブスクリプションイベント(更新、キャンセル)が正しく流れているか確認します。これには[App Storeサーバー通知](enable-app-store-server-notifications)の設定が必要です。 本番イベントが表示されない場合は、[App Store接続設定](app-store-connection-configuration)を確認してください。 ## 次のステップ \{#next-steps\} アプリが公開されました。サブスクリプション収益を伸ばしていきましょう: - **[A/B テスト](ab-tests)**:異なるペイウォールを試して、最もコンバージョンが高いものを見つけましょう。 - **[アナリティクス](charts)**:MRR、チャーン、コンバージョンなどのサブスクリプション指標を追跡しましょう。 - **インテグレーション**:サブスクリプションイベントを[アナリティクス](analytics-integration)や[アトリビューション](attribution-integration)プラットフォームに送信しましょう。 --- # File: general --- --- title: "App settings" description: "Adaptyのシームレスな利用に向けた一般設定と構成についてご説明します。" --- **App Settings** ページの **General** タブから、アプリの動作・外観・収益共有の設定を管理できます。ここでは、アプリ名やアイコンのカスタマイズ、Adapty SDK および API キーの管理、スモールビジネスプログラムのステータス設定、アナリティクスやチャートのタイムゾーン選択などが行えます。 ## 1. アプリの詳細 \{#1-app-details\} <img src="/assets/shared/img/8fa2929-CleanShot_2023-04-21_at_15.16.222x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Adapty インターフェース上でアプリを識別するための一意の名前とアイコンを設定してください。なお、ここで設定するアプリ名とアイコンは、App Store や Google Play 上のアプリ名・アイコンには影響しません。また、アプリの目的やコンテンツを正確に反映した適切なアプリカテゴリを選択してください。これにより、ユーザーがアプリを見つけやすくなり、適切なストアカテゴリに表示されるようになります。 ## 2. スモールビジネスプログラムへの参加と手数料優遇 \{#2-member-of-small-business-program-and-reduced-service-fee\} <img src="/assets/shared/img/825e2be-CleanShot_2023-04-19_at_13.43.292x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Apple の [Small Business Program](app-store-small-business-program) または Google の [Reduced Service Fee プログラム](google-reduced-service-fee) に登録している場合、ストアの手数料が優遇されます。 アプリが手数料優遇プログラムに登録されている場合は、Adapty に通知してください。正確な計算のために、「Reduced Store Fee」セクションでプログラムのステータスを指定してください。 手数料優遇の設定は、今後の取引にのみ適用されます。ステータスが変更される**前に**設定を更新しておくと、Adapty が手数料率を自動的に調整します。 :::warning * 手数料優遇プログラムの参加期間を延長した場合は、**適用期間を追加してください**。 * プログラムの資格を失った場合は、現在の適用期間の**終了日を変更してください**。 ::: 詳細については以下の記事をご覧ください: * [App Store Small Business Program](app-store-small-business-program) * [Google Reduced Service Fee](google-reduced-service-fee) ## 3. レポートのタイムゾーン \{#3-reporting-timezone\} <img src="/assets/shared/img/47227f9-CleanShot_2023-04-19_at_13.45.302x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 拠点となる場所、またはアプリのアナリティクスやチャートに最も適したタイムゾーンを選択してください。一貫性を保つために、App Store Connect または Google Play Console のアカウントと同じタイムゾーンを使用することをおすすめします。なお、このタイムゾーン設定は、UTC タイムゾーンを使用する Adapty のサードパーティ連携には影響しません。 タイムゾーン設定は、**App Settings** ページの **General** タブにある **Reported timezone** セクションから行えます。また、Adapty アカウント内のすべてのアプリに同じタイムゾーンを設定するチェックボックスもあります。 ## 4. アナリティクスにおけるインストールの定義 \{#4-installs-definition-for-analytics\} アナリティクスにおける新規インストールイベントの定義を選択してください: | 基準 | 説明 | |------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | New device_ids | <p>(推奨)ストアからデバイスにアプリをインストールするたびに、新規インストールとしてカウントされます。初回インストールと再インストールの両方が含まれます。</p><p>インストールはデバイス ID 単位でカウントされ、ユーザー認証の影響を受けません。プロファイルの作成(SDK 起動時またはログアウト時)、ログイン、アプリのアップグレードでは追加のインストールイベントは発生しません。</p><p>例えば、同じアプリが 5 台の異なるデバイスにインストールされた場合、アナリティクスには 5 インストールと表示されます。</p> | | New customer_user_ids | <p>このオプションは、Adapty で <InlineTooltip tooltip="Adapty でユーザーを識別する">[iOS](identifying-users)、[Android](android-identifying-users)、[React Native](react-native-identifying-users)、[Flutter](flutter-identifying-users)、[Unity](unity-identifying-users)、[Kotlin Multiplatform](kmp-quickstart-identify)、[Capacitor](capacitor-quickstart-identify)</InlineTooltip> ユーザーを識別するアプリ向けです。</p><p>ログイン済みユーザーの場合、顧客ユーザー ID に関連付けられた最初のインストールのみが新規インストールとしてカウントされます。追加デバイスへのインストールは新規インストールとしてカウントされません。</p><p>匿名ユーザー(ログインしていないユーザー)はアナリティクスでカウントされません。</p><p>アプリの再インストールや再ログインでは追加のインストールは発生しません。</p><p>App Store Connect、Google Play Console、AppsFlyer などのアプリストアやアトリビューションプラットフォームは、デバイスベースでインストールをカウントします。Adapty で顧客ユーザー ID によるインストールカウントを使用した場合、これらの外部サービスの数値と異なる場合があります。</p><p>⚠️ Adapty でユーザーを識別していない場合、このオプションを有効にするとインストールはカウントされません。</p> | | New profiles in Adapty | (レガシー)すべてのアプリインストール、再インストール、およびログアウト時に作成された匿名プロファイルが新規インストールとしてカウントされます。 | このオプションは [**Analytics**](https://app.adapty.io/analytics) ページにのみ影響し、別途ビューを設定できる [**Overview**](https://app.adapty.io/overview) ページには影響しない点に注意してください。 ## 5. App Store の価格値上げロジック \{#5-app-store-price-increase-logic\} Adapty アナリティクスと App Store Connect の結果の間に不整合が生じないよう、App Store Connect で価格値上げに関する設定を変更する際は、適切なオプションを選択することが重要です。 Adapty でサブスクリプションの価格値上げに適用するロジックを選択できます: <img src="/assets/shared/img/b766c8b-CleanShot_2023-07-18_at_19.28.18_22x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> - **既存ユーザーのサブスクリプション価格を維持する:** このオプションを選択すると、App Store Connect で価格を変更しても、既存のサブスクライバーには元の価格が適用され続けます。つまり、既存のサブスクライバーは引き続き元のサブスクリプション価格で請求されます。 - **App Store Connect でサブスクリプション価格が変更された場合、既存のサブスクライバーにも適用される:** このオプションを選択すると、App Store Connect で行った価格変更が既存のサブスクライバーにも適用されます。つまり、既存のサブスクライバーは App Store Connect に設定された新しい価格で請求されます。 :::warning 選択したオプションは、Adapty のアナリティクスだけでなく、連携機能やトランザクション処理全体にも影響することをご注意ください。 ::: 既存のサブスクライバーに対するサブスクリプション価格の取り扱い方針に合ったオプションを選択してください。これにより、Adapty アナリティクスと App Store Connect の結果の正確なデータと同期を維持できます。 ## 6. ユーザーアカウント間でのアクセスレベルの共有 \{#6-sharing-paid-access-between-user-accounts\} :::link メイン記事:[ユーザーアカウント間でのアクセスレベルの共有](sharing-paid-access-between-user-accounts) ::: **Sharing paid access between user accounts** 設定は、複数の[ユーザープロファイル](identifying-users)が同じ購入にアクセスしようとした場合に Adapty がどう処理するかを決定します。[サンドボックス環境](test-purchases-in-sandbox)に対して個別のアクセス共有設定を指定することもできます。 --- no_index: true --- **有効(デフォルト)** 識別済みユーザー([Customer User ID](identifying-users#set-customer-user-id-on-configuration)が設定されているユーザー)は、同じApple/Google IDでサインインしているデバイスであれば、Adaptyが提供する同じ[アクセスレベル](access-level)を共有できます。これは、ユーザーがアプリを再インストールして別のメールアドレスでログインした場合でも、以前の購入へのアクセスを維持できるため便利です。このオプションでは、複数の識別済みユーザーが同じアクセスレベルを共有できます。 アクセスレベルは共有されますが、過去および将来のすべてのトランザクションは、一貫したアナリティクスを維持し完全なトランザクション履歴(トライアル期間、サブスクリプション購入、更新など)を同じプロファイルに紐付けるため、元のCustomer User IDのイベントとして記録されます。 **新しいユーザーへアクセスを移譲** 識別済みユーザーは、デバイスが同じApple/Google IDでサインインしている限り、別の[Customer User ID](identifying-users#set-customer-user-id-on-configuration)でログインしたりアプリを再インストールしたりしても、Adaptyが提供する[アクセスレベル](access-level)を引き続き利用できます。 前のオプションとは異なり、Adaptyは識別済みユーザー間で購入を移譲します。これにより購入済みコンテンツへのアクセスが保証されますが、一度にアクセスできるのは1人のユーザーのみです。たとえば、UserAがサブスクリプションを購入し、同じデバイスでUserBがログインしてトランザクションをリストアした場合、UserBがサブスクリプションへのアクセスを取得し、UserAからはアクセスが取り消されます。 いずれかのユーザー(新しいユーザーまたは古いユーザー)が識別されていない場合でも、Adapty内でそれらのプロファイル間でアクセスレベルは共有されます。 アクセスレベルは移譲されますが、過去および将来のすべてのトランザクションは、一貫したアナリティクスを維持し完全なトランザクション履歴(トライアル期間、サブスクリプション購入、更新など)を同じプロファイルに紐付けるため、元のCustomer User IDのイベントとして記録されます。 **新しいユーザーへアクセスを移譲**に切り替えた後、アクセスレベルはすぐにはプロファイル間で移譲されません。特定のアクセスレベルの移譲プロセスは、サブスクリプションの更新、リストア、またはトランザクションの検証など、ストアからのイベントをAdaptyが受信したときにのみトリガーされます。 **無効** 最初にアクセスレベルを取得した識別済みユーザープロファイルが、それを永続的に保持します。これは、ビジネスロジック上、購入を単一のCustomer User IDに紐付ける必要がある場合に最適なオプションです。 なお、匿名ユーザー間ではアクセスレベルは引き続き共有されます。 [オーナーのユーザープロファイルを削除する](https://adapty.io/docs/ja/api-adapty/operations/deleteProfile)ことで、購入の紐付けを解除できます。削除後、アクセスレベルは最初にそれを要求したユーザープロファイル(匿名または識別済みを問わず)に付与されます。 共有の無効化は新しいユーザーにのみ影響します。すでにユーザー間で共有されているサブスクリプションは、このオプションを無効にした後も共有され続けます。 :::warning AppleとGoogleは、購入をApple/Google IDに紐付けているため、ユーザー間でアプリ内課金を共有または移譲することを求めています。共有がなければ、その後の再インストール時に購入のリストアが機能しない可能性があります。 共有を無効にすると、ログイン後にユーザーがアクセスを取り戻せなくなる場合があります。 共有の無効化は、ユーザーが購入前に**ログインを必須とする**場合にのみ推奨します。そうでない場合、識別済みユーザーがサブスクリプションを購入した後に別のアカウントにログインすると、アクセスを永続的に失う可能性があります。 ::: ### どの設定を選べばよいですか? \{#which-setting-should-i-choose\} | アプリの条件 | 選択するオプション | | ------------------------------------------------------------ | ------------------------------------------------------------ | | ログインシステムがなく、AdaptyのみMatch anonymous profile IDを使用している。 | デフォルトオプションを使用してください。3つのオプションすべてで、匿名プロファイルID間ではアクセスレベルが常に共有されます。 | | オプションのログインシステムがあり、アカウント作成前に購入できる。 | **新しいユーザーへアクセスを移譲**を選択してください。アカウントなしで購入したユーザーが後でトランザクションをリストアできるようになります。 | | 購入前にアカウント作成を必須とするが、購入を複数のCustomer User IDに紐付けることを許可している。 | **新しいユーザーへアクセスを移譲**を選択してください。一度にアクセスできるCustomer User IDは1つに限られますが、別のCustomer User IDでログインしても有料アクセスを失わずに済みます。 | | 購入前にアカウント作成を必須とし、購入を単一のCustomer User IDに厳密に紐付けるルールがある。 | **無効**を選択してください。アカウント間でトランザクションが移譲されないことが保証されます。 | ## 7. SDK および API キー \{#7-sdk-and-api-keys\} アプリに Adapty SDK を組み込むには Public SDK キーを使用し、Adapty の Server API にアクセスするには Secret キーを使用します。必要に応じて新しいキーを生成したり、既存のキーを無効化することができます。Developer CLI 用のトークンを作成するには、**Settings → Developer API** に移動してください。詳細は [Authentication](developer-cli-authentication) をご覧ください。 ## 8. テストデバイス \{#8-test-devices\} テストに使用するデバイスを指定することで、キャッシュによる遅延をバイパスし、ペイウォールやプレースメントの変更が即座に反映されるようにします。詳細は [Testing devices](test-devices) をご覧ください。 ## 9. クロスプレースメントバリエーションのスティッキネス \{#9-cross-placement-variation-stickiness\} テスト終了後、どのくらいの期間ユーザーがテスト内のバリアントを引き続き表示されるかを定義します。これはアナリティクスの精度とユーザー体験に影響します。ユーザーが以前に見たものとは異なるオファーを表示すると、購入の意思決定に影響を与える可能性があります。 スティッキネス期間の最大値かつデフォルト値は 90 日間です。 :::warning 以下の点を考慮してください: - この設定を変更すると、以前にバリアントを受け取ったすべてのユーザーに影響します。対象ユーザーはプレースメントを表示した際に即座に新しいペイウォールの対象となるため、実行中の A/B テストの結果に影響する可能性があります。 - スティッキネス期間が終了したユーザーには、新しいペイウォールや A/B テストが表示される場合があります。ただし、その場合でも、他のクロスプレースメントテストに参加することは永久にできなくなります。 ::: ## 10. アプリの削除 \{#10-delete-the-app\} アプリが不要になった場合、Adapty から削除することができます。 :::warning この操作は元に戻せません。アプリやそのデータを復元することはできません。 ::: --- # File: ios-settings --- --- title: "Apple App Store の認証情報" description: "AdaptyでiOSの設定を構成し、サブスクリプション管理をシームレスに実現します。" --- App Storeの認証情報を設定し、Adapty iOS SDKの最適な動作を確保するには、Adapty ダッシュボードの App Settings ページ内の [iOS SDK](https://app.adapty.io/settings/ios-sdk) タブに移動します。次に、以下のパラメーターを設定してください: <img src="/assets/shared/img/3d4087e-CleanShot_2023-06-26_at_13.27.042x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> | フィールド | 説明 | |----------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Bundle ID** | アプリの [Bundle ID](app-store-connection-configuration#step-1-provide-bundle-id-and-apple-app-id)。 | | **In-app purchase API (StoreKit 2)** | アプリ内課金のトランザクション履歴リクエストの安全な認証と検証を有効にするための [キー](app-store-connection-configuration#step-2-provide-issuer-id-and-key-id)。 | | **App Store Server Notifications** | App Store からの [サーバー間通知](enable-app-store-server-notifications) を有効にし、ユーザーのサブスクリプション状態の変化を監視・対応するために使用するURL。 | | **App Store Promotional Offers** | 特定のプロダクトに対してAdaptyで [プロモーションオファー](generate-in-app-purchase-key) を作成するためのサブスクリプションキー。 | | **Apple app ID** | App StoreにおけるアプリのID。確認するには、App Store Connectでアプリのページを開き、左メニューから **App Information** ページを開いて **Apple ID** をコピーしてください。 | | **App Store Connect shared secret (LEGACY)** | <p>**Adapty SDK v2.9.0 以前向けのレガシーキー**</p><p></p><p>アプリのレシート検証と不正防止のための [キー](app-store-connection-configuration#step-5-enter-app-store-shared-secret)。</p> | --- # File: google-play-store-connection-configuration --- --- title: "Google Play Storeとの連携を設定する" description: "AdaptyでGoogle Play Storeの接続を設定し、アプリ内課金をスムーズに処理しましょう。" --- このセクションでは、Google Play経由で販売されているモバイルアプリをAdaptyと連携する手順を説明します。Play StoreのアプリケーションデータをAdapty ダッシュボードに入力する必要があります。この作業は、AdaptyがPlay Storeから購入を検証し、サブスクリプションの更新情報を受け取るために欠かせないステップです。 この設定は初回オンボーディング時に行うか、後からAdapty ダッシュボードの **App Settings** で変更できます。 :::danger 設定の変更は、Adaptyのペイウォールをアプリにリリースするまでのみ許容されます。リリース後に変更すると連携が壊れ、モバイルアプリでペイウォールが表示されなくなります。 ::: ## ステップ1. パッケージ名を入力する \{#step-1-provide-package-name\} パッケージ名は、Google Play StoreにおけるアプリのユニークなIDです。サブスクリプション処理などAdaptyの基本機能に必要です。 1. [Google Play Developer Console](https://play.google.com/console/u/0/developers)を開きます。 2. IDを確認したいアプリを選択します。**Dashboard** 画面が開きます。 <img src="/assets/shared/img/7889edb-package_name.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. アプリケーション名の下にあるプロダクトIDを確認し、コピーします。 4. AdaptyトップメニューからA[**App settings**](https://app.adapty.io/settings/android-sdk)を開きます。 <img src="/assets/shared/img/b00066c-package_name.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. **App settings** 画面の **Android SDK** タブで、コピーした **Package name** を貼り付けます。 ## ステップ2. アカウントキーファイルをアップロードする \{#step-2-upload-the-account-key-file\} 1. [サービスアカウントキーファイルの作成](create-service-account)ステップで作成したサービスアカウントの秘密鍵ファイル(JSON形式)を、**Service account key file** エリアにアップロードします。 <img src="/assets/shared/img/20fdba1-service_key_file.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 変更を確定するために、**Save** ボタンをクリックするのを忘れずに。 **次のステップ** - [Google Play ConsoleでRTDN(リアルタイム デベロッパー通知)を有効にする](enable-real-time-developer-notifications-rtdn) --- # File: enable-real-time-developer-notifications-rtdn --- --- title: "Google Play ConsoleでリアルタイムデベロッパーNotification(RTDN)を有効にする" description: "Google Play ConsoleでリアルタイムデベロッパーNotification(RTDN)を有効にしてAdaptyのデータ精度を維持しましょう。払い戻しやその他の重要なイベントに関する即時更新を受け取るためのRTDNセットアップ方法を学びます" --- リアルタイムデベロッパーNotification(RTDN)を設定することは、データ精度を確保するうえで非常に重要です。これにより、払い戻しやその他のイベントに関する情報を含む、Play Storeからの更新をリアルタイムで受け取れるようになります。 ## 通知を有効にする \{#enable-notifications\} 1. **Google Cloud Pub/Sub** が有効になっていることを確認してください。[こちらのリンク](https://console.cloud.google.com/flows/enableapi?apiid=pubsub)を開き、アプリのプロジェクトを選択します。**Google Cloud Pub/Sub** をまだ有効にしていない場合は、ここで有効にする必要があります。 <img src="/assets/shared/img/pubsub.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Adaptyのトップメニューから [**App settings > Android SDK**](https://app.adapty.io/settings/android-sdk) に移動し、**Google Play RTDN topic name** タイトルの横にある **Enable Pub/Sub API** フィールドの内容をコピーします。 <img src="/assets/shared/img/a72ff2d-copy_topic.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> <p> </p> :::note **Enable Pub/Sub API** フィールドの内容が正しくない形式の場合(正しい形式は `projects/...` で始まります)、[Enable Pub/Sub APIフィールドの形式を修正する](enable-real-time-developer-notifications-rtdn#fixing-incorrect-format-in-enable-pubsub-api-field) セクションを参照してください。 ::: 3. [Google Play Console](https://play.google.com/console/) を開き、アプリを選択して、**Monetize with Play** -> **Monetization setup** に進みます。**Google Play Billing** セクションで、**Enable real-time notifications** チェックボックスをオンにします。 4. Adaptyの **App Settings** でコピーした **Enable Pub/Sub API** フィールドの内容を、**Topic name** フィールドに貼り付けます。 5. Google Play Consoleで **Save changes** をクリックします。 <img src="/assets/shared/img/e55ba0e-paste_topic_name.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## 通知をテストする \{#test-notifications\} リアルタイムデベロッパーNotificationへの登録が成功したかどうかを確認するには: 1. Google Play Consoleの設定で変更を保存します。 2. Google Play Consoleの **Topic name** の下にある **Send test notification** をクリックします。 <img src="/assets/shared/img/rtdn-test.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. AdaptyのメニューにあるトップメニューからAdaptyの [**App settings > Android SDK**](https://app.adapty.io/settings/android-sdk) に移動します。テスト通知が送信されると、トピック名の上にそのステータスが表示されます。 <img src="/assets/shared/img/rtdn-adapty-test.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## Enable Pub/Sub APIフィールドの形式を修正する \{#fixing-incorrect-format-in-enable-pubsub-api-field\} **Enable Pub/Sub API** フィールドの内容が誤った形式の場合(正しい形式は `projects/...` で始まります)、以下の手順に従って問題を解決してください。 ### 1. APIの有効化と権限を確認する \{#1-verify-api-enablement-and-permissions\} 必要なAPIがすべて有効になっており、サービスアカウントに正しく権限が付与されていることを慎重に確認してください。これらの手順をすでに完了している場合でも、サブステップが抜けていないことを確かめるために再度確認することが重要です。以下のセクションの手順を繰り返してください: 1. [Google Play ConsoleでデベロッパーAPIを有効にする](enabling-of-devepoler-api) 2. [Google Cloud Consoleでサービスアカウントを作成する](create-service-account) 3. [Google Play Consoleでサービスアカウントに権限を付与する](grant-permissions-to-service-account) 4. [Google Play Consoleでサービスアカウントのキーファイルを生成する](create-service-account-key-file) 5. [Google Play Storeインテグレーションを設定する](google-play-store-connection-configuration) ### 2. ドメインポリシーを調整する \{#2-adjust-domain-policies\} **Domain restricted contacts** および **Domain restricted sharing** ポリシーを変更します: 1. [Google Cloud Console](https://console.cloud.google.com/) を開き、アプリを管理するためのサービスアカウントを作成したプロジェクトを選択します。 2. **Quick Access** セクションで、**IAM & Admin** を選択します。 <img src="/assets/shared/img/google-cloud-IAM-and-Admin.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. 左ペインで **Organization Policies** を選択します。 4. **Domain restricted contacts** ポリシーを見つけます。 <img src="/assets/shared/img/google-cloud-policy-action.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. **Actions** 列の省略記号ボタンをクリックし、**Edit policy** を選択します。 6. ポリシー編集ウィンドウで: 1. **Policy source** の下で、**Override parent's policy** ラジオボタンを選択します。 2. **Policy enforcement** の下で、**Replace** ラジオボタンを選択します。 3. **Rules** の下で、**ADD A RULE** ボタンをクリックします。 <img src="/assets/shared/img/google-cloud-edit-policy.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **New rule** -> **Policy values** の下で、**Allow All** を選択します。 <img src="/assets/shared/img/google-cloud-allow-all-policy.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. **SET POLICY** をクリックします。 7. **Domain restricted sharing** ポリシーについても、手順4〜6を繰り返します。 最後に、**Google Play RTDN topic name** タイトルの横にある **Enable Pub/Sub API** フィールドの内容を再作成します。フィールドは正しい形式になります。 リアルタイムデベロッパーNotification(RTDN)の有効化に成功したら、更新したポリシーの **Policy source** を **Inherit parent's policy** に戻すことを忘れずに行ってください。 ## 生イベントの転送 \{#raw-events-forwarding\} 場合によっては、Googleからの生のS2Sイベントを引き続き受け取りたいこともあるでしょう。Adaptyを使用しながらそれらを受け取り続けるには、**URL for forwarding raw Google events** フィールドにエンドポイントを追加するだけで、Googleからの生イベントをそのまま送信します。 <img src="/assets/shared/img/e388892-001774-September-22-GhkjOFbT.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> --- **次のステップ** 以下のプラットフォーム向けにAdapty SDKを設定します: - [Android](sdk-installation-android) - [React Native](sdk-installation-reactnative) - [Flutter](sdk-installation-flutter) - [Kotlin Multiplatform](sdk-installation-kotlin-multiplatform) - [Unity](sdk-installation-unity) --- # File: apple-search-ads --- --- title: "Apple Ads" description: "Apple Ads を Adapty と連携してサブスクリプションのコンバージョンを最適化しましょう。" --- :::important **App settings** の Apple Ads 連携は、基本的なアナリティクスと SplitMetrics Acquire および Asapty 連携にのみ使用されます。 [Apple Ads Manager](adapty-ads-manager) は別の接続を使用します。Apple Ads アカウントは [Apple Ads Manager の設定](adapty-ads-manager-get-started)で接続してください。 ::: Adapty は Apple Ads からアトリビューションデータを取得し、キャンペーンやキーワードのセグメンテーションで指標を分析するのに役立ちます。Adapty は SDK と AdServices Framework を通じて Apple Ads のアトリビューションデータを自動的に収集します。 Apple Ads 連携を設定すると、Adapty が Apple Ads からアトリビューションデータを受信し始めます。このデータはプロファイルページで簡単に確認できます。 <img src="/assets/shared/img/ba4a3e9-CleanShot_2023-08-21_at_15.14.592x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## 連携の設定 \{#set-up-integration\} ### Adapty を AdServices フレームワークに接続する \{#connect-adapty-to-the-adservices-framework\} [AdServices](https://developer.apple.com/documentation/adservices) 経由の Apple Ads は Adapty ダッシュボードでの設定が必要で、アプリ側でも有効化する必要があります。AdServices フレームワークを使って Adapty 経由で Apple Ads を設定するには、以下の手順に従ってください。 #### ステップ 1: 公開鍵を取得する \{#step-1-obtain-public-key\} Adapty ダッシュボードで [Settings -> Apple Ads](https://app.adapty.io/settings/apple-search-ads) に移動します。 事前に生成された公開鍵(Adapty がキーペアを用意しています)を見つけてコピーします。 <img src="/assets/shared/img/baa5998-CleanShot_2023-08-21_at_14.55.542x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> :::note Apple Ads アトリビューションに別のサービスや独自のソリューションを使用している場合は、独自の秘密鍵をアップロードできます。 ::: #### ステップ 2: Apple Ads でユーザー管理を設定する \{#step-2-configure-user-management-on-apple-ads\} [Apple Ads アカウント](https://ads.apple.com/app-store)で **Settings > User Management** ページに移動します。Adapty がアトリビューションデータを取得できるようにするには、別の Apple ID アカウントを招待して API Account Manager アクセス権を付与する必要があります。既存のアカウントを使用するか、この目的専用の新しいアカウントを作成してください。重要なのは、その Apple ID で Apple Ads にログインできる必要があることです。 <img src="/assets/shared/img/ec183b2-kdjsfldsfjkdsfdfd.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> #### ステップ 3: API 認証情報を生成する \{#step-3-generate-api-credentials\} 次に、新しく追加したアカウントで Apple Ads にログインします。Apple Ads の Settings -> API に移動します。先ほどコピーした公開鍵を指定のフィールドに貼り付けて、新しい API 認証情報を生成します。 #### ステップ 4: Apple Ads の認証情報を Adapty に設定する \{#step-4-configure-adapty-with-apple-ads-credentials\} Apple Ads の設定から Client ID、Team ID、Key ID をコピーします。Adapty ダッシュボードで、これらの認証情報を対応するフィールドに貼り付けます。 <img src="/assets/shared/img/7356113-CleanShot_2023-08-21_at_15.08.512x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### アプリを AdServices ネットワークに接続する \{#connect-your-app-to-the-adservices-network\} [AdServices フレームワークの設定](#connect-the-adservices-framework)が完了すると、Adapty は Apple Search Ad のアトリビューションデータの収集を自動的に開始します。SDK コードを追加する必要はありません。 iOS アプリケーションでは、このアトリビューションデータは**常に**他のソースからのデータより優先されます。この動作が不要な場合は、以下の手順で ASA アトリビューションを*無効化*してください。 ## 連携を無効化する \{#disable-integration\} Apple Search Ads アトリビューションをオフにするには、[**App Settings** -> **Apple Search Ads** タブ](https://app.adapty.io/settings/apple-search-ads)を開き、**Receive Apple Search Ads attribution** スイッチをオフにします。 <img src="/assets/shared/img/asa-disable.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> :::warning これを無効化すると、ASA アナリティクスの受信が完全に停止します。その結果、ASA はアナリティクスでの使用や連携への送信が行われなくなります。また、SplitMetrics Acquire と Asapty は ASA アトリビューションに依存して動作するため、機能しなくなります。 この変更以前に受信済みのアトリビューションデータには影響しません。 ::: ## 独自のキーをアップロードする \{#uploading-your-own-keys\} :::note オプション これらの手順は Apple Ads アトリビューションには必要ありません。Asapty などの他のサービスや独自ソリューションと連携する場合にのみ必要です。 ::: ASA アトリビューションに他のサービスや独自ソリューションを使用している場合は、独自の公開鍵・秘密鍵ペアを使用できます。 ### ステップ 1 \{#step-1\} ターミナルで秘密鍵を生成する ```text showLineNumbers title="Text" openssl ecparam -genkey -name prime256v1 -noout -out private-key.pem ``` Adapty の Settings -> Apple Ads でアップロードする(**Upload private key** ボタン) ### ステップ 2 \{#step-2\} ターミナルで公開鍵を生成する ```text showLineNumbers title="Text" openssl ec -in private-key.pem -pubout -out public-key.pem ``` この公開鍵は、API Account Manager ロールを持つアカウントの Apple Ads 設定で使用できます。これにより、生成された Client ID、Team ID、Key ID の値を Adapty や他のサービスで利用できます。 --- # File: account --- --- title: "アカウント詳細と請求" description: "Adapty アカウントを管理し、サブスクリプションのトラッキングに最適な設定を行いましょう。" --- **Account** ページでは、プロファイル、チームメンバー、請求情報を管理できます。 このページには 3 つのタブがあります。 - [一般設定](#general-settings) - [サブスクリプションと請求](#billing-info) - [メンバー](#members) アカウント設定にアクセスするには、右上の **Account** をクリックするか、[app.adapty.io/account](https://app.adapty.io/account) にアクセスしてください。 <img src="/assets/shared/img/account-info.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## 一般設定 \{#general-settings\} 「General」タブには、プロファイル、アカウント設定、表示設定、レポート設定が含まれています。 - **Profile**: 名前、姓、会社名を入力します。会社名は最大 256 文字まで入力できます。 - **Account settings**: 登録済みのメールアドレスを確認し、パスワードを変更できます。 - **Date & Time formats**: Adapty 全体での日付と時刻の表示形式を選択します。 - **American format**: January 31, 2022 および 12 時間表示 (AM/PM) - **European format**: 31 January, 2022 および 24 時間表示 (16:00) - **Email reports**: 1 つまたはすべてのアプリに対して、日次・週次・月次のレポートを設定します。すべてのアプリのレポートをまとめて受け取るか、選択した各アプリの詳細レポートを受け取るかを選べます。 <img src="/assets/shared/img/account-info.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## サブスクリプションと請求 \{#billing-info\} **Subscription & Billing** タブでは、支払い情報と機能へのアクセスを管理できます。 - 支払い情報の追加または更新 - 請求情報の確認 - 追加の有料機能の購入 機能と料金の詳細については、[こちら](https://adapty.io/pricing)をご覧ください。 ## メンバー \{#members\} アカウント設定からチームメンバーを管理できます。チームメンバーを追加するには、メールアドレスで招待してロールを割り当ててください。 チームメンバーとアクセス権限の管理については、[こちら](members-settings)をご覧ください。 --- # File: members-settings --- --- title: "メンバー" description: "Adaptyダッシュボードでメンバーの設定と権限を管理します。" --- :::note このページはAdaptyダッシュボードのメンバーに関するものです アプリのユーザーに異なるアクセスレベルを付与したい場合は、[アクセスレベル](access-level)を参照してください。 ::: Adaptyダッシュボードのメンバーシステムでは、Adaptyへのアクセスレベルを各メンバーごとに設定し、利用可能なアプリを指定することができます。 ## ロール \{#roles\} Adaptyダッシュボードでは、メンバーに以下のロールを割り当てることができます。 | ロール | 請求情報へのアクセス | 新しいメンバーの追加 | 変更の実行 | すべてのセクションへのアクセス | |-------------|-------------------|-----------------|-----------------|------------------------| | Owner | ✅ | ✅ | ✅ | ✅ | | Admin | ❌ | ✅ | ✅ | ✅ | | Developer | ❌ | ❌ | ✅ | ❌ | | Viewer | ❌ | ❌ | ❌ | ✅ | | Support | ❌ | ❌ | ❌ | ❌ | | ASA manager | ❌ | ❌ | ❌ | ❌ | - **Owner:** OwnerはAdaptyアカウントの最初の作成者であり、最高レベルのアクセス権と管理権を持ちます。Ownerは請求情報に完全にアクセスでき、支払い情報やサブスクリプションプランを管理できます。また、新しいメンバーのアプリアクセスを指定できるのはOwnerとAdminのみです。各Adaptyアカウントに設定できるOwnerは1人のみです。 - **Admin:** Adminロールのメンバーは、選択したアプリケーションへの完全なアクセス権を持ちます。ペイウォールの作成・編集、A/B テストの実施、アナリティクスの分析、メンバー管理など、さまざまな管理タスクを行えます。 - **Developer:** Developerロールのメンバーはアナリティクスとアカウントメンバーを除くすべての機能にフルアクセスできます。請求設定にはアクセスできません。このロールは、ペイウォールやA/B テストなどの設定やAdaptyのアプリへの統合を担当するが、財務データを閲覧すべきでない担当者向けです。 - **Viewer:** ViewerロールのメンバーはAdaptyへの読み取り専用アクセスを持ちます。情報の閲覧はできますが、ペイウォールやA/B テストなどの作成・編集、新規ユーザーの招待、新規アプリの作成、アプリ設定の変更はできません。 - **Support:** Supportロールのメンバーは、選択したアプリケーション内のユーザープロファイルにのみアクセスできます。新しいメンバーの追加やAdaptyの他のセクションへのアクセスはできません。このロールは、サブスクリプション関連の問い合わせやトラブルシューティングで顧客をサポートするチームや担当者に特に適しています。 - **ASA manager:** ASA managerロールのメンバーは[Apple Ads Manager](adapty-ads-manager)ダッシュボードにのみアクセスできます。 ## メンバーを追加する \{#add-a-member\} Adaptyでは最大256人のチームメンバーを招待できます。新しいメンバーの追加は無料です。 :::note Adaptyにまだ登録されていないメールアドレスのみ招待できます。同僚がすでに独立したアカウントを持っている場合は、別のメールアドレスで招待するか、Adaptyサポートに既存アカウントの削除を依頼してください。 ::: チームメンバーを追加するには: 1. 右上の **Account** をクリックして **Members** タブを開きます。 2. **Invite member** をクリックします。 <img src="/assets/shared/img/invite-member.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. メンバーのメールアドレスを入力します。 4. リストから[ロール](#roles)を選択します。 5. アクセスを付与するアプリを選択します。 6. (任意)**Always allow access to new apps** を有効にすると、将来追加されるアプリにも自動的にアクセス権が付与されます。 7. **Save** をクリックします。 <img src="/assets/shared/img/add-member.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '500px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## アカウントのオーナーシップを移譲する \{#transfer-account-ownership\} **アカウントのオーナーシップ**全体を移譲する必要がある場合は、[support@adapty.io](mailto:support@adapty.io)のサポートチームにお問い合わせください。 **アプリのオーナーシップ**を移譲する必要がある場合は、[専用ガイド](transfer-apps)を参照してください。 --- # File: set-up-app-store-connect --- --- title: "App Store Connect のセットアップ" description: "Apple Developer Program への登録とアプリ内課金のための App Store Connect セットアップを初めて行う開発者向けガイド。" --- **初めて iOS アプリを開発する場合**、Adapty を統合する前に Apple Developer アカウントと App Store Connect のセットアップを行う必要があります。 :::note すでに Apple Developer アカウントをお持ちで、App Store Connect にアプリを登録済みの場合は、このガイドをスキップして [App Store との初期連携](initial_ios) に直接進んでください。 ::: ## ステップ 1. Apple Developer Program に登録する \{#step-1-enroll-in-apple-developer-program\} App Store でアプリを配布してアプリ内課金を販売するには、[Apple Developer Program](https://developer.apple.com/programs/) に参加する必要があります。 ### 登録タイプを選択する \{#choose-enrollment-type\} Apple では 2 種類の登録タイプを用意しています。 | | 個人 | 組織 | |-----------------------------|--------------------|------------------------------| | **対象者** | 個人開発者 | 企業・チーム・非営利団体 | | **D-U-N-S ナンバーの要否** | 不要 | 必要 | | **アプリの公開名** | 個人名 | 組織名 | | **チーム管理** | 利用不可 | 利用可能 | :::tip 組織として登録する場合は、**D-U-N-S ナンバー**(Dun & Bradstreet が発行する 9 桁の企業識別番号)が必要です。[組織にすでに番号が割り当てられているか確認する](https://developer.apple.com/enroll/duns-lookup/) か、ページ下部のリンクから新規取得を申請できます。D-U-N-S ナンバーの発行には最大 5 営業日かかる場合があります。 ::: ### 登録する \{#enroll\} 1. [Apple Developer Program の登録ページ](https://developer.apple.com/programs/enroll/) にアクセスします。 2. Apple ID でサインインします。Apple ID をお持ちでない場合は、先に作成してください。 3. 登録タイプ(個人または組織)に応じた手順に従います。 4. 年会費を支払います。 Apple が登録を処理すると、[App Store Connect](https://appstoreconnect.apple.com) へのアクセスが付与されます。登録には通常最大 48 時間かかります。組織の場合、D-U-N-S の確認が必要なときはさらに時間がかかることがあります。 ## ステップ 2. App Store Connect でアプリをセットアップする \{#step-2-set-up-your-app-in-app-store-connect\} アプリ内課金を販売する前に、App Store Connect で初期設定を完了する必要があります。この設定には、契約への署名、支払い情報の追加、アプリの登録が含まれます。 ### 有料アプリケーション契約に署名する \{#sign-the-paid-applications-agreement\} App Store で販売するには、Apple の Paid Applications Agreement(有料アプリケーション契約)への署名が必要です。これは有料アプリだけでなく、無料アプリ内のアプリ内課金にも適用されます。 1. [App Store Connect](https://appstoreconnect.apple.com/business) の **Business** ページに移動します。 2. **Paid Apps** の契約を見つけ、**Review and Agree** をクリックします。 3. 必要な情報を入力します。 - **Banking information**: Apple から収益が振り込まれる銀行口座を追加します。 - **Tax information**: 販売したい国の税務フォームに記入します。 - **Contact information**: 連絡先情報を入力します。 :::important 契約を有効にするには、3 つのセクション(銀行情報、税務情報、連絡先情報)をすべて入力する必要があります。契約が有効になるまで、アプリ内課金を販売することはできません。 ::: ### Bundle ID を作成する \{#create-a-bundle-id\} Bundle ID は、Apple のエコシステム全体でアプリを一意に識別します。App Store Connect へのアプリ登録と Adapty 連携の設定に必要です。 1. [Apple Developer ポータル](https://developer.apple.com/account) を開きます。 2. **Certificates, Identifiers & Profiles** → **Identifiers** に移動します。 3. **+** をクリックして新しい識別子を登録します。 4. **App IDs** を選択して **Continue** をクリックします。 5. タイプとして **App** を選択し、**Continue** をクリックします。 6. 以下の項目を入力します。 - **Description**: この Bundle ID を識別するための名前(例:「My Subscription App」)。 - **Bundle ID**: **Explicit** を選択し、逆ドメイン形式の一意の識別子を入力します(例:`com.yourcompany.yourapp`)。 7. **Capabilities** セクションで下にスクロールし、**In-App Purchase** にチェックを入れます。 8. **Continue** をクリックし、次に **Register** をクリックします。 ### App Store Connect にアプリを登録する \{#register-your-app-in-app-store-connect\} 1. [App Store Connect](https://appstoreconnect.apple.com/apps) の **Apps** ページに移動します。 2. **+** → **New App** をクリックします。 3. 必要な項目を入力します。 - **Platforms**: **iOS** を選択します。 - **Name**: App Store に表示されるアプリ名。 - **Primary language**: アプリのメタデータのデフォルト言語。 - **Bundle ID**: 前の手順で作成した Bundle ID を選択します。 - **SKU**: アプリの一意の識別子(ユーザーには表示されません)。例:`my_subscription_app_2025`。 4. **Create** をクリックします。 これでアプリが App Store Connect に登録され、Adapty 連携の準備が整いました。 ## 次のステップ \{#whats-next\} - [App Store との初期連携](initial_ios): App Store アプリを Adapty に接続する - [SDK の統合](quickstart-sdk): Adapty SDK をアプリのコードに統合する - [サンドボックステスト](test-purchases-in-sandbox): リリース前にアプリ内課金をテストする - [iOS アプリを App Store に提出する](submit-app-to-app-store): ビルドをアップロードして Apple の審査に提出する - [App Store Small Business Program](app-store-small-business-program): App Store の手数料を 30% から 15% に引き下げる --- # File: app-store-products --- --- title: "App Store のプロダクト" description: "Adapty のサブスクリプションツールを使って App Store のプロダクトを効率的に管理しましょう。" --- このページでは、App Store Connect でプロダクトを作成する方法を説明します。Adapty の機能とは直接関係ない内容も含まれますが、App Store Connect アカウントでプロダクトを作成する際に困ったときに役立つ情報です。 Adapty に連携するプロダクトを作成するには、以下の手順に従ってください。 1. **App Store Connect** を開き、左側メニューの [**Monetization** → **Subscriptions**](https://appstoreconnect.apple.com/apps/6477523342/distribution/subscriptions) セクションに進みます。 <img src="/assets/shared/img/148c3b5-subscriptions.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. サブスクリプショングループをまだ作成していない場合は、**Subscription Groups** タイトルの下にある **Create** ボタンをクリックして作成を開始します。App Store Connect の [Subscription Groups](https://developer.apple.com/help/app-store-connect/manage-subscriptions/offer-auto-renewable-subscriptions) は、プロダクトを分類・管理し、ユーザーがさまざまなプランをシームレスに切り替えられるようにするための機能です。なお、グループ外にサブスクリプションを作成することはできません。 3. 表示された **Create Subscription Group** ウィンドウで、**Reference Name** フィールドに新しいサブスクリプショングループ名を入力します。参照名は、アプリ内の異なるサブスクリプショングループを区別・管理するために自分で定義するラベルまたは識別子です。 参照名はユーザーには表示されず、主に内部での整理・管理に使用します。App Store Connect の管理画面で特定のサブスクリプショングループを識別・参照する際に役立ちます。複数のサブスクリプションプランがある場合や、アプリの構成に合った形でカテゴリ分けしたい場合に特に便利です。 <img src="/assets/shared/img/3f93c44-create_subscription_group.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **Create** ボタンをクリックして、サブスクリプショングループの作成を確定します。 5. サブスクリプショングループが作成され、開かれます。次に、グループ内にサブスクリプションを作成します。**Subscriptions** タイトルの下にある **Create** ボタンをクリックします。既存のグループに新しいサブスクリプションを追加する場合は、**Subscriptions** タイトルの隣にある **Plus** ボタンをクリックします。 <img src="/assets/shared/img/22fc643-add_subscription.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 6. 表示された **Create Subscription** ウィンドウで、**Reference Name** フィールドに名前を、**Product ID** フィールドにサブスクリプションの固有コードを入力します。 Reference Name は、App Store Connect 内でアプリ内サブスクリプションを識別するための専用識別子です。App Store のユーザーには表示されません。作成するサブスクリプションの内容が明確にわかる、人が読みやすい説明文を使用することをお勧めします。なお、この名前は 64 文字以内にする必要があります。 Product ID は、開発フェーズでプロダクトにアクセスし、アプリ内サブスクリプションを管理するサービスである Adapty と同期するために必要な、一意の英数字識別子です。Product ID には英数字、ピリオド、アンダースコアのみ使用できます。 <img src="/assets/shared/img/04aca55-create_subscription.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 7. **Create** ボタンをクリックして、サブスクリプションの作成を確定します。 8. サブスクリプションが作成され、開かれます。次に、**Subscription Duration** リストからサブスクリプションの期間を選択します。サブスクリプション名に期間が既に含まれている場合でも、**Subscription Duration** フィールドへの入力を忘れずに行ってください。 <img src="/assets/shared/img/f56cf0f-subscription_duration.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 9. 次は、サブスクリプションの価格を設定します。**Subscription Prices** タイトルの下にある **Add Subscription Price** ボタンをクリックしてください。見つからない場合は、下にスクロールしてみてください。 10. 表示された **Subscription Price** ウィンドウで、**Country or Region** リストから基準となる国を、**Price** リストから基準となる通貨を選択します。Appleがこの基本価格と最新の為替レートをもとに、175 か国・地域すべての価格を自動計算します。 <img src="/assets/shared/img/de1cec8-subscription_price.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 11. **Next** ボタンをクリックします。表示された **Price by Country or Region** ウィンドウには、すべての国の価格が自動計算された状態で表示されます。必要に応じて変更することもできます。 <img src="/assets/shared/img/2a047a6-price_by_country.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 12. 地域別の価格を更新したら、ウィンドウ下部の **Next** ボタンをクリックして進みます。 13. 表示された **Confirm Subscription Price?** ウィンドウで、最終的な価格を慎重に確認します。価格を修正する場合は、**Back** ボタンをクリックして **Price by Country or Region** ウィンドウに戻り、更新できます。価格に問題がなければ、**Confirm** ボタンをクリックします。 <img src="/assets/shared/img/d2b2031-confirm_prices.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 14. **Confirm Subscription Price?** ウィンドウを閉じた後、サブスクリプションウィンドウで **Save** ボタンをクリックするのを忘れないでください。クリックしないと、サブスクリプションが作成されず、入力したデータがすべて失われます。 なお、ここまでの手順は自動更新サブスクリプション(Auto-Renewable Subscription)の設定を対象としています。その他の種類のアプリ内課金を設定する場合は、サイドバーの「Subscriptions」ではなく **In-App Purchases** タブをクリックしてください。そこから、さまざまな種類のアプリ内課金を管理・作成できるセクションにアクセスできます。 <img src="/assets/shared/img/5663d85-in-app_purchases.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### Adapty にプロダクトを追加する \{#add-products-to-adapty\} App Store Connect でのアプリ内課金、サブスクリプション、オファーの追加が完了したら、次は [これらのプロダクトを Adapty に追加](create-product) します。 --- # File: apple-app-privacy --- --- title: "Apple App Privacy" description: "Appleアプリのプライバシーポリシーとサブスクリプションアプリへの影響を理解する。" --- Appleは、App Store Connectの **App Privacy** セクションおよびアプリのマニフェストファイルとして、すべての新しいアプリおよびアップデートに対してプライバシーの開示を義務付けています。AdaptyはアプリのサードパーティSDKであるため、ユーザーデータに関してAdaptyをどのように使用しているかを開示する必要があります。 ## Apple アプリプライバシーマニフェスト \{#apple-app-privacy-manifest\} `PrivacyInfo.xcprivacy` という名前の[プライバシーマニフェストファイル](https://developer.apple.com/documentation/bundleresources/describing-data-use-in-privacy-manifests)は、アプリが使用するプライベートデータとその理由を記述します。アプリオーナーはすべて、自分のアプリ用のマニフェストファイルを作成する必要があります。さらに、追加のSDKを統合している場合は、[プライバシーマニフェストと署名が必要なSDK](https://developer.apple.com/support/third-party-SDK-requirements/)リストに含まれるSDKのマニフェストファイルが含まれていることを確認してください。アプリをビルドする際、Xcodeはこれらすべてのマニフェストファイルを1つにまとめます。 Adaptyは[プライバシーマニフェストと署名が必要なSDK](https://developer.apple.com/support/third-party-SDK-requirements/)のリストには含まれていませんが、Adapty SDK バージョン2.10.2以降では便宜のためにマニフェストが含まれています。マニフェストを取得するためにSDKを更新してください。 Adaptyはアプリプライバシーレポートとも呼ばれるマニフェストファイルにデータを含める必要はありませんが、トラッキングのためにAdaptyの `customerUserId` を使用している場合は、次のようにマニフェストファイルに指定する必要があります: 1. プライバシー情報ファイルの `NSPrivacyCollectedDataTypes` 配列にディクショナリを追加します。 2. ディクショナリに `NSPrivacyCollectedDataType`、`NSPrivacyCollectedDataTypeLinked`、`NSPrivacyCollectedDataTypeTracking` キーを追加します。 3. `NSPrivacyCollectedDataTypes` ディクショナリの `NSPrivacyCollectedDataType` キーに、文字列 `NSPrivacyCollectedDataTypeUserID`([マニフェストファイルで報告するデータカテゴリとタイプの一覧](https://developer.apple.com/documentation/bundleresources/describing-data-use-in-privacy-manifests#Describe-the-data-your-app-or-third-party-SDK-collects)における `UserID` データタイプの識別子)を追加します。 4. `NSPrivacyCollectedDataTypes` ディクショナリの `NSPrivacyCollectedDataTypeTracking` および `NSPrivacyCollectedDataTypeLinked` キーに `true` を追加します。 5. `NSPrivacyCollectedDataTypes` ディクショナリの `NSPrivacyCollectedDataTypePurposes` キーの値として、文字列 `NSPrivacyCollectedDataTypePurposeProductPersonalization` を使用します。 カスタム属性を使用してオーディエンスにペイウォールをターゲティングしている場合は、使用しているカスタム属性が[マニフェストファイルで報告するデータカテゴリとタイプ](https://developer.apple.com/documentation/bundleresources/describing-data-use-in-privacy-manifests)に該当するかどうかを慎重に確認してください。該当する場合は、データタイプごとに上記の手順を繰り返してください。 収集するすべてのデータタイプとカテゴリを報告したら、[Appleのドキュメント](https://developer.apple.com/documentation/bundleresources/describing-data-use-in-privacy-manifests#Create-your-apps-privacy-report)に従ってアプリのプライバシーレポートを作成してください。 ## App Store Connectでのプライバシー開示 \{#apple-app-privacy-disclosure-in-app-store-connect\} 1. [App Store Connect](https://appstoreconnect.apple.com/)でアプリを開き、**App Privacy** に移動します。**Get Started** をクリックします。 <img src="/assets/shared/img/app-privacy-get-started.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. **Yes, we collect data from this app** を選択し、**Next** をクリックします。 <img src="/assets/shared/img/app-privacy-data-collection.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### データタイプ \{#data-types\} 以下の表は、Appleが開示を求めるデータタイプと、Adaptyが必要とするものを示しています。**これはAdaptyのみを対象としています。** アプリが他のSDKや独自のコードを通じて追加データを収集する場合は、それらのデータタイプも選択してください。 ✅ = Adaptyが必要とする 👀 = 必要な場合あり(詳細は下記参照) ❌ = Adaptyでは不要 — アプリが他の手段でこのデータを収集する場合に選択 | データタイプ | 必要 | 備考 | |--------------------------------------------------------------|----------|----------------------------------------------------------------------------------------------------------------------------------------------------| | 識別子 | ✅ | <p>customerUserIdでユーザーを識別している場合は、「User ID」を選択します。</p><p></p><p>AdaptyはIDFAを収集するため、「Device ID」を選択する必要があります。</p> | | 購入 | ✅ | Adaptyはユーザーの購入履歴を収集します。 | | 名前、電話番号、メールアドレスなどの連絡先情報 | 👀 | **`updateProfile`** メソッドを使用して名前、電話番号、メールアドレスなどの個人データを渡す場合に必要です。 | | 使用状況データ | 👀 | Amplitude、Mixpanel、AppMetrica、Firebaseなどのアナリティクスを使用している場合に必要な場合があります。 | | 位置情報 | ❌ | Adaptyは正確な位置情報を収集しません。アプリが収集する場合は選択してください。 | | ヘルス&フィットネス | ❌ | Adaptyはヘルスやフィットネスデータを収集しません。アプリが収集する場合は選択してください。 | | 機密情報 | ❌ | Adaptyは機密情報を収集しません。アプリが収集する場合は選択してください。 | | ユーザーコンテンツ | ❌ | Adaptyはユーザーコンテンツを収集しません。アプリが収集する場合は選択してください。 | | 診断情報 | ❌ | Adaptyは診断データを収集しません。アプリが収集する場合は選択してください。 | | 閲覧履歴 | ❌ | Adaptyは閲覧履歴を収集しません。アプリが収集する場合は選択してください。 | | 検索履歴 | ❌ | Adaptyは検索履歴を収集しません。アプリが収集する場合は選択してください。 | | 連絡先 | ❌ | Adaptyは連絡先リストを収集しません。アプリが収集する場合は選択してください。 | | 財務情報 | ❌ | Adaptyは財務情報を収集しません。アプリが収集する場合は選択してください。 | ### 必須データタイプ \{#required-data-types\} #### 購入 \{#purchases\} Adaptyを使用する場合、アプリが**購入履歴**を収集することを開示する必要があります。 <img src="/assets/shared/img/feb3b9f-CleanShot_2023-08-25_at_12.32.552x.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> #### 識別子 \{#identifiers\} Adaptyを使用する場合、次の識別子を開示する必要があります: - **Device ID** — AdaptyはIDFAを収集します。 - **User ID** — **`customerUserId`** でユーザーを識別する場合に必要です。 <img src="/assets/shared/img/93f3daa-CleanShot_2023-08-25_at_12.35.272x.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### データの使用目的 \{#data-usage\} **データタイプ**を保存した後、データの使用目的を示す必要があります: 1. **Purchases** ブロック内の **Set up purchase history** をクリックします。 <img src="/assets/shared/img/purchase-privacy.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. Appleが購入履歴データの使用目的を尋ねてきたら、Adaptyに関して以下を選択します: - **Analytics** — Adaptyは収益アナリティクス、コホート、および指標のために購入履歴を使用します。 - **Product Personalization** — Adaptyはオーディエンスのセグメンテーションとペイウォールのターゲティングのために購入データを使用します。 - **App Functionality** — Adaptyは購入を検証し、アクセスレベルを管理し、サブスクリプションの状態を追跡します。 アプリが他の方法で購入データを使用する場合(例:Adaptyインテグレーション経由で広告プラットフォームに購入イベントを送信する場合)は、追加の目的を選択してください。 <img src="/assets/shared/img/purchase-history.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. **Next** をクリックします。 4. **Device ID** および **User ID**(使用している場合)のいずれについても: 1. **User/Device ID** ブロック内の **Set up user/device ID** をクリックします。 2. Appleが識別子データの使用目的を尋ねてきたら、Adaptyに関して以下を選択します: - **App Functionality** — Adaptyはユーザープロファイルの管理、購入の紐付け、アクセスレベルの追跡のために識別子を使用します。 Adaptyインテグレーション(AppsFlyerやAdjustなど)経由でサードパーティプラットフォームにアトリビューションデータを送信する場合は、**Third-Party Advertising** も選択してください。アプリが他の方法で識別子を使用する場合は、追加の目的を選択してください。 <img src="/assets/shared/img/user-id-privacy.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. **Next** をクリックします。 --- # File: apple-family-sharing --- --- title: "Appleファミリー共有" description: "AdaptyでAppleファミリー共有を有効にして、共有サブスクリプションをサポートします。" --- Appleのファミリー共有を使うと、アプリ内課金を家族メンバー間で共有できます。ビデオストリーミングサービスや子ども向けアプリなど、グループ向けアプリのユーザーが、Apple IDを共有せずにサブスクリプションを分け合える便利な仕組みです。最大5人の家族メンバーがサブスクリプションを利用できるようになるため、[ファミリー共有](https://developer.apple.com/documentation/storekit/supporting-family-sharing-in-your-app)はアプリのユーザーエンゲージメントや継続率の向上に役立ちます。 このガイドでは、ファミリー共有にサブスクリプションをオプトインする方法と、Adaptyがファミリー内で共有された購入をどのように管理するかについて説明します。 特定のプロダクトのファミリー共有を有効にするには、まず[App Store Connect](https://appstoreconnect.apple.com/)にアクセスしてください。ファミリー共有は、新規・既存のアプリ内課金いずれもデフォルトでオフになっているため、各アプリ内課金ごとに個別に有効化する必要があります。**アプリのページ**にアクセスし、対象のアプリ内課金ページに移動して、ファミリー共有セクションの**Turn On**オプションを選択するだけで簡単に設定できます。 一度プロダクトのファミリー共有を有効にすると、**再び無効にすることはできません**。すでに家族とサブスクリプションを共有しているユーザーのエクスペリエンスが損なわれるためです。 また、共有できるのは非消耗型アイテムとサブスクリプションのみである点にもご注意ください。 <img src="/assets/shared/img/6db165a-CleanShot_2023-03-28_at_17.15.342x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 表示されたモーダルで**Confirm**ボタンをクリックすると、設定が完了します。完了すると、ファミリー共有セクションに「このサブスクリプションはファミリーグループの全員で共有できます」というメッセージが表示されます。これにより、サブスクリプションがファミリー共有に対応し、最大5人の家族メンバーと共有できるようになったことが確認できます。 Adaptyでは、追加の作業なしでファミリー共有をサポートできます。[App Storeのプロダクトを設定](app-store-products)するだけで、App Store Connectで**ファミリー共有**を**有効化**すると、**Adapty**に自動的に反映され、Webhookでイベントとして受信されます。 :::note ファミリー共有はサンドボックス環境ではサポートされていません。 ::: ユーザーがサブスクリプションを購入して家族メンバーと共有した場合、家族メンバーが利用できるようになるまで**最大1時間の遅延**が発生することがあります。これはAppleが意図的に設けたもので、ユーザーが気が変わった際に共有を取り消せるようにするためです。ただし、サブスクリプションが更新された場合、家族メンバーへの反映に遅延はありません。 ユーザーがファミリー共有対応のアプリ内プロダクトを購入すると、通常通りレシートにトランザクションが記録されますが、`in_app_ownership_type`というフィールドが追加され、値は`PURCHASED`となります。さらに、すべての家族メンバーに対して新しいトランザクションが作成され、元の購入とは異なる`web_order_line_item_id`および`original_transaction_id`が付与されます。この場合、`in_app_ownership_type`フィールドの値は`FAMILY_SHARED`となります。 正確な収益計算を行うため、Adaptyアナリティクスでは`in_app_ownership_type`が`PURCHASED`のトランザクションのみを集計します。`FAMILY_SHARED`トランザクションは収益およびコンバージョン指標から除外されます。 **ファミリー共有トランザクションに送信されるイベント** `FAMILY_SHARED`トランザクションは**アクセスレベル更新**イベントのみを発火します。プロダクト単位のサブスクリプションイベントは家族メンバーには発火しません。 | イベント | `FAMILY_SHARED` | `PURCHASED` | | --- | --- | --- | | **アクセスレベル更新** | あり | あり | | **サブスクリプション開始** | なし | あり | | **トライアル開始** | なし | あり | | **サブスクリプション更新** | なし | あり | | **サブスクリプション終了** | なし | あり | | **サブスクリプション返金** | なし | あり | | **請求エラー検出** | なし | あり | ダウンストリームのアナリティクスが**サブスクリプション開始**を基準にしている場合、家族メンバーはそこに表示されません。アクティブな家族メンバーを検出するには、**アクセスレベル更新**を使用してください。 Adaptyで他の家族メンバーを特定するには、イベントの詳細を確認します。まず、元のファミリー購入トランザクションを見つけます。次に、そのトランザクションのイベント詳細で、同じプロダクト、購入日、有効期限のものを探してください。イベント詳細を分析することで、元の購入に関連する他のファミリーメンバーシップトランザクションを特定できます。 --- # File: app-store-small-business-program --- --- title: "App Store Small Business Program" description: "Apple の Small Business Program の内容と、収益および Adapty のアナリティクスへの影響について説明します" --- :::link 対応する Play Store プログラムについては、[Google 手数料減額サービス](google-reduced-service-fee)をご覧ください。 ::: 年間の App Store 収益が 100 万ドル以下の組織は、Apple の [Small Business Program](https://developer.apple.com/app-store/small-business-program/) に参加できます。登録すると、標準の 30% ストア手数料が **15%** に引き下げられます。 プログラムに参加する場合は、収益計算とインテグレーションイベントの処理を正確に行うために、**Adapty の設定を変更する**必要があります。 この記事では以下について説明します: * [アプリが Small Business Program に登録されている場合の Adapty 設定方法](#configure-adapty) * [ストア手数料を削減するためのプログラム登録方法](#apply-for-the-program) ## Adapty の設定 \{#configure-adapty\} Adapty では、[アナリティクス](analytics)および[インテグレーションイベント](analytics-integration)に対して引き下げられた手数料率を適用できます。有効にするには、アプリごとに Small Business Program のステータスを指定してください。 :::warning 承認を受けたら**すぐに** Adapty で SBP ステータスを設定してください。遅れて変更しても、配信済みの Webhook イベントは書き換えられません([詳細](#retroactive-setting-changes))。 ::: 1. [**App Settings** → **General**](https://app.adapty.io/account) を開きます。 2. **Small Business Program** セクションを見つけます。 3. **Add period** をクリックします。 4. メンバーシップの開始日を選択します。 5. 終了日を選択するか、**At the current moment** チェックマークを有効にしてステータスを無期限に延長します。将来[資格を失った](#losing-eligibility)場合は、終了日を変更できます。 6. **Apply** をクリックします。 組織がプログラムの資格を維持している場合、メンバーシップは翌暦年に引き継がれます。ただし、メンバーシップステータスは**指定した期間のみ**に適用されます。 * **Add period** をクリックして新しいメンバーシップ期間を追加します。 * ステータスを無期限に延長するには、**At the current moment** チェックマークを有効にします。 設定を確認するには、[収益チャート](revenue)を開き、**Proceeds after store commission** を選択します。表示される収益が引き下げ後の手数料率を反映していることを確認してください。 ## プログラムへの申請 \{#apply-for-the-program\} ### 資格要件 \{#eligibility-requirements\} Apple は**年間収益**(前暦年の売上からストア手数料と税金を差し引いた金額)に基づいて SBP の資格を判定します。 資格を得るには、あなたの組織とその<InlineTooltip tooltip="関連デベロッパーアカウント">あなたまたはあなたの組織が過半数の所有権(50%超)または意思決定権を持つアカウント。</InlineTooltip>の年間収益の合計が 100 万ドル以下である必要があります。 新規作成の組織は、自動的にプログラムへの申請資格があります。 ### 申請前の確認事項 \{#before-you-apply\} 以下を確認してください: - Apple Developer Program のアカウントホルダーであること - App Store Connect で最新の有料アプリケーション契約に同意していること - すべての関連デベロッパーアカウントをリストアップできること ### 登録手順 \{#enrollment\} 1. [App Store Small Business Program 登録ページ](https://developer.apple.com/app-store/small-business-program/)にアクセスします。 2. **Enroll** をクリックし、Apple Developer アカウントでサインインします。 3. 事前入力された情報(名前、メール、Team ID)を確認して送信します。 ### 審査 \{#review\} 審査プロセスには 1 か月以上かかる場合があります。資格がある場合は、Apple から承認メールが届きます。 承認後、待機期間があります。引き下げられた手数料は、Apple の[次の会計期間](https://adapty.io/apple-fiscal-calendar/)の 15 日目から適用されます。それ以前の取引には適用されません。 ### 資格の喪失 \{#losing-eligibility\} 現在の暦年の累計収益が 100 万ドルを超えると、プログラムのメンバーシップを失い、Apple が標準の 30% 手数料を適用し始めます。 :::important ビジネスが Small Business Program を離れる場合は、設定の終了日を**すぐに変更してください**。変更しないと、Adapty は引き続き引き下げ後の手数料率で計算を続けます。 ::: 年間収益が再び 100 万ドルを下回った**翌年**に、プログラムに再申請できます。詳細については、[公式プログラム規約](https://developer.apple.com/app-store/small-business-program/)をご覧ください。 ## 設定の遡及的変更 \{#retroactive-setting-changes\} --- no_index: true --- Adapty で手数料減額ステータスをさかのぼって変更した場合、新しい手数料率は Adapty のデータに異なるスケジュールで反映されます: | 反映される場所 | 手数料率を変更した後の動作 | | --- | --- | | アナリティクスダッシュボード(Revenue、Proceeds、MRR、ARR) | 日次再計算が実行される24時間以内に、新しい手数料率が適用されます。 | | S3、GCS、BigQuery エクスポート | 次回のスケジュールされたエクスポート時に、新しい手数料率が適用されます。 | | 配信済みの Webhook イベント | Adapty は配信後の Webhook イベントを変更できません。古い手数料率のままになります。 | データウェアハウスに Webhook イベントからの収益データが保存されている場合、それらのレコードには古い手数料率が残ります。データを調整するには、アナリティクスダッシュボードから該当期間のデータを取得するか、S3、GCS、または BigQuery への新しいエクスポートを生成してください。 --- # File: android-products --- --- title: "Play Storeのプロダクト" description: "AdaptyでAndroidプロダクトを管理し、アプリ内課金を効率化して、収益化戦略を最適化しましょう。" --- このページでは、Play Storeでのプロダクト作成に関するガイダンスを提供します。この情報はAdaptyの機能に直接関係するものではありませんが、Google PlayコンソールでのプロダクトZo作成に困った際の参考資料として役立ちます。 プロダクトとは、Play Storeのアプリ内でユーザーに提供するデジタルアイテムやサービスのことで、通常は購入可能なものを指します。買い切り購入、サブスクリプション、その他のデジタルグッズなど、さまざまなアプリ内課金アイテムが含まれます。 [Googleの課金システム](https://developer.android.com/google/play/billing/compatibility)では、サブスクリプションに複数のベースプランを設定でき、各ベースプランにさまざまな割引やオファーを追加できます。この仕組みは、主に以下の3つの要素で構成されています: - **サブスクリプション:** 特定の期間、ユーザーが享受できるサービスセットを表します(販売するアイテム本体)。例えば、プレミアム機能を提供する「ゴールドティア」などがこれにあたります。 - **ベースプラン:** 請求期間、更新タイプ、価格の具体的な設定を表します(アイテムの販売方法)。「自動更新付き年間プラン」や「前払い月額プラン」などが例として挙げられます。 - **オファー:** 対象ユーザーに提供される割引で、ベースプランの価格を変更します。例えば「新規ユーザー向け14日間無料トライアル」などがこれにあたります。 ## Play Storeでプロダクトを作成するには? \{#how-to-create-a-product-in-play-store\} プロダクトとは、アプリ内でユーザーに提供するデジタルアイテムやサービスのことで、通常は購入可能なものを指します。買い切り購入、サブスクリプション、その他のデジタルグッズなど、さまざまなアプリ内課金アイテムが含まれます。 Androidデバイス向けにプロダクトを設定するには: 1. Google PlayコンソールのLeft menuから [**Monetize** -> **Subscriptions**](https://console.cloud.google.com/iam-admin/serviceaccounts) または [**Monetize** -> **In-app products**](https://console.cloud.google.com/iam-admin/serviceaccounts) セクションを開きます。 <img src="/assets/shared/img/6eff1d1-subscription_GP.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. **Create subscription** ボタンをクリックします。 <img src="/assets/shared/img/af7fe02-create_subscription_GP.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. 表示された **Create subscription** ウィンドウで、**Product ID** フィールドにサブスクリプションIDを、**Name** フィールドにサブスクリプション名を入力します。 Product IDはユニークである必要があり、数字または小文字で始まり、アンダースコア(\_)やピリオド(.)を含めることができます。開発中にプロダクトにアクセスしたり、Adaptyと同期したりするために使用されます。一度Google PlayコンソールでProduct IDがプロダクトに割り当てられると、そのプロダクトが削除されても、他のアプリで再利用することはできません。 Product IDの命名には、標準化されたフォーマットに従うことをお勧めします。より簡潔なアプローチとして、`<サブスクリプション名>.<アクセスレベル>` という形式でプロダクトに名前を付けることを推奨します。そうすることで、weekly、monthlyなどのベースプランを使って期間や請求頻度を管理できます。 Nameはあくまで内部参照用ですが、Google Playストアの掲載ページにも表示されるため、分かりやすい名前を自由に付けてください。最大55文字まで使用できます。 4. **Create** ボタンをクリックしてサブスクリプションの作成を確定します。 :::note AdaptyにおけるGoogle Playサブスクリプションプロダクト Adaptyのプロダクトは、Google Playサブスクリプションのベースプランに対応します。これは、ベースプランがユーザーが実際に購入できるプロダクトだからです。Adaptyは既存のGoogle Playサブスクリプションとそれに対応するベースプランの移行をシームレスに処理するため、追加の作業は不要です。ただし、Adaptyで新しいプロダクトを追加する際は、ベースプランIDとProduct IDの両方を指定する必要があります。 ::: ### ベースプランを作成する \{#create-a-base-plan\} サブスクリプションプロダクトには、ベースプランを追加する必要があります。ベースプランは、ユーザーがサブスクリプションを購入する際の請求期間、価格、更新タイプを決定します。なお、ユーザーはサブスクリプションプロダクトを直接購入するのではなく、常にサブスクリプション内のベースプランを購入する形になります。 ベースプランを作成するには: 1. Google PlayコンソールのLeft menuから [**Monetize** -> **Subscriptions**](https://console.cloud.google.com/iam-admin/serviceaccounts) セクションを開きます。そこで、ベースプランを追加したいサブスクリプションを見つけます。 2. サブスクリプションの横にある **View subscription** ボタンをクリックします。 <img src="/assets/shared/img/4072a2a-subscriptions_GP.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. サブスクリプションの詳細が表示されたら、**Base plans and offers** タイトルの下にある **Add base plan** ボタンをクリックします。スクロールダウンしないと表示されない場合があります。 <img src="/assets/shared/img/b493b60-add_base_plan.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. 表示された **Add base plan** ウィンドウで、**Plan ID** フィールドにベースプランのユニークな識別子を入力し、必須項目を入力します。IDは数字または小文字で始まり、数字(0-9)、小文字(a-z)、ハイフン(-)を含めることができます。 <img src="/assets/shared/img/8146763-CleanShot_2023-07-20_at_16.51.412x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. 地域ごとの価格を設定します。 <img src="/assets/shared/img/8b26e1d-prices.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 6. **Save** ボタンをクリックして設定を確定します。 7. **Activate** ボタンをクリックしてベースプランを有効化します。 Adaptyでは、サブスクリプションプロダクトには期間と更新タイプが一致する単一のベースプランのみ設定できる点にご注意ください。 ### フォールバックプロダクト \{#fallback-products\} :::warning 後方互換性のないベースプランのサポートについて 古いバージョンのAdapty SDKは、Google Billing Library v5+の機能(サブスクリプションプロダクトごとの複数ベースプランおよびオファー)をサポートしていません。これらのSDKバージョンでは、Google PlayコンソールでGame **[後方互換](https://support.google.com/googleplay/android-developer/answer/12124625?hl=en#backwards_compatible)** とマークされたベースプランのみにアクセスできます。なお、後方互換としてマークできるベースプランはサブスクリプションごとに1つだけです。 ::: <img src="/assets/shared/img/b5e70cb-CleanShot_2023-07-20_at_17.03.252x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Adaptyで強化されたGoogleサブスクリプションの設定と機能を最大限に活用するために、後方互換のフォールバックプロダクトを設定する機能を提供しています。このフォールバックプロダクトは、古いバージョンのAdapty SDKを使用するアプリ専用に使用されます。Google Playプロダクトを作成する際に、そのプロダクトをPlayコンソールで後方互換としてマークするかどうかを指定できます。Adaptyはこの情報を使って、そのプロダクトが古いバージョンのSDK(バージョン2.5以下)で購入可能かどうかを判断します。 例えば、`subscription.premium` というサブスクリプションに「週次(後方互換)」と「月次」の2つのベースプランがあるとします。`subscription.premium:weekly` プロダクトをAdaptyに追加する場合、後方互換プロダクトを指定する必要はありません。しかし、`subscription.premium:monthly` プロダクトの場合は、後方互換プロダクトを指定する必要があります。指定しないと、Google Billing Library v4で意図せず `subscription.premium:weekly` プロダクトが購入されてしまう可能性があります。このシナリオに対応するために、月次でかつ後方互換としてマークされたベースプランを持つ別のプロダクトを作成する必要があります。これにより、`subscription.premium:monthly` を選択したユーザーが正しい頻度で請求されることが保証されます。 ## Adaptyにプロダクトを追加する \{#add-products-to-adapty\} App Store Connectでアプリ内課金、サブスクリプション、オファーの追加が完了したら、次のステップとして[これらのプロダクトをAdaptyに追加](create-product)します。 --- # File: google-play-data-safety --- --- title: "Google Play データセーフティ" description: "AdaptyでGoogle Playデータセーフティポリシーへの準拠を確認します。" --- Google Playのデータセーフティセクションは、アプリ開発者がユーザーに対して、アプリが収集または共有するデータについて簡単に説明し、アプリの重要なプライバシーおよびセキュリティ対策を強調するための方法を提供しています。この情報により、ユーザーはダウンロードして使用するアプリを選ぶ際に、より十分な情報に基づいた判断ができるようになります。 以下は、Adaptyが収集するデータについての簡単なガイドです。Google Playに必要な情報を提供する際にご活用ください。 ## データ収集とセキュリティ \{#data-collection-and-security\} <img src="/assets/shared/img/3508c24-image4.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> **アプリは必要なユーザーデータタイプを収集または共有していますか?** Adaptyはユーザーの購入履歴を収集するため、「はい」を選択してください。 **アプリが収集するすべてのユーザーデータは転送中に暗号化されますか?** Adaptyは転送中のデータを暗号化するため、「はい」を選択してください。 **ユーザーがデータの削除をリクエストできる方法を提供していますか?** 「はい」を選択する場合は、ユーザーがサポートチームにデータ削除をリクエストできる手段を確保してください。Adapty ダッシュボードまたはREST APIから直接ユーザーを削除できます。 ## データタイプ \{#data-types\} 以下は、Googleが申告を求めるデータタイプの一覧です。Adaptyが各タイプのデータを収集するかどうかを示しています。 | データタイプ | 詳細 | | :---------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | 位置情報 | Adaptyは収集しません | | 健康とフィットネス | Adaptyは収集しません | | 写真と動画 | Adaptyは収集しません | | ファイルとドキュメント | Adaptyは収集しません | | カレンダー | Adaptyは収集しません | | 連絡先 | Adaptyは収集しません | | ユーザーコンテンツ | Adaptyは収集しません | | 閲覧履歴 | Adaptyは収集しません | | 検索履歴 | Adaptyは収集しません | | アプリ情報とパフォーマンス | Adaptyは収集しません | | Webブラウジング | Adaptyは収集しません | | 連絡先情報 | Adaptyは収集しません | | 財務情報 | Adaptyはユーザーの購入履歴を収集します | | 個人情報と識別子 | Adaptyは、ユーザーIDと、氏名・メールアドレス・電話番号などの識別可能な連絡先情報を、Adapty SDKに明示的に渡した場合に収集します。 | | デバイスおよびその他の識別子 | AdaptyはデバイスIDのデータを収集します。 | ## データの利用と取り扱い \{#data-usage-and-handling\} ### ユーザーID \{#user-ids\} **1. このデータは収集されますか、共有されますか、それとも両方ですか?** このデータはAdaptyによって収集されます。Adaptyとサービスプロバイダーとみなされないサードパーティとの連携を使用している場合は、「共有」も開示する必要がある場合があります。 **2. このデータは一時的に処理されますか?** 「いいえ」を選択してください。 **3. このデータの収集はアプリに必須ですか、それともユーザーが選択できますか?** このデータ収集は必須であり、オフにすることはできません。 <img src="/assets/shared/img/2c60161-image5.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> **4. このユーザーデータはなぜ収集されますか? / なぜ共有されますか?** 「アプリの機能」と「分析」のチェックボックスを選択してください。 <img src="/assets/shared/img/07a3c9e-image2.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### 財務情報 \{#financial-info\} Adaptyを使用している場合は、Google Play Consoleのデータタイプセクションで、アプリが「購入履歴」情報を収集することを開示する必要があります。 <img src="/assets/shared/img/1057870-image7.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### デバイスまたはその他のID \{#device-or-other-ids\} <img src="/assets/shared/img/d10f132-CleanShot_2023-03-01_at_17.55.312x.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> <img src="/assets/shared/img/ccb1a2a-image5.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## 次のステップ \{#next-steps\} データセーフティの選択が完了すると、Googleはアプリのプライバシーセクションのプレビューを表示します。前述のとおり「財務情報」と「デバイスまたはその他のID」を選択した場合、プライバシー情報は次の例のように表示されます。 <img src="/assets/shared/img/e8d9b73-image3.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> アプリのレビュー申請の準備ができている場合は、[リリースチェックリスト](release-checklist)ドキュメントを参照し、申請の準備について詳しくご確認ください。 --- # File: google-reduced-service-fee --- --- title: "Googleの手数料減額プログラム" description: "Googleの手数料減額プログラムの内容と、収益やAdaptyのアナリティクスへの影響について理解しましょう" --- :::link App Storeの対応プログラムについては、[App Store中小企業プログラム](app-store-small-business-program)をご覧ください。 ::: Google Playの[手数料減額プログラム](https://support.google.com/googleplay/android-developer/answer/112622?hl=en)は、年間収益の最初の100万ドルに対する手数料を30%から**15%**に引き下げます。同一カレンダーイヤーの100万ドルを超える収益には、通常の30%の手数料が適用されます。 :::note 2022年1月1日以降、Googleはこのプログラムに関係なく、すべての自動更新サブスクリプションに対して15%の手数料を課しています。手数料減額プログラムは主に、非サブスクリプションのアプリ内課金と有料アプリに恩恵をもたらします。 ::: プログラムのメンバーは、正確な収益計算とインテグレーションイベントの処理を確保するために、**Adaptyの設定を変更する必要があります**。 この記事では以下について説明します: * [アプリが手数料減額プログラムに登録されている場合のAdaptyの設定方法](#configure-adapty) * [ストア手数料を削減したい場合のプログラム登録方法](#enroll-in-the-program) ## Adaptyの設定 \{#configure-adapty\} Adaptyは、[アナリティクス](analytics)と[インテグレーションイベント](analytics-integration)に減額された手数料率を適用できます。これを有効にするには、アプリごとに手数料減額プログラムのステータスを指定してください。 :::warning **登録したらすぐに**AdaptyでReducedService Feeのステータスを設定してください。設定を後から変更しても、配信済みのWebhookイベントを書き換えることはできません([詳細](#retroactive-setting-changes))。 ::: 1. [**App Settings** → **General**](https://app.adapty.io/account)を開きます。 2. **Reduced Service Fee**セクションを見つけます。 3. **Add period**をクリックします。 4. メンバーシップの開始日を選択します。 5. 終了日を選択するか、**At the current moment**チェックマークを有効にして、このステータスを無期限に延長します。[年間収益が100万ドルを超えた場合](#exceeding-the-threshold)、終了日を変更できます。 6. **Apply**をクリックします。 メンバーシップのステータスは、**指定した日付範囲にのみ**適用されます。プログラムはカレンダーイヤーごとにリセットされます。 * **Add period**をクリックして、新しいメンバーシップ期間を追加します。 * このステータスを無期限に延長するには、**At the current moment**チェックマークを有効にします。 設定を確認するには、[Revenueチャート](revenue)を開いて**Proceeds after store commission**を選択します。表示された収益が減額された手数料率を反映しているか確認してください。 ## プログラムへの登録 \{#enroll-in-the-program\} ### 資格要件 \{#eligibility-requirements\} Googleは、<InlineTooltip tooltip="アカウントグループ">収益が合算されるデベロッパーアカウントのグループです。デベロッパーアカウントをプライマリデベロッパーアカウントとして指定し、関連するアカウントをグループにリンクする必要があります。</InlineTooltip>内のすべてのアカウントの**年間収益**に基づいて資格を判断します。 15%の手数料率は、合算した年間収益の最初の100万ドルに適用されます。その閾値を超えた収益には30%が課されます。 ### 登録前の確認事項 \{#before-you-enroll\} 以下を確認してください: - [支払いプロフィール](https://support.google.com/googleplay/android-developer/answer/10632485)が設定されていること - すべての関連デベロッパーアカウントをリストアップできること ### 登録手順 \{#enrollment\} 1. [Google Play Console](https://play.google.com/console/)にアクセスします。 2. アカウントグループを作成し、デベロッパーアカウントをプライマリデベロッパーアカウントとして設定します。 3. 関連するデベロッパーアカウントをグループにリンクします。 4. 手数料減額プログラムの利用規約に同意します。 これらの手順を完了すると、Googleが自動的に登録します。手動レビューや承認メールはありません。詳細な手順については、Googleの[登録ガイド](https://support.google.com/googleplay/android-developer/answer/10632485)をご覧ください。 ### 閾値を超えた場合 \{#exceeding-the-threshold\} 合算した年間収益が100万ドルを超えると、Googleはそのカレンダーイヤーの残りの期間、閾値を超えた部分に30%の手数料を課します。 :::important 年間収益が100万ドルを超えた場合は、**すぐにAdaptyの設定で終了日を変更してください**。変更しないと、Adaptyは引き続き減額された手数料率で計算を続けます。 ::: プログラムはカレンダーイヤーごとにリセットされます。ある年に収益が100万ドルを超えた場合でも、翌年は最初の100万ドルに対して15%の手数料率が自動的に再適用されます。再登録は不要です。詳細については、[公式プログラム規約](https://support.google.com/googleplay/android-developer/answer/112622?hl=en)をお読みください。 ## 設定の遡及的な変更 \{#retroactive-setting-changes\} --- no_index: true --- Adapty で手数料減額ステータスをさかのぼって変更した場合、新しい手数料率は Adapty のデータに異なるスケジュールで反映されます: | 反映される場所 | 手数料率を変更した後の動作 | | --- | --- | | アナリティクスダッシュボード(Revenue、Proceeds、MRR、ARR) | 日次再計算が実行される24時間以内に、新しい手数料率が適用されます。 | | S3、GCS、BigQuery エクスポート | 次回のスケジュールされたエクスポート時に、新しい手数料率が適用されます。 | | 配信済みの Webhook イベント | Adapty は配信後の Webhook イベントを変更できません。古い手数料率のままになります。 | データウェアハウスに Webhook イベントからの収益データが保存されている場合、それらのレコードには古い手数料率が残ります。データを調整するには、アナリティクスダッシュボードから該当期間のデータを取得するか、S3、GCS、または BigQuery への新しいエクスポートを生成してください。 --- # File: google-play-quota-increase --- --- title: "Google Play Developer API クォータ増加のリクエスト" description: "履歴データのインポートや大規模なサブスクライバーベースでデフォルトの上限を超えた場合に、Google Play Developer API のクォータ増加をリクエストします。" --- Adapty は [Google Play Developer API](https://developers.google.com/android-publisher) を使用して、購入の検証とサブスクリプションデータの同期を行います。この API のデフォルトクォータは 1 分あたり 3,000 クエリです。アプリがこの上限を超えると、Google からメール通知が届きます。これは主に[履歴データのインポート](importing-historical-data-to-adapty)時や、アクティブなサブスクライバーが多いアプリで発生します。 大規模なインポートを実行する前、またはクォータ超過の通知を受け取った場合は、サービスの中断を防ぐために Google にクォータ増加をリクエストしてください。 ## 始める前に \{#before-you-start\} まだ設定していない場合は、[リアルタイムデベロッパー通知 (RTDN)](enable-real-time-developer-notifications-rtdn) を有効にしてください。RTDN はポーリングではなくプッシュ通知でサブスクリプションの更新を配信するため、API の消費量を削減できます。RTDN が有効になっていない場合、Google はクォータ増加リクエストを却下することがあります。 ## 必要な情報を収集する \{#gather-required-information\} リクエストフォームを開く前に、以下の情報を準備してください。 - **デベロッパーアカウント ID**: [Google Play Console](https://play.google.com/console/) で **Settings > Developer account > Account details** に移動すると確認できます。ID はページの上部に表示されています。 - **アプリのパッケージ名**: Android アプリのパッケージ名(例: `com.example.app`)。Google Play Console のアプリの **Dashboard** ページで確認できます。 - **Google Cloud プロジェクト番号**: [Google Cloud Console](https://console.cloud.google.com/) でプロジェクトを選択すると確認できます。プロジェクト番号は **Dashboard** ページに表示されています。 ## クォータ増加をリクエストする \{#request-the-quota-increase\} 1. [Google Play Developer API クォータ増加リクエストフォーム](https://support.google.com/googleplay/android-developer/contact/apiqr)を開きます。 2. デベロッパーアカウント ID、アプリのパッケージ名、Google Cloud プロジェクト番号を入力します。 3. 増加が必要な API とクォータバケットを選択します。クォータ超過について Google からメールが届いている場合は、そのメールにどのバケットかが記載されています。 4. 正当化フィールドに、購入の検証とサブスクリプションデータの同期に API アクセスが必要なサードパーティのサブスクリプション管理サービスを使用していることを説明します。 5. リクエストするクォータ量に、必要な数値を入力します。必要な量が不明な場合は、[Google Cloud Console](https://console.cloud.google.com/) の **IAM & Admin > Quotas**(「Google Play Android Developer API」でフィルタリング)で現在の使用状況を確認し、使用状況データとインポートを予定している履歴エントリ数を [support@adapty.io](mailto:support@adapty.io) に送信してください。適切な量の判断をサポートします。 6. フォームを送信します。 Google は通常、数営業日以内にクォータ増加リクエストを処理します。 --- # File: prepare-your-app-for-store-review --- --- title: "ストア審査に向けたアプリの準備" description: "App StoreおよびGoogle Play Storeでアプリを承認してもらうためのアドバイス" --- この記事では、ストアがアプリの審査を行う際のプロセスと、より早く承認を得るためのヒントを紹介します。情報は以下の公式ガイドラインを参照しています。 * [App Store 提出ガイドライン](https://developer.apple.com/app-store/review/guidelines/) * [Google Play Store 提出ガイドライン](https://play.google/developer-content-policy/) :::important どちらのストアも同様の審査プロセスに従っています。特定のストアにのみ適用されるポリシーについては、記事内でストア名を明記しています。 ::: Adapty ユーザーは、[ペイウォールとアプリ内課金](#iap-related-requirements)に関するコンプライアンス要件に特に注意してください。これらは審査却下の最も一般的な理由の一つです。 ## はじめる前に \{#before-you-begin\} アプリが提出の準備ができているか確認してください。 Adaptyには、アプリのリリース準備を整えるための[リリースチェックリスト](release-checklist)があります。 Google Play Storeでは、初めてアプリを公開するデベロッパーが、提出前に[アプリをテスト](https://support.google.com/googleplay/android-developer/answer/14151465?hl=en)することを求めています。テストには少なくとも12人が参加し、最低14日間継続して実施する必要があります。この要件は、Google の審査スタッフに届くバグの多いアプリを減らすために2025年に導入されました。 ## 審査プロセスの概要 \{#review-process-overview\} #### ステップ1:自動スクリーニング \{#step-1-the-automated-screening\} App StoreとGoogle Play Storeはどちらも、同様の2ステップの審査プロセスを採用しています。提出後すぐに、アプリは数時間かかる場合がある自動スキャンを受けます。 どちらのストアもマルウェアのスキャンを行いますが、Google はこのプロセスに特に力を入れています。不審なサーバーへの接触やユーザーデータへの不当なアクセスなど、悪意のある活動の行動指標を検出します。アプリが潜在的に有害と判断された場合、フラグが立てられ、人間のセキュリティアナリストに渡されます。このステップで実行されるチェックの大まかなリストは、[Google Play Protect のドキュメント](https://developers.google.com/android/play-protect/cloud-based-protections#machine-learning)に記載されています。 ストアはまた、必要なメタデータの有無、有害または著しく古い依存関係がないこと、ビルドの整合性も確認します。 #### ステップ2:人間による審査 \{#step-2-the-human-review\} 自動スクリーニングを通過すると、アプリは人間の審査担当者によって検査されます。このステップは、アプリの複雑さと現在の審査キューによっては、数日かかる場合があります。機密データを処理するアプリは、審査に時間がかかります。 ## 一般的な要件 \{#general-requirements\} ### 安定性 \{#stability\} 審査中にクラッシュするアプリは却下されます。審査担当者は意図的に不安定なネットワーク状況をシミュレートすることがあるため、アプリはそのような状況にも適切に対応できる必要があります。 ### 完成度 \{#completeness\} AppleとGoogle はどちらも、ストアコンテンツに対して*完成度*(「最低限の機能」)要件を課しています。 * プレースホルダー、「近日公開」画面、動作しない機能は iOS アプリの却下につながります。 * Google は[より柔軟](https://support.google.com/googleplay/android-developer/answer/9898783?hl=en)であり、特にアプリが[早期アクセス](https://knowledge.workspace.google.com/admin/users/access/turn-early-access-apps-on-or-off-for-users)段階にある場合はそうです。 * どちらのストアも、機能がほとんどまたはまったくない**アプリを却下**します。これには、1枚の画像、PDF ファイル、またはウェブページを表示するだけのアプリも含まれます。 コンテンツの欠如も同じカテゴリーに含まれます。 * アプリが宣伝していることを実現していない場合、却下されます。 * ダッシュボードでアプリ内課金を設定していても、ビルドに含めていない場合、アプリは却下されます。 ### メタデータの正確性 \{#metadata-accuracy\} 説明、スクリーンショット、その他のメタデータに誤解を招く、不正確な、または一貫性のない情報があると、却下につながる可能性があります。 ストアのリスティングを使って将来のアプリ機能を宣伝しないでください。 アプリが一般向けに設計されていない場合、審査担当者はそのワークフローを説明する追加のドキュメントを求めます。アプリのメタデータに明確な説明を含めてください。 ### コンテンツレーティング \{#content-rating\} アプリ内のコンテンツは、宣言されたレーティングと一致している必要があります。 ### 法的側面 \{#legal-aspects\} * アプリのプライバシーポリシーは、アプリ内からアクセスできるようにする必要があります。ペイウォールビルダーの[リンクボタン](paywall-buttons#links)を使用できます。 * 法的合意事項は、発効**前**にユーザーが読んで同意するよう求めてください。 * アプリ内の広告の存在を開示してください。開示しない場合、却下につながる可能性があります。 * iOS アプリにアプリ内課金が含まれる場合、App Store Connect のダッシュボードで**有料アプリ契約**に同意する必要があります。 ### 認証 \{#authentication\} アプリのコンテンツの一部が認証後にのみ利用可能な場合、審査担当者に有効なアクセス認証情報を提供してください。コンテンツに完全にアクセスできない場合は却下されます。 アプリでユーザーがアカウントを作成できる場合、アカウントを削除することもできるようにする必要があります。メールベースのサポートやウェブサイトに誘導するだけでは、この要件を満たしません。 ### アクセスとプライバシー \{#access-and-privacy\} アプリのメタデータには、要求する各権限の理由を明確に記載する必要があります。最も機密性の高い権限(例:テキストメッセージや通話履歴へのアクセス)には、動画によるデモが必要になる場合があります。 同じ原則が機密性の高いユーザーデータにも適用されます。要求する場合は、その理由を説明してください。 ## アプリ内課金に関する要件 \{#iap-related-requirements\} ビジネスポリシーの違反は、アプリ却下の最も一般的な理由の一つです。アプリの主な収益化方法がサブスクリプションとアプリ内課金の場合、より厳しい審査を受けます。 ### ペイウォールの要件 \{#paywall-requirements\} アプリ審査担当者は、わかりやすく理解しやすいペイウォールを期待しています。 ユーザー操作が疑われる場合、アプリは却下されます。複数回の審査で不正行為の証拠が見つかった場合、アカウントが無効化され、アプリが[停止](https://support.google.com/googleplay/android-developer/community-guide/287283557/app-suspended-for-repeated-rejections?hl=en)される可能性があります。Google Play には、すべてのアプリが削除される可能性がある[ストライクシステム](https://support.google.com/googleplay/android-developer/answer/9899234?hl=en)があります。 ペイウォールのデザインでは以下の点を遵守してください。 - **透明性を保ち、事前に明示する。** 購入を促す前に、プロダクトの正確な価格、請求頻度、特典、およびキャンセル条件を表示してください。 一回限りの購入と定期的な支払いが必要なプロダクトを明確に区別してください。 プロダクトに無料トライアルが含まれる場合、その期間と条件を明確に記載してください。 ユーザーを誤解させるような意図的にわかりにくい言葉を使用しないでください。 - **一貫性を保つ。** プロダクトの価格は、App Store のリスティング、アプリ内画面、サブスクリプション管理画面、マーケティングコンテンツ全体で一致していなければなりません。どんなに小さな価格の不一致でも、却下の原因になります。 Adapty のペイウォールビルダーは、ペイウォールと App Store Connect プロダクトの価格を自動的に同期します。ペイウォールを手動でコーディングしている場合は、データ配列から[各プロダクトの価格を取得](fetch-paywalls-and-products)する必要があります。 - **すべての料金プランを均等に表示する。** 最も高い価格のオプションをあらかじめ選択した状態にしたり、安いオプションを隠したりしないでください。 - **「ダークパターン」を避ける。** 偽りの緊急感や希少感を演出しないでください。 無料機能を意図的に使いにくくしたり見つけにくくしたりして、ユーザーに購入を強制しないでください。 ### アクセスの保証 \{#access-guarantee\} アプリはユーザーが購入にアクセスする権利を保証しなければなりません。 * **即時アクセス** 購入が成功したら、目に見える遅延なしに即座にプロダクトへのアクセスを解放する必要があります。 支払い認証の中間状態でエラーが発生したり、ユーザーエクスペリエンスが損なわれたりしてはいけません。 購入が成功したら、ペイウォールをすぐに非表示にする必要があります。購入後もペイウォールを表示し続けると、ユーザーが支払ったコンテンツにアクセスできなくなります。 * **アクセスの復元** ユーザーは新しいデバイスからプロダクトへのアクセスを復元できる必要があります。復元ボタンを見やすい場所に配置してください。 [ペイウォールビルダー](adapty-paywall-builder)でペイウォールを作成した場合、復元ボタンは自動的に復元プロセスをトリガーします。[手動でペイウォールを実装](ios-implement-paywalls-manually)した場合は、[restorePurchases](restore-purchase) メソッドを呼び出すコードを追加してください。Adapty は、SDK を[オブザーバーモード](observer-vs-full-mode)で使用している場合を**除き**、ユーザーのアクセスレベルを復元します。 アプリは、プロダクトのストアページやアプリストアの他の場所で行われたアプリ内課金を認識できる必要があります。 ### 適切な支払い方法 \{#appropriate-payment-methods\} どちらのストアも、アプリ内課金による物理的な商品の販売を禁止しており、ほとんどのデジタル商品にはストア内課金を要求しています。 ストア内課金の要件は、米国や EU を含む一部の地域では適用されません。国によっては、[ストア内課金を完全に回避](https://support.google.com/googleplay/android-developer/answer/16497028)したり、アプリストア課金と代替課金の[ユーザーに選択肢を提示](https://support.google.com/googleplay/android-developer/answer/13821247)したりできる場合があります。 電子書籍リーダーやデーティングアプリなどの一部のアプリカテゴリは、これらの地域以外でも代替支払い方法を使用できる場合があります。詳細については、ストアの公式ガイドラインをご確認ください。 :::tip [Google](https://support.google.com/googleplay/android-developer/answer/13821247) と異なり、Apple は代替課金方法を許可している国の確定的なリストを提供していません。新しい地域で同様の法律が制定されるにつれて、利用可能な地域が拡大していきます。対象国に関するドキュメントを読んでから進めてください。 ::: なお、どちらのストアも決済プロバイダーの統合に関するガイドラインを適用しており、これらのサービスを使用した取引に対しても引き続き手数料を請求します。 ## 却下への対応 \{#handling-rejection\} アプリが却下された場合、審査担当者はどのガイドライン違反があったかを明示します。ガイドラインを全文読んで修正してください。 * [App Store 提出ガイドライン](https://developer.apple.com/app-store/review/guidelines/) * [Google Play Store 提出ガイドライン](https://play.google/developer-content-policy/) 却下が不当だと感じる場合は、異議を申し立てる権利があります。コンプライアンスの証拠を提供し、ストアに連絡してください。 * 審査中はアプリを更新しないでください。 * アプリを審査に提出するたびに、異なる審査担当者に当たる可能性があります。これは有利に働く場合も、不利に働く場合もあります。 * 問題を一つずつ修正しないでください。すべての修正が完了してから再審査に提出してください。 * Google Play でポリシー違反によりアプリが却下された場合、一時停止中または非アクティブなトラックも含め、すべてのトラックで該当データを更新してください。 * 再審査は通常、初回より短時間で完了します。 * 重大なバグや締め切りに対しては、審査の優先対応が利用できる場合があります。必要最小限に使用してください。 ## 審査後:継続的なモニタリング \{#after-the-review-continuous-monitoring\} どちらのアプリストアも、審査プロセスを通過した後もアプリの監視を継続します。 承認後にアプリの機能が変わった場合(例:動的に読み込まれるコードによる変更)、フラグが立てられ、リストから削除されます。ユーザーからの否定的なフィードバックが急増した場合も、追加の審査対象となります。 2024年から2025年にかけて、Google は平均品質を向上させるために [Play Store アプリの47%を削除](https://techcrunch.com/2025/04/29/google-play-sees-47-decline-in-apps-since-start-of-last-year/)しました。 アプリを放置することにもリスクがあります。[Google](https://www.cnet.com/tech/mobile/google-play-store-will-hide-apps-that-havent-been-updated-in-years/) と [Apple](https://developer.apple.com/support/app-store-improvements/#:~:text=Developers%20of%20apps%20that%20have,launch%20will%20be%20removed%20immediately.) はどちらも、更新やダウンロードのないアプリをリストから削除します。 ## 関連項目 \{#see-also\} * [サンドボックステスト](test-purchases-in-sandbox) * [リリースチェックリスト](release-checklist) --- # File: firebase-apps --- --- title: "Firebase アプリ" description: "Firebase と Adapty を連携して、モバイルアプリのユーザー分析とサブスクリプション追跡を強化しましょう。" --- このページは、Firebase 上で動作するアプリへの Adapty 連携についての説明です。 :::note はじめに これは Adapty を動作させるために必要なすべての手順ではなく、Firebase との連携に役立つヒントをまとめたものです。アプリに Adapty を導入したい場合は、まず [クイックスタートガイド](quickstart) をお読みください。 ::: ## ユーザーの識別 \{#user-identification\} Firebase 認証を使用している場合、このスニペットを参考にすることで Firebase と Adapty 間のユーザーを同期できます。これはあくまでサンプルコードであり、アプリの認証仕様に合わせて適宜調整してください。 <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS with Firebase" default> ```swift showLineNumbers @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Configure Adapty before Firebase Adapty.activate("YOUR_API_KEY") Adapty.delegate = self // Configure Firebase FirebaseApp.configure() // Add state change listener for Firebase Authentication Auth.auth().addStateDidChangeListener { (auth, user) in if let uid = user?.uid { // identify Adapty SDK with new Firebase user Adapty.identify(uid) { error in if let e = error { print("Sign in error: \(e.localizedDescription)") } else { print("User \(uid) signed in") } } } } return true } } extension AppDelegate: AdaptyDelegate { // MARK: - Adapty delegate func didReceiveUpdatedPurchaserInfo(_ purchaserInfo: PurchaserInfoModel) { // You can optionally post to the notification center whenever // purchaser info changes. // You can subscribe to this notification throughout your app // to refresh tableViews or change the UI based on the user's // subscription status NotificationCenter.default.post(name: NSNotification.Name(rawValue: "com.Adapty.PurchaserInfoUpdatedNotification"), object: purchaserInfo) } } ``` </TabItem> <TabItem value="kotlin" label="Android with Firebase" default> ```kotlin showLineNumbers class App : Application() { override fun onCreate() { super.onCreate() // Configure Adapty Adapty.activate(this, "YOUR_API_KEY") Adapty.setOnPurchaserInfoUpdatedListener(object : OnPurchaserInfoUpdatedListener { override fun onPurchaserInfoReceived(purchaserInfo: PurchaserInfoModel) { // handle any changes to subscription state } }) // Add state change listener for Firebase Authentication FirebaseAuth.getInstance().addAuthStateListener { auth -> val currentUserId = auth.currentUser?.uid if (currentUserId != null) { // identify Adapty SDK with new Firebase user Adapty.identify(currentUserId) { error -> if (error == null) { //success } } } else { Adapty.logout { } } } } } ``` </TabItem> </Tabs> --- # File: refund-saver --- --- title: "Refund Saver" description: "Adapty Refund Saverを使用して払い戻しを最小化し、収益を最大化しましょう。" --- ユーザーが払い戻しをリクエストすると、Appleは調査を行います。**払い戻しが正当かどうか**を判断するために、Appleはそのユーザーのアクティビティに関する情報を開発者に求めます。この証拠がなければ、頻繁に利用されているサブスクリプションでも払い戻しが承認される可能性が高くなります。 **Refund Saver**はAppleの消費情報リクエストに[自動的に](https://developer.apple.com/documentation/appstoreserverapi/send-consumption-information-v1)対応し、収益を守りながら、不正なリクエストが**拒否される可能性を高めます**。自動更新サブスクリプション、買い切りサブスクリプション、消耗型アイテム、非消耗型アイテム(永続アクセス商品を含む)など、Appleのすべてのアプリ内課金タイプに対応しています。 ## Refund Saverの仕組み \{#how-refund-saver-works\} 1. ユーザーが払い戻しリクエストを開始すると、App Storeはトランザクションと利用状況の詳細を求める通知を送信します。 この通知を**無視**したり**遅延**したりすると、Appleは払い戻しを**承認**する可能性が高くなります。 2. Adapty Refund Saverはこれらの通知を自動的に処理し、Appleに必要なデータを提供します。 この自動化により、不要な払い戻しの発生を抑えながら、時間の節約と収益の保護を実現します。 3. Adaptyは各結果(払い戻し済みまたは拒否)を記録します。そのデータがダッシュボードのRefund Saver分析を支えます。 :::info Refund Saverを使用することで、払い戻しリクエストによる収益損失の最大40%を守ることができます。 ::: ## Refund Saverを使用するための要件 \{#requirements-to-use-refund-saver\} この機能を使用するには、以下の前提条件を満たしていることを確認してください。 1. **App Store Connectのプライバシーポリシーを更新する:** アプリのプライバシーポリシーに、消費データの収集と使用についての開示が必要です。これにより、ユーザーがアプリをダウンロードする前にプライバシー慣行を理解できます。詳しくは[Appleのアプリプライバシーの詳細](https://developer.apple.com/app-store/app-privacy-details/)を参照してください。 2. **アプリ内でデータ共有に関するユーザーの同意を取得する:** Appleは、ユーザーの個人データを共有する前に有効な同意を取得することを義務付けています。ユーザーデータをAppleと共有するのは開発者であるため、この同意の取得は開発者の責任です。詳細はAppleの[ガイドライン](https://developer.apple.com/documentation/appstoreserverapi/send-consumption-information)を参照してください。 3. **Server Notifications V2を有効にする:** V1通知はサポートされていないため、Apple Developerアカウントでサーバー通知V2が有効になっており、Adaptyで正しく設定されていることを確認してください。まだ有効にしていない場合は、[App Storeサーバー通知の有効化](enable-app-store-server-notifications)ガイドの手順に従ってください。 ## Refund Saverを有効にする \{#turn-on-refund-saver\} 1. Adapty ダッシュボードで[Refund Saver](https://app.adapty.io/refund-saver)セクションを開きます。 2. **Turn on Refund Saver**をクリックして機能を有効にします。 ## デフォルトの払い戻し動作を設定する \{#set-a-default-refund-behavior\} Appleは、各払い戻しリクエストへの対応時に開発者が希望する結果を指定することを許可しています。この設定の目的は、払い戻しの拒否と承認の適切なバランスを見つけて、正当な払い戻しのみが行われるようにすることです。なお、この設定はあくまで結果に影響を与えるためのものであり、最終的な判断はAppleが行います。 Adaptyはこの設定に対応していますが、すべての払い戻しリクエストに同じ値を使用します。 1. 設定を変更するには、**Edit refund preference**をクリックします。 2. **Edit refund preference**ウィンドウで、**Default refund request preference**オプションを選択します。 | オプション | 説明 | | -------------------------------------------- | ------------------------------------------------------------ | | Always decline | (デフォルト)デフォルトのオプションで、通常は払い戻しを最小化する最良の結果をもたらします。 | | Decline first refund request, grant all next | Refund Saverが処理するすべてのトランザクションに対して、最初はAppleに払い戻しを拒否するよう求めます。ただし、同じトランザクションが再度現れた場合は、常に払い戻しを承認するよう推奨します。このアプローチにより、不当な払い戻し拒否によるユーザーの不満を最小化できます。ユーザーは単に再度リクエストするだけで払い戻しを受けられる可能性があります。 | | Always refund | すべての払い戻しリクエストをAppleが承認するよう推奨します。 | | No preference | Appleに対して何も推奨しません。この場合、Appleはあなたの設定からの影響を受けず、内部ポリシーとユーザー履歴のみに基づいて払い戻し結果を決定します。最も中立的なアプローチです。 | ## ダッシュボードで特定ユーザーの払い戻し動作を設定する \{#set-refund-behavior-for-a-specific-user-in-the-dashboard\} アプリ全体のデフォルトのRefund Saver動作を設定していても、特定のユーザーに個別の設定を行いたい場合があります。Adapty ダッシュボードでは、ユーザーのプロファイルからこれを行うことができます。左下にある**Refund Saver Preferences**セクションを使用してください。 :::note ユーザーごとの設定はアプリレベルのデフォルト(「Decline first refund request, grant all next」の動作を含む)より優先されます。 ::: ## SDKで特定ユーザーの払い戻し動作を設定する \{#set-refund-behavior-for-a-specific-user-in-the-sdk\} ユーザーのアクションに応じて、インストールごとに個別に払い戻し設定をアプリコードで行うことができます。以下のスニペットを使用して設定を行ってください。 <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS (3.4.1+)" default> ```swift showLineNumbers code do { try await Adapty.updateRefundPreference(<PREFERENCE_VALUE>) // possible values: .noPreference, .grant, .decline } catch { // handle the error } ``` </TabItem> <TabItem value="flutter" label="Flutter (3.4.0+)" default> ```javascript showLineNumbers code try { // possible values: AdaptyRefundPreference.noPreference, AdaptyRefundPreference.grant, AdaptyRefundPreference.decline await Adapty().updateRefundPreference(<PREFERENCE_VALUE>); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` </TabItem> <TabItem value="rn" label="React Native (3.4.0+)" default> ```typescript showLineNumbers try { await adapty.updateRefundPreference(<PREFERENCE_VALUE>); // possible values: RefundPreference.NoPreference, RefundPreference.Grant, RefundPreference.Decline } catch (error) { // handle the `AdaptyError` } ``` </TabItem> <TabItem value="unity" label="Unity (3.3.0+)" default> ```csharp showLineNumbers Adapty.UpdateAppStoreRefundPreference(<PREFERENCE_VALUE>, (error) => { if (error != null) { // handle the error return; } }); ``` </TabItem> </Tabs> :::note Server-side APIを使用して[個別の払い戻し設定を行う](api-adapty/operations/setRefundSaverSettings)こともできます。 - ユーザーがボタンをクリックして設定を行うなど、設定がクライアントの操作に直接紐づいている場合はSDKを使用してください。 - サーバーサイドの処理が必要な場合や、アプリケーションのアーキテクチャに適している場合はAPIを使用してください。 ::: ## ユーザーの同意を取得する \{#obtain-user-consent\} データ共有に関するユーザーの同意をどのように収集するかはお客様次第ですが、Appleは個人データを共有する前に有効なユーザーの同意を取得することを義務付けています。Appleは**オプトインアプローチ**を推奨しており、データの使用方法を説明し、明示的なユーザーアクションを求めるアプリ内プロンプトを使用します。ユーザーがプロンプトを無視または拒否した場合、同意したとは見なされません。詳細はAppleの[ガイドライン](https://developer.apple.com/documentation/appstoreserverapi/send-consumption-information)を参照してください。 アプリで明示的な同意が実用的でない場合は、**オプトアウトアプローチ**を検討することもできます。これは、利用規約にデータ共有条項を含め、利用規約に同意することでデータ共有に同意したものとみなす方法です。ユーザーが同意を取り消す方法を明確に説明することも忘れずに。 以下は、共有する可能性のあるデータの種類を含むオプトアウトアプローチの条項例です。これはあくまで参考のためのサンプルです。最終版がすべての適用法およびAppleの要件に準拠していることを確認する責任はお客様にあります。 *「アプリ内購入の払い戻しリクエストを受け取った場合、ユーザーのアプリ内購入アクティビティに関する情報をAppleに提供することがあります。これには、アプリのインストールからの経過時間、総アプリ使用時間、匿名のアカウント識別子、アプリ内購入が完全に消費されたかどうか、トライアル期間が含まれていたかどうか、総支出額、総払い戻し額などの詳細が含まれる場合があります。」* 選択したアプローチに応じて、**Edit refund preferences**メニューの**Default consent policy**オプションを設定してください。 <p> </p> | オプション | 説明 | | ------- | ------------------------------------------------------------ | | Opt-out | (デフォルト)Adaptyがユーザーの同意状態を把握していない場合、同意が**与えられた**と見なし、Refund Saverは払い戻し関連データをAppleと**共有します**。 | | Opt-in | Adaptyがユーザーの同意状態を把握していない場合、同意が**与えられていない**と見なし、Refund Saverはデータを**共有しません**。これはAppleが推奨するアプローチです。 | ## SDKでユーザーの同意を更新する \{#update-user-consent-in-the-sdk\} 特定のユーザーが同意を与えたかどうかをAdaptyに伝えるには、`updateCollectingRefundDataConsent`メソッドを使用します。この値はプロファイルごとにサーバーサイドで保持されるため、同意が変更された場合のみ呼び出す必要があります。 <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS (3.4.1+)" default> ```swift showLineNumbers do { try await Adapty.updateCollectingRefundDataConsent(<CONSENT_VALUE>) // true = consent is explicitly provided, false = consent is explicitly revoked } catch { // handle the error } ``` </TabItem> <TabItem value="flutter" label="Flutter (3.4.0+)" default> ```dart showLineNumbers try { // true = user gave consent, false = user revoked consent await Adapty().updateCollectingRefundDataConsent(<CONSENT_VALUE>); } on AdaptyError catch (adaptyError) { // handle the error } catch (e) { // handle the error } ``` </TabItem> <TabItem value="rn" label="React Native (3.4.0+)" default> ```typescript showLineNumbers try { await adapty.updateCollectingRefundDataConsent(<CONSENT_VALUE>); // true = consent is explicitly provided, false = consent is explicitly revoked } catch (error) { // handle the `AdaptyError` } ``` </TabItem> <TabItem value="unity" label="Unity (3.3.0+)" default> ```csharp showLineNumbers Adapty.UpdateAppStoreCollectingRefundDataConsent(<CONSENT_VALUE>, (error) => { if (error != null) { // handle the error return; } }); ``` </TabItem> </Tabs> :::note Server-side APIを使用して[個別のデータ共有設定を行う](api-adapty/operations/setRefundSaverSettings)こともできます。 - ユーザーがボタンをクリックして設定を行うなど、設定がクライアントの操作に直接紐づいている場合はSDKを使用してください。 - サーバーサイドの処理が必要な場合や、アプリケーションのアーキテクチャに適している場合はAPIを使用してください。 ::: ## ユーザーの同意を確認する \{#check-user-consent\} ユーザーの現在の同意状態はいつでも確認できます。Adapty ダッシュボードでユーザーのプロファイルを開き、左下の**Refund Saver Preferences**セクションにある**Allow data sharing**設定を確認してください。 :::note Server-side APIを使用して[個別の払い戻しと共有の設定を取得する](api-adapty/operations/getRefundSaverSettings)こともできます。 ::: ## 制限事項 \{#limitations\} - **AppleのApp Storeのみ対応:** Refund SaverはAppleのApp Storeへの払い戻しリクエストにのみ対応しています。Google Playは払い戻しに対する消費データ分析を提供していません。Google Playでの払い戻し決定はGoogleのポリシーとユーザーが提供する情報のみに基づいています。 - **Server Notifications V2が必要:** Refund SaverはApp Store Server Notifications V1とは互換性がありません。現在AdaptyでV1を使用している場合はV2に切り替える必要があります。詳細は[App Storeサーバー通知をAdaptyに送信する](enable-app-store-server-notifications)ガイドを参照してください。V2に切り替えることで、より正確で包括的なデータが提供され、Adaptyの分析も向上します。 --- # File: meta-create-campaign --- --- title: "Meta Ads でアプリを宣伝する" --- このステップバイステップガイドでは、Meta でアプリの広告を作成・設定し、パフォーマンスを簡単に最適化・追跡する方法を説明します。 ## Meta における広告の構造 \{#how-ads-in-meta-are-structured\} Meta Ads で広告を出すには、3 つの階層レベルを設定する必要があります。 - **キャンペーン**: キャンペーンでは広告の目的を定義します。 - **広告セット**: 広告セットではターゲットオーディエンスとプレースメントを指定し、広告を誰にどこで表示するかを決定します。1 つのキャンペーンに複数の広告セットを含めることができます。 - **広告**: 広告はユーザーが実際に目にして操作するクリエイティブです。1 つの広告セットに複数の広告を含めることができますが、最適なパフォーマンスのために広告セットあたり 5 件以内に抑えることが推奨されます。 ## ステップ 1. Meta Ads Manager アカウントを作成する \{#step-1-create-meta-ads-manager-account\} Meta Ads を始めるには Facebook ビジネスページが必要です。個人ページでは広告を掲載できません。 ビジネスページを Meta Ads のビジネスポートフォリオにリンクする手順は次のとおりです。 1. [business.facebook.com](https://business.facebook.com/) にアクセスします。ビジネスポートフォリオにビジネスページがまだない場合は追加が必要です。**Go to settings** をクリックします。 2. 左サイドバーから **Account > Pages** に移動します。**Add** をクリックし、**Add an existing Facebook page** または **Create a new Facebook page** を選択します。ビジネスページをまだお持ちでない場合は、[ビジネスページ作成ガイド](https://www.facebook.com/business/help/473994396650734)をご参照ください。 3. 必要に応じて、設定の **Account > Instagram accounts** ページで Instagram アカウントを連携します。 ビジネスページを接続したら、次のステップに進む準備が整いました。 ## ステップ 2. Meta ピクセルを追加する \{#step-2-add-meta-pixel\} キャンペーンデータを収益に紐付け、より良い結果を得るために Meta ピクセルが必要です。 データを接続してピクセルを作成する前に、以下が必要です。 - ビジネスページ – [**Settings > Accounts > Pages**](https://business.facebook.com/latest/settings/pages) でビジネスポートフォリオに追加する - ビジネスマネージャーアカウント – ビジネスポートフォリオの完全な管理権限が必要 - ビジネスメールアドレス – [**Settings > Business info**](https://business.facebook.com/latest/settings/business_info) で設定する - 広告アカウント – [**Settings > Accounts > Ad accounts**](https://business.facebook.com/latest/settings/ad_accounts) でビジネスポートフォリオに追加する 準備ができたら、ピクセルを作成します。 1. [**Events Manager**](https://www.facebook.com/events_manager2) にアクセスします。**Connect data** をクリックします。 2. データソースの種類として **Web** を選択します。 3. データセットに名前を付け、**Create** をクリックします。 4. [Adapty User Acquisition](adapty-user-acquisition) では、ピクセルの完全なインストールを完了する必要はありません。インテグレーションについて尋ねられた場合、設定ウィンドウの **x** をクリックするだけで、ページを更新するとピクセルがリストに表示されます。 5. データセットがリストに表示されたら、キャンペーンの作成に進めます。 ## ステップ 3. キャンペーンを作成する \{#step-3-create-campaign\} Meta Ads Manager でキャンペーンを作成するには: 1. [Meta Ads Manager](https://adsmanager.facebook.com/adsmanager/manage) にアクセスします。**Campaign** タブで **Create** をクリックします。 2. キャンペーンの目的として **Sales** を選択し、**Continue** をクリックします。 3. **Campaign name** セクションでキャンペーン名を入力します。 4. **Budget** セクションの **Budget strategy** で予算の管理方法を選択します。 - **Campaign budget**: どのオプションが最適かわからない場合は最も簡単な選択肢です。これを選択すると、Meta Ads がトップパフォーマーを自動で検出し、パフォーマンスの高い広告セットにより多くの予算を割り当てます。 次に、**Daily**(日次)または **Lifetime**(通算)予算のどちらが必要かを選択し、自国通貨で上限を入力します。**Daily** 予算は学習中に柔軟性が高く、少額から始めてその都度調整できます。または **Schedule budget increase** を選択して、金額またはパーセンテージで自動的に予算を増加するルールを設定することもできます。 - **Ad set budget**: どのオーディエンスにキャンペーン予算を多く・少なく配分するかを手動で定義したい場合はこちらを選択します。まだ確信が持てない場合は、**Share some of your budget with other ad sets** を選択すると、広告パフォーマンスに有益な場合に Meta が広告セット予算を最大 20% まで自動調整できます。 5. **Campaign bid strategy** で目標に最適なオプションを選択します。 - **Highest volume(デフォルト)**: 最も簡単な開始オプションです。これを選択すると、予算に対して最良の結果を得られるよう Meta がクリックコストを最適化します。 - **Cost per result goal**: ベンチマークがわかっている場合、特定の結果あたりのコストを目標に設定します。 - **Bid cap**: 入札する最高コストを設定します。 6. Adapty では包括的な [A/B テスト](ab-tests)を実施できます。ただし、必要に応じて Meta Ads でも A/B テストを有効にすることができます。Meta Ads Manager の A/B テストについては[こちら](https://www.facebook.com/business/help/1159714227408868)をご覧ください。 7. 次に、キャンペーンに最初の広告セットを追加します。**Next** をクリックして続行します。 ## ステップ 4. 広告セットを作成する \{#step-4-create-ad-set\} 広告セットを作成するには: 1. **Ad set name** フィールドで広告セットに名前を付けます。 2. **Conversion location** ドロップダウンで **Website** を選択します。 3. **Performance goal** フィールドで、ランディングページがある場合は **Maximize number of landing page views**、ユーザーをストアに直接誘導するスマートリンクを使用している場合は **Maximize number of link clicks** を選択します。 4. **Dataset** フィールドで、[ステップ 2](#step-2-add-meta-pixel) で作成したデータセットを選択します。 5. **Conversion event** を選択します。今回の場合、おそらく **Purchase** または **Start trial** になります。データセットにまだイベントがないという警告が表示されても問題ありません。これはデータセットが新しいことを意味するだけです。 6. キャンペーン設定時に **Ad set budget** を選択した場合、**Daily**(日次)または **Lifetime**(通算)予算のどちらが必要かを選択し、自国通貨で上限を入力します。**Daily** 予算は学習中に柔軟性が高く、少額から始めてその都度調整できます。 広告セットの開始日と(該当する場合)終了日を設定します。たとえば、アプリのプロモーションオファーを宣伝する場合は、広告セットの期間をオファーの期間に合わせることが重要です。 7. **Audience controls** セクションでオーディエンス設定を行います。 - **Location**: 必要に応じて広範または詳細に設定できます。広告の地域特性に合わせて、広告セットの **Locations** を絞り込むことができます。 - **Minimum age**: 広告を表示するユーザーの最低年齢を選択します。一部の広告では法的に要求される場合があります。グローバルでは 18 歳未満、タイでは 20 歳未満は選択できません。 - **Language**: 選択した国で最も一般的な言語でない場合のみ **Language** を設定します。たとえば、米国では **English** を選択する必要はありませんが、そこに住むスペイン語話者をターゲットにする場合は **Spanish** を選択します。 8. デフォルトでは、Meta が自動的に広告に関連性の高い小さなグループを見つけます。ただし、オーディエンスの提案を追加することで、反応しやすいと思われるユーザーに向けて Meta を誘導できます。**Advantage+ audience** セクションで以下を調整できます。 - **Age**: 特定の年齢層の特性に合わせてターゲットとする年齢範囲を設定します。 - **Gender**: すべてのユーザーに広告を表示するか、性別でターゲットを絞ります。 - **Detailed targeting**: この設定では広告やアプリのオーディエンスを最も細かく管理できます。**Demographics**(デモグラフィック)、**Interests**(興味・関心)、**Behaviors**(行動)に基づいてグループを形成できます。アプリの内容に応じて、特定の職業、特定のミュージシャンのファン、新生児の親、オンラインショッピングをよく利用するユーザーなどに絞ることができます。 :::note **Detailed targeting** の設定は **Or** 演算子で適用されます。**And** 演算子で条件を適用したい場合は、**Define further** をクリックして新しい条件を選択します。 ::: 9. **Placements** セクションでは広告の表示場所を選択できます。デフォルトでは **Advantage+** 設定が選択されており、Meta がパフォーマンスを最大化できる場所に予算を自動配分します。広告の配置に迷う場合はこのオプションの使用をお勧めします。特定の配置を手動で選択したい場合は **Manual placements** を選択してカスタマイズします。詳細は[こちら](https://www.facebook.com/business/help/965529646866485)をご覧ください。 10. **推奨**: デバイスでターゲットを絞ることで支出を最適化できます。**Placements** セクションで **Show more settings** をクリックします。**Devices and operating system** サブセクションで、オーディエンスに含めるデバイス、OS、OS バージョンを選択します。これにより、関連するユーザーにのみ広告が表示されます。たとえば、デスクトップユーザーには広告が表示されず、アプリがサポートしていない古い OS バージョンのユーザーは除外されます。 11. 準備ができたら、**Next** をクリックして続行します。 ## ステップ 5. 広告を作成する \{#step-5-create-ads\} Meta Ads Manager で広告を作成するには: 1. **Ad name** フィールドで広告に名前を付けます。 2. **Identity** セクションで、広告の投稿に使用する Facebook ページを選択します。アプリ専用の Instagram アカウントがあり、[ステップ 1](#step-1-create-meta-ads-manager-account) で Meta Business Suite に連携している場合は、**Instagram account** ドロップダウンで選択します。それ以外の場合は **Use Facebook page** を選択し、Facebook ページを使って Instagram 広告を投稿します。 3. **Ad setup** で広告の投稿方法を選択します。アプリの広告には **Create ad** の選択をお勧めします。投稿が Facebook ページではなくアプリにユーザーをリダイレクトするためです。**Format** フィールドで、保有するクリエイティブの数と表示方法に応じてオプションを選択します。 4. **Destination** セクションで **Main destination** として **Website** が選択されていることを確認します。**Website URL** フィールドに `https://api-ua.adapty.io/api/v1/attribution/click` を貼り付けます。[Adapty User Acquisition](adapty-user-acquisition) で[ウェブキャンペーンを作成](ua-facebook)し、**Tracking** セクションの **URL parameters** フィールドに `https://api-ua.adapty.io/api/v1/attribution/click` の後に **Click link** の内容を貼り付けます。 5. **Ad creative** セクションで **Set up creative** をクリックし、**Image ad** または **Video ad** を選択します。新しいウィンドウが開き、メディアファイルのアップロード、クロップ、テキスト追加が求められます。 6. 広告テキストを自動翻訳したい場合は、**Languages** セクションで **Add languages** をクリックします。次に、プライマリ言語を追加すると、クリエイティブからテキストが自動的に取得されます。その後、自動翻訳する言語を追加します。 7. 準備ができたら **Publish** をクリックして広告を公開します。 ## 次のステップ \{#whats-next\} 広告を有効にするには、まだ支払い方法を追加していない場合は追加する必要があります。 その後、[Adapty User Acquisition ダッシュボードでキャンペーンがアプリ収益に与える影響を確認](adapty-user-acquisition)できます。 Adapty User Acquisition をまだご利用でないですか?[こちらからお問い合わせ](https://calendly.com/tnurutdinov-adapty/30min)いただくと、広告キャンペーンの追跡と最適化にどのように役立つかをご説明します。 --- # File: tiktok-create-campaign --- --- title: "TikTok for Businessでアプリを宣伝する" --- このステップバイステップガイドでは、TikTok for Businessでアプリの広告を作成・設定する方法を説明します。広告のパフォーマンスを簡単に最適化・追跡できるようになります。 ## ステップ1. ビジネス情報を追加する \{#step-1-add-business-info\} TikTok for Businessを初めて利用する場合は、まずビジネス情報を追加する必要があります: 1. [https://ads.tiktok.com](https://ads.tiktok.com/business/) にアクセスし、**Get started** をクリックします。 2. メールアドレスまたはTikTokアカウントでサインアップします。 3. ビジネス情報を入力し、画面の指示に従います。 ビジネスアカウントが承認されると、最初のキャンペーン作成画面にリダイレクトされます。 ## ステップ2. ピクセルを作成する \{#step-2-create-a-pixel\} キャンペーンデータを収益に結びつけてより良い結果を得るために、TikTokピクセルが必要です: 1. [**Events Manager**](https://ads.tiktok.com/i18n/events_manager/home) にアクセスし、**Connect data source** をクリックします。 2. データソースの種類として **Web** を選択します。 3. **Add your website** ウィンドウで **Skip** をクリックします。 4. **Manual setup** を選択し、**Next** をクリックします。 5. **TikTok pixel + Events API** を選択し、**Next** をクリックします。 6. ピクセルに名前を付け、**Create** をクリックします。 7. [Adapty User Acquisition](adapty-user-acquisition) では、ピクセルの完全なインストールを完了する必要はありません。セットアップウィンドウを閉じるだけで、ピクセルがリストに表示されます。 8. このピクセルをキャンペーンで使用できるようにするには、[Adapty User Acquisition](adapty-user-acquisition) からテストイベントを送信する必要があります: 1. [新しいTikTokキャンペーンを作成する](ua-tiktok)。 2. プラットフォーム固有のセクション(例:iOS)を展開します。 3. ドロップダウンからピクセルを選択します。 4. **Send test event** をクリックします。 5. ドロップダウンで、広告の最適化に使用するイベントを選択します。 6. TikTok for Businessでピクセルを開き、**Test events** タブに切り替えます。`test_event_code` をコピーします。 7. Adaptyの **Test event code** フィールドに貼り付け、**Send** をクリックします。 9. テストイベントは数分後にTikTokに表示されます。ピクセルの詳細画面で確認できたら、TikTok Ads Managerでのキャンペーン設定を進めることができます。 ## ステップ3. キャンペーンの目標を選択する \{#step-3-select-the-campaign-objective\} :::important このチュートリアルでは、TikTok Ads ManagerのQuick setupビューを使用しています。いくつかの推奨設定はFull viewにのみ表示されます。該当するステップでその旨を記載しています。 ::: Ads Managerの[広告作成ページ](https://ads.tiktok.com/i18n/nb_creation/create/objectives)にアクセスします。 最初の画面で広告の目標を選択し、**Continue** をクリックします。 **Sales > Website conversion** を選択します。 ## ステップ4. キャンペーン情報を入力する \{#step-4-fill-in-the-campaign-info\} 次に、キャンペーン情報を入力します: 1. **Campaign name** フィールドにキャンペーン名を入力します。 2. **Optimization goal** フィールドで **Conversion** を選択します。 3. ドロップダウンからアクティブなピクセルを選択し、**Optimization event** を選びます。選択できるのはアクティブなイベントのみです。必要なイベントが表示されない場合は、[ステップ2](#step-2-create-a-pixel)の手順に従ってテストイベントを送信してください。 4. 広告はTikTokフィードと検索に表示されます。追加設定を行うには、**Advanced settings** をクリックします。**Placements** でプレースメント設定を構成します: - **User comment**:コメントセクションにも広告を表示したい場合は選択します。TikTokは、インプレッション数を増やすためにユーザーコメントをオンにすることを推奨しています。 - **Allow video download**:視聴者が広告をダウンロードできるようにします。 - **Allow video sharing**:視聴者が広告をシェアできるようにします。 5. **Continue** をクリックします。 ## ステップ5. 広告コンテンツを追加する \{#step-5-add-ad-content\} 次に、クリエイティブと遷移先URLを設定します: 1. **TikTok account** フィールドで、投稿に使用するアカウントを選択します。 2. [Adapty User Acquisition](adapty-user-acquisition) で[ウェブキャンペーンを作成](ua-tiktok)し、**Click link** を **Destination URL** フィールドに貼り付けます。 3. **Creatives** セクションで **+ Videos and images** をクリックします。 4. TikTok投稿をクリエイティブとして使用する場合は、**TikTok post** タブで選択します。それ以外の場合は **Creative library** タブに切り替えて **Upload** をクリックします。アップロードしたファイルは後でこのタブからアクセスでき、他のキャンペーンで再利用できます。 5. クリエイティブをTikTokフォーマットに合わせてトリミングし、シングル広告またはカルーセルのいずれかを選択します。 6. アップロードしたクリエイティブを展開し、**No music selected** の横にある **+** をクリックします。mp3ファイルをアップロードできます。音楽の追加は必須です。 7. **Add text** フィールドに、説明文として使用するテキストを入力します。 8. この広告をTikTokアカウントの投稿として公開する場合は、**Place the ads on this TikTok account as a post** を選択します。 9. **Call to action** フィールドで、広告に関連するコール・トゥ・アクションを選択または削除します。これらはTikTokによって自動的に広告に追加されます。 10. **Continue** をクリックします。 ## ステップ6. ターゲティングと予算を設定する \{#step-6-configure-targeting-and-budget\} 最後に、広告の表示対象と費用の計画を設定します: 1. **Targeting** セクションで **Automatic** または **Custom** を選択します。オーディエンスをまだ把握できていない場合は **Automatic** が最も簡単です。ただし、**Custom** を選択すると、広告に反応しやすいユーザーグループを選んで費用を最適化できます。 2. **Custom** を選択した場合は、以下を設定します: - **Location**:デフォルトの場所は広告アカウントの場所です。複数のターゲット国や地域を選択すると、広告審査の結果は場所ごとに個別に返されます。また、実際の広告配信は、各プレースメントの対応エリアによって異なる場合があります。 - **Languages**:デフォルトでは全言語が選択されています。選択した場所で最もよく使われる言語をターゲット言語として選択してください。 - **Gender**:デフォルトでは全性別が選択されています。 :::tip Fullモードに切り替えると、**Targeting** の下に **Device** セクションが表示されます。ここでデバイスの種類、OS、OSバージョンによってオーディエンスを絞り込めます。アプリに最低バージョン要件がある場合に便利です。 ::: 3. **Budget** セクションで、表示された候補から選択するか、**Custom** を選択します。 4. **Custom** を選択した場合は、**Daily** または **Lifetime** 予算を選択し、使用する通貨で上限額を入力します。**Daily** 予算はまだ学習中の段階でより柔軟に対応できるため、少額から始めてその都度調整していくのがおすすめです。 5. **Schedule** セクションで、**Continue for at least 7 days** または **Custom** を選択します。広告に時間的な制約がある場合は **Custom** スケジュールを設定することを推奨します。停止のタイミングを逃さないようにするためです。 6. **Custom** を選択した場合は、広告の開始日時、または開始・終了日時を設定します。アカウントのタイムゾーンが使用されます。 7. **Publish** をクリックします。 完了すると、1つの広告グループを含む新しいキャンペーンが作成されます。広告グループには、カルーセルを設定した場合は1つの広告が、クリエイティブを個別の広告として追加した場合は複数の広告が含まれます。 ## ステップ7. 支払い情報を入力する \{#step-7-enter-payment-details\} 広告を掲載し始めるには、ターゲティングと広告予算を設定した後に支払い情報を入力します。これで準備完了です! ## 次のステップ \{#whats-next\} [Adapty User Acquisitionダッシュボードでキャンペーンがアプリの収益に与える影響を確認](adapty-user-acquisition)できます。 Adapty User Acquisitionをまだ使っていませんか?[こちらからお問い合わせ](https://calendly.com/tnurutdinov-adapty/30min)いただければ、広告キャンペーンの追跡と最適化にどのように役立つかご説明します。 --- # File: getting-started-with-server-side-api --- --- title: "サーバーサイド API" description: "サブスクリプション管理のための Adapty サーバーサイド API を使ってみましょう。" --- :::tip AI コーディングエージェントを使っていますか?[バックエンドからサブスクリプションアクセスを確認・付与する](server-side-api-with-ai)に、一つのページにまとめたエンドツーエンドのレシピがあります。 ::: この API を使うと、以下のことができます: 1. ユーザーのサブスクリプション状態を確認する。 2. アクセスレベルでユーザーのサブスクリプションを有効化する。 3. ユーザー属性を取得する。 4. ユーザー属性を設定する。 5. ペイウォール設定を取得・更新する。 <img src="/assets/shared/img/server.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> <p> </p> :::note サブスクリプションイベントを追跡するには、Adapty の [Webhook](webhook) 連携を利用するか、既存のサービスと直接連携してください。 ::: ## ウェブとモバイル間でサブスクライバーを同期する場合 \{#case-1-sync-subscribers-between-web-and-mobile\} StripeやChargeBeeなどのWeb決済プロバイダーを使用している場合、サブスクリプションユーザーを簡単に同期できます。手順は以下のとおりです: 1. <InlineTooltip tooltip="各ユーザーに一意のIDを割り当てる">[iOS](identifying-users)、[Android](android-identifying-users)、[React Native](react-native-identifying-users)、[Flutter](flutter-identifying-users)、[Unity](unity-identifying-users)</InlineTooltip> 2. APIを使用して[サブスクリプションのステータスを確認する](api-adapty/operations/getProfile)。 3. ユーザーがフリーミアムプランの場合、Webサイトにペイウォールを表示する。 4. 決済が完了したら、APIを通じてAdaptyの[サブスクリプションステータスを更新する](api-adapty/operations/setTransaction)。 5. サブスクリプションユーザーはモバイルアプリと自動的に同期されます。 ## Case 2: サブスクリプションを付与する \{#case-2-grant-a-subscription\} :::note セキュリティ上の理由から、SDK を使ってサブスクリプションを付与することはできません。 ::: Google Play や App Store 以外のプラットフォーム(独自のオンラインストア、Amazon Appstore、Microsoft Store など)で販売している場合は、アクセス権の付与とアナリティクスでのトランザクション追跡を行うために、それらのトランザクションを Adapty と同期する必要があります。 1. <InlineTooltip tooltip="各ユーザーに固有のIDを割り当てる">[iOS](identifying-users)、[Android](android-identifying-users)、[React Native](react-native-identifying-users)、[Flutter](flutter-identifying-users)、[Unity](unity-identifying-users)</InlineTooltip> 2. [Adapty ダッシュボードでプロダクトのカスタムストアを設定する](custom-store)。 3. [Set transaction](api-adapty/operations/setTransaction) API リクエストを使用して、トランザクションを Adapty に同期する。 ## ケース3: アクセスレベルを付与する \{#case-3-grant-an-access-level\} 7日間の無料トライアルプロモーションを実施していて、プラットフォーム間で一貫したエクスペリエンスを提供したいとします。モバイルアプリと同期するには: 1. <InlineTooltip tooltip="各ユーザーに一意のIDを割り当てる">[iOS](identifying-users)、[Android](android-identifying-users)、[React Native](react-native-identifying-users)、[Flutter](flutter-identifying-users)、[Unity](unity-identifying-users)</InlineTooltip>。 2. APIを使用して、7日間の[プレミアムアクセスを付与](api-adapty/operations/grantAccessLevel)します。 7日間が経過しても購読しないユーザーは、無料プランにダウングレードされます。 ## ケース4: ユーザーのプロパティとカスタム属性を同期する \{#case-4-sync-users-properties-and-custom-attributes\} 言語学習アプリで学習した単語数など、ユーザー独自のカスタム属性がある場合も同期できます。 1. <InlineTooltip tooltip="各ユーザーに一意のIDを割り当てる">[iOS](identifying-users)、[Android](android-identifying-users)、[React Native](react-native-identifying-users)、[Flutter](flutter-identifying-users)、[Unity](unity-identifying-users)</InlineTooltip>。 2. APIまたはSDKで[属性を更新](api-adapty/operations/updateProfile)する。 これらのカスタム属性を使用して、セグメントを作成したり A/B テストを実行したりできます。 ## ケース5: ペイウォール設定を管理する \{#case-5-manage-paywall-configurations\} アプリを再デプロイすることなく、ペイウォールの外観や動作を動的に変更するために、[ペイウォールのリモートコンフィグを更新](api-adapty/operations/updatePaywall)できます。 --- **次のステップ:** - [サーバーサイド API の認証](ss-authorization)に進む - リクエスト: - [プロファイルを取得する](api-adapty/operations/getProfile) - [プロファイルを作成する](api-adapty/operations/createProfile) - [プロファイルを更新する](api-adapty/operations/updateProfile) - [プロファイルを削除する](api-adapty/operations/deleteProfile) - [アクセスレベルを付与する](api-adapty/operations/grantAccessLevel) - [アクセスレベルを取り消す](api-adapty/operations/revokeAccessLevel) - [トランザクションを設定する](api-adapty/operations/setTransaction) - [購入を検証し、顧客にアクセスレベルを付与し、トランザクション履歴をインポートする](api-adapty/operations/validateStripePurchase) - [インテグレーション識別子を追加する](api-adapty/operations/setIntegrationIdentifiers) - [ペイウォールを取得する](api-adapty/operations/getPaywall) - [ペイウォール一覧を取得する](api-adapty/operations/listPaywalls) - [ペイウォールを更新する](api-adapty/operations/updatePaywall) --- # File: onboardings --- --- title: "Onboardings" --- :::warning The no-code onboarding builder is fully functional, but Adapty is no longer adding features or shipping updates for it. For new projects, consider the [Adapty Flow Builder](adapty-flow-builder) — a visual no-code editor for single-screen paywalls and multi-screen onboarding flows that render natively on device: - **Any flow type**: Build single-screen paywalls, multi-step onboardings that include a paywall, and anything in between. - **Native rendering**: Flows render through the Adapty SDK, without web views. - **Update without redeploying**: Change copy, design, or logic any time, and updates reach users without an app release. ::: Adapty's onboardings let non-technical teams build onboarding flows without code. The no-code builder creates a series of screens that introduce users to your app. You can personalize screens with interactive questions and variables, then run A/B tests to find the best-performing flow. Onboardings are available for apps using Adapty SDK v3.8.0+ (iOS, Android, React Native, Flutter), v3.14.0+ (Unity), or v3.15.0+ (Kotlin Multiplatform, Capacitor). ## How it works 1. [Design an onboarding in the no-code editor.](design-onboarding) 2. [Create a placement for the onboarding.](create-onboarding#step-2-create-a-placement-for-your-onboarding) 3. Integrate the onboarding with your project using the Adapty SDK: - [iOS](ios-onboardings) - [Android](android-onboardings) - [React Native](react-native-onboardings) - [Flutter](flutter-onboardings) - [Unity](unity-onboardings) - [Kotlin Multiplatform](kmp-onboardings) - [Capacitor](capacitor-onboardings) 4. Test the onboarding and release it for your users. --- # File: create-onboarding --- --- title: "オンボーディングを作成する" --- [オンボーディング](onboardings)は、モバイルアプリの価値・機能・使い方を新規ユーザーに紹介するものです。 ## ステップ 1. オンボーディングを作成する \{#step-1-create-an-onboarding\} Adapty ダッシュボードで新しいオンボーディングを作成するには: 1. Adapty のメインメニューから **Onboardings** に移動します。このページでは、設定済みのすべてのオンボーディングとその指標の概要を確認できます。**Create onboarding** をクリックします。 <img src="/assets/shared/img/create-onboarding1.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. オンボーディングのわかりやすい名前を入力し、**Proceed to build onboarding** をクリックします。 <img src="/assets/shared/img/create-onboarding2.png" style={{ border: '1px solid #727272', /* border width and color */ width: '400px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. オンボーディングビルダーにリダイレクトされます。 デフォルトのデモテンプレートが用意されており、オンボーディングがどのようにデータを収集するか、変数やクイズを使ってどのようにパーソナライズできるかを確認できます。不要な画面は自由に削除し、[独自のオンボーディング体験をデザイン](design-onboarding)してください。 <img src="/assets/shared/img/create-onboarding3.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. 準備ができたら、右上の **Preview** ボタンをクリックします。すべてが期待どおりに動作することを確認するために、実際にオンボーディングフローを最後まで体験してください。 <img src="/assets/shared/img/create-onboarding4.png" style={{ border: '1px solid #727272', /* border width and color */ width: '400px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. 問題がなければ、右上の **Publish** をクリックします。Adapty に戻る前に、公開が完了するまで待ってください。そうしないと、作業内容が失われます。 :::danger **Publish** をクリックしないと、SDK は作成したオンボーディングを取得できません。 ::: <img src="/assets/shared/img/create-onboarding5.png" style={{ border: '1px solid #727272', /* border width and color */ width: '400px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> オンボーディングが公開されたら、**Back to Adapty** をクリックします。オンボーディングが作成されました。プレースメントに追加して使い始めることができます。 ## ステップ 2. オンボーディング用のプレースメントを作成する \{#step-2-create-a-placement-for-your-onboarding\} 1. メインメニューから **Placements** に移動し、**Onboardings** タブに切り替えます。**Create placement** をクリックします。 <img src="/assets/shared/img/create-onboarding6.png" style={{ border: '1px solid #727272', /* border width and color */ width: '400px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. プレースメントの名前と ID を入力します。次に、**Run onboarding** をクリックし、すべてのユーザーに表示するオンボーディングを選択します。 3. 特定のユーザーグループ向けに別のオンボーディングを用意している場合は、[オーディエンスを追加](audience)して、そのグループに別のオンボーディングを選択してください。 ## ステップ 3. オンボーディングをアプリに組み込む \{#step-3-integrate-the-onboarding-into-your-app\} :::important オンボーディングは、Adapty SDK v3.8.0 以降(iOS、Android、React Native、Flutter)、v3.14.0 以降(Unity)、または v3.15.0 以降(Kotlin Multiplatform、Capacitor)を使用するアプリで利用できます。 ::: アプリでオンボーディングの表示を開始するには、Adapty SDK を使用して組み込んでください: - [iOS](ios-onboardings) - [Android](android-onboardings) - [React Native](react-native-onboardings) - [Flutter](flutter-onboardings) - [Unity](unity-onboardings) - [Kotlin Multiplatform](kmp-onboardings) - [Capacitor](capacitor-onboardings) どのオンボーディングがより効果的かを把握するために、[A/B テスト](ab-tests)を実施することもできます。 --- # File: design-onboarding --- --- title: "オンボーディングをデザインする" description: "効果的なオンボーディングを作成しましょう。" --- ノーコードのモバイルアプリ向けオンボーディングビルダーは、ユーザーに最高のオンボーディング体験を提供するための強力でカスタマイズ性の高いツールです。開発者やデザイナーでなくても、優れた結果を得ることができます。 ## オンボーディングの画面 \{#onboarding-screens\} オンボーディングのフローは、追加してデザインする複数の画面で構成されます。 ユーザーはボタンをタップして画面間を移動します。 :::tip 一部のユーザーに少し異なるフローが必要な場合(たとえば、フィットネスアプリでユーザーの性別に応じて異なる「目標」画像を表示したい場合)、別のオンボーディングを作成する必要はありません。 代わりに、一部の画面をデフォルトで非表示にし、特定の条件のときだけ表示されるよう設定できます。 ::: ## オンボーディングの要素 \{#onboarding-elements\} オンボーディングの要素は、左側に表示順で表示されます。右上の **Add** をクリックして新しい要素を追加します。 追加できる要素のグループは以下のとおりです: - **Containers**:コンテナを使うと、柔軟なレイアウトを設定できます。たとえば、2カラムのテキストを追加したい場合は、**Columns** を追加してから、左ペインの **Columns** に2つのテキストブロックをドラッグします。カルーセルを追加する場合は、内部の **Media** 要素に画像を追加する必要があります。 - **Typography**:事前にフォーマットされたテキストブロックを追加し、見た目を自由に設定できます。 - **Media & Display**:画像や動画のほか、アプリの価値をアピールしてユーザーの意欲を高めるアニメーションチャートも追加できます。 **対応している動画フォーマット**はMP4とWebMです。**メディアファイルの最大サイズ**は15MBです。 Lottieのような非対応のアニメーション要素を追加したい場合は、動画に変換して(例:[このツール](https://www.lottielab.com/lottie/lottie-to-video)を使用)、動画として埋め込むことができます。 - **Quiz**:テキストや画像の選択肢を使った短いアンケートを作成し、オンボーディング体験をカスタマイズしながらユーザーのことをより深く知ることができます。 - **Inputs**:ユーザーのデータを収集します。 - **Buttons**:ボタンを使うと、画面間の移動、オンボーディングの終了、ペイウォールへの移動をユーザーが行えます。光沢のあるボタンや動くボタンを追加して、ユーザーの注意を引き、インストールを購入につなげることもできます。 - **Loaders**:アニメーションローダーで、処理中もユーザーを飽きさせません。 - **User engagement**:テスティモニアル、ユーザーメールリスト、カウントダウンを追加できます。 :::note **Media & Display** グループの一部として、提供されているカスタマイズオプションでは不十分な場合にカスタムHTMLコードも追加できます。 ただし、カスタムHTML要素はプリロードもキャッシュもされないため、**Raw HTML** は小さく軽量な要素にのみ使用することを推奨します。 ::: <img src="/assets/shared/img/design-onboarding4.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### 要素IDとアクションID \{#element-id-and-action-id\} ボタンをカスタムアクションに使用したい場合は、**アクションID** を割り当て、ソースコード内で使用します。アクションIDを使うと、同じアクションIDを持つ複数のボタンを同じ方法で処理できます。 <img src="/assets/shared/img/ios-events-1.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 特定のフィールドでユーザーの入力を処理したい場合(例:年齢やメールアドレスを保存する)は、**要素ID** を割り当て、ソースコード内で質問と回答を紐付けるために使用します。要素IDはオンボーディング内で1回だけ使用できます。 <img src="/assets/shared/img/design-onboarding5.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## カスタマイズオプション \{#customization-options\} ビルダーでは以下のカスタマイズオプションを利用できます: - **Styles** タブ:要素の見た目を調整します。 <img src="/assets/shared/img/design-onboarding1.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> - **Element** タブ:表示/非表示、ボタン押下時のアクションなど、要素の見た目以外の属性を設定します。 <img src="/assets/shared/img/design-onboarding2.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> - **Screen** タブ:ヘッダーや画面カウンターの表示など、画面全体の設定を行います。 <img src="/assets/shared/img/design-onboarding3.png" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## 画面と要素のコピー \{#copy-screens-and-elements\} オンボーディングを作成済みで、その一部を再利用したい場合や、少し変更を加えてA/Bテストを行いたい場合は、1つまたは複数の画面を別のオンボーディングにコピーできます。 画面をコピーするには、オンボーディングビルダーを開き、次のいずれかを行います: - 単一の画面を右クリックして **Copy** を選択する - 目的の画面を選択して `Ctrl+C`(Windows)または `⌘+C`(Mac)を押す 個々の要素やテキストブロックも、同じオンボーディング内でも別のオンボーディング間でもコピーできます。 ## ウェブ to アプリファネルからの画面のコピー \{#copy-screens-from-web-to-app-funnels\} [FunnelFox](https://funnelfox.com/) で作成したウェブ to アプリファネルを使用していて、ファネルの画面をオンボーディングで使いたい場合は、ファネルビルダーで画面をコピーしてオンボーディングビルダーに貼り付けることで素早く実現できます: 1. FunnelFoxのファネルビルダーで画面を右クリックして **Copy** を選択するか、画面を選択して `Ctrl+C`/`⌘+C` を押します。 2. オンボーディングビルダーを開きます。 3. コピーした画面を挿入したい画面を右クリックして **Paste** を選択するか、その画面を選択して `Ctrl+V`/`⌘+V` を押します。コピーされた画面は選択した画面の下に挿入されます。 <img src="/assets/shared/img/funnel-to-onboarding.gif" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> --- # File: adapty-paywall-builder --- --- title: "Adapty Paywall Builder (Legacy)" description: "ビジュアルなノーコードビルダーでペイウォールとオンボーディングフローを作成します。" --- :::warning ペイウォールビルダーは引き続き完全に動作しますが、Adapty は今後このビルダーへの機能追加やアップデートの提供を終了しています。新規プロジェクトには、[Adapty フロービルダー](adapty-flow-builder) の利用をご検討ください。これは、デバイス上でネイティブにレンダリングされる単一画面のペイウォールおよびマルチ画面オンボーディングフロー向けのビジュアルノーコードエディターです。 - **あらゆるフロータイプに対応**: 単一画面のペイウォール、ペイウォールを含むマルチステップのオンボーディング、そしてその中間にあたるあらゆる構成を構築できます。 - **ネイティブレンダリング**: フローは Adapty SDK を通じてレンダリングされ、Web ビューは使用しません。 - **再デプロイ不要で更新可能**: コピー、デザイン、ロジックをいつでも変更でき、アプリのリリースなしにユーザーへ更新が反映されます。 ::: Adapty の**ペイウォールビルダー**は、カスタムペイウォールをデザインするためのビジュアルノーコードツールです。テンプレートから始めてレイアウトをカスタマイズし、カルーセル、カード、プロダクトリスト、フッターなどの要素を追加できます。カスタムフォント、プロダクトタグ、ローカライズにも対応しています。 ペイウォールビルダーを使用するには Adapty SDK v3.0 以降が必要です。ペイウォールを作成したら、[プレースメントに追加](add-audience-paywall-ab-test)してアプリ内で表示しましょう。 - [iOS](ios-quickstart-paywalls) - [Android](android-quickstart-paywalls) - [React Native](react-native-quickstart-paywalls) - [Flutter](flutter-quickstart-paywalls) - [Unity](unity-quickstart-paywalls) - [Capacitor](capacitor-quickstart-paywalls) - [Kotlin Multiplatform](kmp-quickstart-paywalls) --- # File: flutterflow --- --- title: "Adapty Plugin for FlutterFlow" description: "サブスクリプション管理を強化するために FlutterFlow と Adapty を連携する方法を紹介します。" --- Adapty はモバイルアプリの成長を支援するために設計された多機能プラットフォームです。立ち上げたばかりのアプリでも、すでに数千人のユーザーを抱えているアプリでも、Adapty を使えばアプリ内課金の組み込みにかかる時間を大幅に短縮し、ペイウォール管理でサブスクリプション収益を倍増させることができます。 FlutterFlow 向け Adapty プラグインを使えば、コードを一切書かずに Adapty のすべての機能を活用できます。FlutterFlow でペイウォールページをデザインし、購入機能を有効化した上で、表示するプロダクトをリモートで管理できます。特定のユーザーグループへのターゲティングや A/B テストも利用可能です。アプリをリリースした後は、ダッシュボード上でユーザーの購入に関する詳細な分析データに即座にアクセスできます。 ペイウォールに表示するプロダクトを変更したいときも簡単です! Adapty ダッシュボード内で数クリックするだけで変更が反映され、ユーザーはすぐに新しいプロダクトを確認できます。新バージョンのアプリをリリースする必要はありません! Adapty が提供するその他の機能: - **サブスクリプションとアプリ内課金**: Adapty がサーバーサイドのレシート検証を代わりに行い、ウェブを含むすべてのプラットフォーム間でユーザー情報を同期します。 - **ペイウォールの A/B テスト**: 価格、期間、トライアル期間、ビジュアル要素をテストして、サブスクリプションや買い切り購入を最適化します。 - **強力な分析機能**: 詳細な指標にアクセスして、アプリのマネタイズをより深く理解し改善できます。 - **インテグレーション**: Adapty は Amplitude、AppsFlyer、Adjust、Branch、Mixpanel、Facebook Ads、AppMetrica、カスタム Webhook など、サードパーティの分析ツールとシームレスに連携します。 --- # File: ff-getting-started --- --- title: "はじめに" description: "Adapty フィーチャーフラグを使って、サブスクリプションフローをパーソナライズしましょう。" --- Adapty を使うと、モバイルアプリのユーザーの旅のさまざまな時点(オンボーディング、設定画面など)でペイウォールや A/B テストを作成・実行できます。これらの時点を[プレースメント](placements)と呼びます。アプリ内のプレースメントは、複数のペイウォールや [A/B テスト](ab-tests)を同時に管理でき、それぞれ特定のユーザーグループ([オーディエンス](audience)と呼びます)向けに作成されます。さらに、新しいアプリバージョンをリリースせずに、ペイウォールを別のものと入れ替えながら実験することも可能です。モバイルアプリにハードコードするのはプレースメント ID だけです。 <img src="/assets/shared/img/audience.jpg" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Adapty ライブラリは、Adapty ダッシュボードから最新のプロダクトを取得し、ペイウォールを常に最新の状態に保ちます。[プロダクトデータを取得](ff-action-flow)して[ペイウォールに表示](ff-add-variables-to-paywalls)し、[購入を処理](ff-make-purchase)し、[ユーザーのアクセスレベルを確認](ff-check-subscription-status)して有料コンテンツを表示すべきかどうかを判断します。 始めるには、以下の手順に従って FlutterFlow プロジェクトに [Adapty ライブラリを追加](ff-getting-started#add-the-adapty-library-as-a-dependency)し、[初期化](ff-getting-started#initiate-adapty-plugin)してください。 :::warning 始める前に、以下の制限事項を確認してください: - FlutterFlow 用 Adapty ライブラリは Web アプリをサポートしていません。Web アプリへのコンパイルは避けてください。 - FlutterFlow 用 Adapty ライブラリは、Adapty のペイウォールビルダーで作成されたペイウォールをサポートしていません。Adapty で購入を有効にする前に、FlutterFlow で独自のペイウォールをデザインする必要があります。 ::: ## Adapty ライブラリを依存関係として追加する \{#add-the-adapty-library-as-a-dependency\} 1. [FlutterFlow ダッシュボード](https://app.flutterflow.io/dashboard)でプロジェクトを開き、左メニューから **Settings and Integrations** をクリックします。左側の **Project setup** セクションで **Project dependencies** を選択します。 <img src="/assets/shared/img/main_settings.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. **FlutterFlow Libraries** セクションで **Add Library** をクリックし、`adapty-xtuel0` と入力します。**Add** をクリックします。 3. 次に、SDK キーをライブラリに関連付けます。ライブラリの横にある **View details** をクリックします。 <img src="/assets/shared/img/ff_view_details.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. Adapty ダッシュボードの [**App Settings** -> **General** タブ](https://app.adapty.io/settings/general)から **Public SDK key** をコピーします。 <img src="/assets/shared/FF_img/adaptyapikey.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. FlutterFlow の **AdaptyApiKey** にキーを貼り付けます。 <img src="/assets/shared/img/ff_apikey.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '400px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Adapty FF ライブラリがプロジェクトの依存関係として追加されます。**Adapty** FF ライブラリウィンドウには、プロジェクトにインポートされたすべての Adapty リソースが表示されます。 ## アプリ起動時に新しいアクティベーションアクションを呼び出す \{#call-the-new-activation-action-at-application-launch\} 1. 左メニューから **Custom Code** セクションに移動し、`main.dart` を開きます。 <img src="/assets/shared/img/ff_dartmain.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. **+** をクリックして `activate (Adapty)` を選択します。 <img src="/assets/shared/img/ff_activate.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. **Save** をクリックします。 ## Adapty プラグインを初期化する \{#initiate-adapty-plugin\} Adapty ダッシュボードにアプリを認識させるには、FlutterFlow で特別なキーを設定する必要があります。 1. FlutterFlow プロジェクトで、左メニューから **Settings and Integrations > Permissions** に移動します。 2. 開いた **Permissions** ウィンドウで、**Add Permission** ボタンをクリックします。 3. **iOS Permission Key** と **Android Permission Key** の両方のフィールドに `AdaptyPublicSdkKey` を貼り付けます。 4. **Permission Message** には、Adapty ダッシュボードの [**App Settings** -> **General** タブ](https://app.adapty.io/settings/general)から **Public SDK key** をコピーして貼り付けます。各アプリには固有の SDK キーがあるため、複数のアプリがある場合は正しいキーを使用してください。 <img src="/assets/shared/img/ff_permissions.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> これらの手順が完了すると、FlutterFlow アプリでペイウォールを呼び出し、そこから購入を有効にできるようになります。 ## 次のステップ \{#whats-next\} 1. FlutterFlow で Adapty ペイウォールのプロダクトとそのデータを処理するための[アクションフローを作成](ff-action-flow)します。 2. 受け取ったデータを FlutterFlow でデザインした[ペイウォールにマッピング](ff-add-variables-to-paywalls)します。 3. ペイウォールの[購入ボタンを設定](ff-make-purchase)して、クリック時に Adapty 経由でトランザクションを処理できるようにします。 4. 最後に、[サブスクリプションステータスの確認を追加](ff-check-subscription-status)して、ユーザーに有料コンテンツを表示するかどうかを判断します。 --- # File: ff-action-flow --- --- title: "ステップ1. ペイウォールデータを表示するフローを作成する" description: "Adaptyでフィーチャーフラグのアクションフローを設定し、ユーザーのサブスクリプション体験をパーソナライズする方法を解説します。" --- :::important FlutterFlowプラグインを使用する場合、Adaptyのペイウォールビルダーで作成したペイウォールは使用できません。FlutterFlowで独自のペイウォールページを実装し、Adaptyと連携させる必要があります。 ::: AdaptyライブラリをFlutterFlowプロジェクトの依存関係として追加したら、次は**AdaptyのペイウォールとプロダクトデータをFlutterFlowで設計したペイウォールに取得して表示する**フローを構築します。 まずAdaptyからペイウォールデータを受け取る必要があります。最初にAdaptyのペイウォールをリクエストし、次にそれに関連するプロダクトをリクエストし、最後にデータが正常に受信されたかどうかを確認します。成功した場合はペイウォールページにプロダクトのタイトルと価格を表示し、失敗した場合はエラーメッセージを表示します。 先に進む前に、以下の作業が完了していることを確認してください。 1. Adapty ダッシュボードで[ペイウォールを少なくとも1つ作成し、プロダクトを少なくとも1つ追加している](create-paywall)こと。 2. Adapty ダッシュボードで[プレースメントを少なくとも1つ作成](create-placement)し、[そのペイウォールを追加している](add-audience-paywall-ab-test)こと。 それでは始めましょう! ## ステップ1.1. Adaptyペイウォールをリクエストする \{#step-11-request-adapty-paywall\} 前述の通り、FlutterFlowのペイウォールにデータを表示するには、まずAdaptyからデータを取得する必要があります。最初のステップはAdaptyのペイウォール自体を取得することです。手順は以下の通りです。 1. ペイウォール画面を開き、右ペインの **Actions** セクションに切り替えます。そこから **Action Flow Editor** を開きます。 <img src="/assets/shared/img/ff_action_flow.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. **Select Action Trigger** ウィンドウで **On Page Load** を選択します。 <img src="/assets/shared/img/ff_action_trigger.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. **Add Action** をクリックします。次に、`getPaywall` カスタムアクションを検索して選択します。 <img src="/assets/shared/img/ff_getpaywall.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **Set Actions Arguments** セクションで、ペイウォールを含むAdapity ダッシュボードで[作成したプレースメント](create-placement)の実際のIDを入力します。この例では `monthly` です。必ず実際のプレースメントIDを使用してください! <img src="/assets/shared/img/ff_placementid.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. Adapty ダッシュボードでペイウォールを[ローカライズ](localizations-and-locale-codes)している場合は、**locale** 引数も設定できます。 6. **Action Output Variable Name** で新しい変数を作成し、`getPaywallResult` という名前を付けます。次のステップでAdaptyのペイウォールを参照してプロダクトをリクエストする際に使用します。 <img src="/assets/shared/img/ff_getpaywallresult.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## ステップ1.2. Adaptyペイウォールプロダクトをリクエストする \{#step-12-request-adapty-paywall-products\} Adaptyのペイウォールを取得しました。次は、このペイウォールに関連するプロダクトを取得しましょう。 1. 作成したアクションの下にある **+** をクリックし、**Add Action** を選択します。このアクションでAdaptyペイウォールのプロダクトを受け取ります。`getPaywallProducts` を検索して選択します。 2. **Set Actions Arguments** セクションで、先ほど作成した `getPaywallResult` 変数を選択します。 <img src="/assets/shared/img/ff_getpaywallproduct.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. 残りのフィールドを以下のように入力します。 - **Available Options**: Data Structured Field - **Select Field**: value - **Available Options**: No further changes <img src="/assets/shared/img/ff_getpaywallresult2.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **Confirm** をクリックします。 5. **Action Output Variable Name** で新しい変数を作成し、`getPaywallProductsResult` という名前を付けます。FlutterFlowで設計したペイウォールとAdaptyのペイウォールデータをマッピングする際に使用します。 <img src="/assets/shared/img/ff_getpaywallproductsresult.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## ステップ1.3. ペイウォールが正常にアップロードされたか確認する \{#step-13-add-check-if-the-paywall-uploaded-successfully\} 次に進む前に、Adaptyのペイウォールが正常に受信されたかどうかを確認しましょう。成功した場合はプロダクトデータでペイウォールを更新し、失敗した場合はエラーを処理します。確認を追加する手順は以下の通りです。 1. **+** をクリックし、**Add Conditional** をクリックします。 <img src="/assets/shared/img/ff-add-conditional.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. **Action Output** セクションで、先ほど作成したアクション出力変数(この例では `getPaywallResult`)を選択します。 <img src="/assets/shared/img/ff-getpaywallresult.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. Adaptyのペイウォールが受信されたことを確認するため、値を持つフィールドの存在を確認します。フィールドを以下のように入力します。 - **Available Options**: Has Field - **Field (AdaptyGetPaywallResult)**: value 4. **Confirm** をクリックして条件を確定します。 ## ステップ1.4. ペイウォールの表示をログに記録する \{#step-14-log-the-paywall-review\} Adaptyのアナリティクスがペイウォールの表示を追跡できるよう、このイベントをログに記録する必要があります。この手順を省略すると、表示がアナリティクスでカウントされません。手順は以下の通りです。 1. **TRUE** ラベルの下にある **+** をクリックし、**Add Action** をクリックします。 2. **Select Action** フィールドで **logShowPaywall** を検索して選択します。 <img src="/assets/shared/img/ff-logshowpaywall.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. **Set Action Arguments** エリアで **Value** をクリックし、作成した `getPaywallResult` 変数を選択します。この変数にはペイウォールデータが含まれています。 4. フィールドを以下のように入力します。 - **Available Options**: Data Structured Field - **Select Field**: value 5. **Confirm** をクリックします。 <img src="/assets/shared/img/ff-lohsgowpaywallresult.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## ステップ1.5. ペイウォールが受信されなかった場合にエラーを表示する \{#step-15-show-error-if-paywall-not-received\} Adaptyのペイウォールが受信されなかった場合は、[エラーを処理する](error-handling-on-flutter-react-native-unity#system-storekit-codes)必要があります。この例では、アラートメッセージを表示するだけにします。 1. **FALSE** ラベルに **Informational Dialog** アクションを追加します。 2. **Title** フィールドに、ダイアログのタイトルとして表示したいテキストを入力します。この例では **Error** です。 3. **Message** ボックスで **Value** をクリックします。 4. フィールドを以下のように入力します。 - **Set Variable**: 作成した `getPaywallProductResult` 変数 - **Available Options**: Data Structure Field - **Select Field**: error - **Available Options**: Data Structure Field - **Select Field**: errorMessage <img src="/assets/shared/img/ff-error.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. **Confirm** をクリックします。 6. **FALSE** フローに **Terminate action** を追加します。 <img src="/assets/shared/img/ff-terminate.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 7. 右上隅の **Close** をクリックします。 おめでとうございます!プロダクトデータの取得に成功しました。次は[FlutterFlowで設計したペイウォールにデータをマッピング](ff-add-variables-to-paywalls)しましょう。 --- # File: ff-add-variables-to-paywalls --- --- title: "ステップ 2. ペイウォールページにデータを追加する" description: "Adapty のペイウォールに Feature Flag 変数を追加する。" --- [必要なプロダクトデータをすべて取得](ff-action-flow)したら、FlutterFlow でデザインした美しいペイウォールにそのデータをマッピングしましょう。この例では、プロダクトのタイトルと価格をマッピングします。 ## ステップ 2.1. ペイウォールページにプロダクトタイトルを追加する \{#step-21-add-product-title-to-paywall-page\} 1. ペイウォールページのプロダクトテキストをダブルクリックします。**Set from Variable** ウィンドウで `getPaywallProductResult` 変数を検索して選択します。 <img src="/assets/shared/img/ff-paywall-text.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. 各フィールドを以下のように入力します: - **Available Options**: Data Structured Field - **Select Field**: value - **Available Options**: Item at Index - **List Index Options**: First - **Available Options**: Data Structured Field - **Select Field**: localizedTitle - **Default Variable Value**: null - **UI Builder Display Value**: 任意の値。この例では `product.title` <img src="/assets/shared/img/ff-product.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. **Confirm** をクリックして変更を保存します。 ## ステップ 2.2. ペイウォールページに価格テキストを追加する \{#step-22-add-price-text-to-paywall-page\} ステップ 2.1 と同じ手順を、以下のように価格テキストに対しても繰り返します: 1. ペイウォールページの価格テキストをダブルクリックします。**Set from Variable** ウィンドウで `getPaywallProductResult` 変数を検索して選択します。 <img src="/assets/shared/img/ff-price.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. 各フィールドを以下のように入力します: - **Available Options**: Data Structured Field - **Select Field**: value - **Available Options**: Item at Index - **List Index Options**: First - **Available Options**: Data Structured Field - **Select Field**: price - **Default Variable Value**: null - **UI Builder Display Value**: 任意の値。この例では `product.price` 3. **Confirm** ボタンをクリックして変更を保存します。 ### ペイウォールページに現地通貨の価格を追加する \{#add-price-in-local-currency-to-paywall-page\} 1. ペイウォールページの価格をダブルクリックします。**Set from Variable** ウィンドウで `getPaywallProductResult` 変数を検索して選択します。 2. 各フィールドを以下のように入力します: - **Available Options**: Data Structured Field - **Select Field**: value - **Available Options**: Item at Index - **List Index Options**: First - **Available Options**: Data Structured Field - **Select Field**: price - **Available Options**: Data Structured Field - **Select Field**: amount - **Available Options**: Decimal - **Decimal Type**: Automatic - **Default Variable Value**: null - **UI Builder Display Value**: 任意の値。この例では `price.amount` 3. **Confirm** をクリックして変更を保存します。 これで完了です!アプリを起動すると、Adapty ペイウォールのプロダクトデータがペイウォールページに表示されるようになります! 次は[ユーザーがプロダクトを購入できるようにする](ff-make-purchase)ステップに進みましょう。 --- # File: ff-make-purchase --- --- title: "ステップ 3. 購入を有効にする" description: "AdaptyのFeature Flagsシステムを使って購入を行う方法を学びましょう。" --- おめでとうございます![Adaptyからのプロダクトデータをペイウォールに表示する設定](ff-add-variables-to-paywalls)(プロダクト名や価格を含む)が完了しました。 次は最終ステップとして、ユーザーがペイウォールを通じて購入できるようにしましょう。 ## ステップ 3.1. ユーザーが購入できるようにする \{#step-31-enable-users-to-make-purchases\} 1. ペイウォールページの購入ボタンをダブルクリックします。右パネルで **Actions** セクションがまだ開いていなければ開きます。 2. **Action Flow Editor** を開きます。 <img src="/assets/shared/img/ff-action-flow-editor.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. **Select Action Trigger** ウィンドウで **On Tap** を選択します。 4. **No Actions Created** ウィンドウで **Add Action** をクリックします。`makePurchase` アクションを検索して選択します。 <img src="/assets/shared/img/ff-makepurchase.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. **Set Actions Arguments** セクションで、以前作成した `getPaywallProductsResult` 変数を選択します。 6. 各フィールドを次のように入力します: - **Available Options**: Data Structure Field - **Select Field**: value - **Available Options**: Item at Index - **List Index Options**: First <img src="/assets/shared/img/ff-makepurchase-value.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 7. `subscriptionUpdateParameters` をクリックし、`AdaptySubscriptionUpdateParameters` を検索して選択します。**Confirm** をクリックします。 :::info デフォルトでは、オブジェクトのフィールドはすべて空のままにしておけます。Android アプリで一つのサブスクリプションを別のものに置き換える場合にのみ入力が必要です。詳細は[こちら](https://android.adapty.io/adapty/com.adapty.models/-adapty-subscription-update-parameters/)をご覧ください。 ::: <img src="/assets/shared/img/ff-subupdate.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 8. **Confirm** をクリックします。 9. **Action Output Variable Name** で新しい変数を作成し、`makePurchaseResult` という名前を付けます。これは後で購入が成功したことを確認するために使用します。 <img src="/assets/shared/img/ff-makepurchaseresult.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## ステップ 3.2. 購入が成功したか確認する \{#step-32-check-if-the-purchase-was-successful\} 購入が正常に完了したか確認する処理を設定しましょう。 1. **+** をクリックして **Add Conditional** をクリックします。 2. **Set Condition for Action** で `makePurchaseResult` 変数を選択します。 3. **Set Variable** ウィンドウで各フィールドを次のように入力します: - **Available Options**: Has Field - **Select Field**: profile <img src="/assets/shared/img/ff-makepurchaseresult-conditional.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **Confirm** をクリックします。 ## ステップ 3.3. 有料コンテンツを開く \{#step-33-open-paid-content\} 購入が成功したら、有料コンテンツのロックを解除できます。設定方法は次のとおりです: 1. **TRUE** ラベルの下の **+** をクリックして **Add Action** をクリックします。 2. **Define Action** フィールドで、**Navigate To** リストから開きたいページを検索して選択します。この例では **Questions** ページです。 <img src="/assets/shared/img/ff-questions.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## ステップ 3.4. 購入失敗時にエラーメッセージを表示する \{#step-34-show-error-message-if-purchase-failed\} 購入が失敗した場合は、ユーザーにアラートを表示しましょう。 1. **FALSE** ラベルに **Informational Dialog** アクションを追加します。 2. **Title** フィールドに、ダイアログのタイトルとして表示するテキストを入力します(例:**Purchase Failed**)。 <img src="/assets/shared/img/ff-purchase-fail.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. **Message** ボックスの **Value** をクリックします。**Set from Variable** ウィンドウで `makePurchaseResult` を検索して選択します。各フィールドを次のように入力します: - **Available Options**: Data Structure Field - **Select Field**: error - **Available Options**: Data Structure Field - **Select Field**: errorMessage <img src="/assets/shared/img/ff-fail-message.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **Confirm** をクリックします。 5. **FALSE** フローに **Terminate** アクションを追加します。 <img src="/assets/shared/img/ff-terminate-purchase.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 6. 最後に、右上隅の **Close** をクリックします。 おめでとうございます!これでユーザーがプロダクトを購入できるようになりました。追加のステップとして、[有料コンテンツへのユーザーアクセスを確認する設定](ff-check-subscription-status)を行い、有料コンテンツまたはペイウォールのどちらを表示するかを判断できるようにしましょう。 --- # File: ff-check-subscription-status --- --- title: "ステップ 4. 有料コンテンツへのアクセスを確認する" description: "Adaptyのフィーチャーフラグを使用してサブスクリプションステータスを確認し、ユーザーセグメンテーションを改善する方法を学びましょう。" --- ユーザーが特定の有料コンテンツにアクセスできるかどうかを確認するには、そのユーザーのアクセスレベルを検証する必要があります。具体的には、ユーザーが少なくとも1つのアクセスレベルを持っているか、またそのレベルが必要なものであるかをチェックします。 これは、利用可能なすべてのアクセスレベルを含むユーザーのプロファイルを確認することで行えます。 それでは、ユーザーがプロダクトを購入できるようにしましょう: 1. 有料コンテンツを表示するボタンをダブルクリックし、右ペインの **Actions** セクションがまだ開いていない場合は開きます。 2. **Action Flow Editor** を開きます。 <img src="/assets/shared/img/ff-open-paid-content.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. **Select Action Trigger** ウィンドウで、**On Tap** を選択します。 4. **No Actions Created** ウィンドウで、**Add Conditional Action** ボタンをクリックします。 5. **UNSET** をクリックしてアクション引数を設定し、`currentProfile` 変数を選択します。これは現在のユーザーのプロファイルに関するデータを保持するAdaptyの変数です。 <img src="/assets/shared/img/ff-currentprofile.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '300px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 6. 以下のようにフィールドを入力します: - **Available Options**: Data Structure Field - **Select Field**: accessLevels - **Available Options**: Filter List Items - **Filter Conditions**: 1. **Conditions -> Single Condition** を選択し、**UNSET** をクリックします。 2. **First value** フィールドで、**Source** として **Item in list** を選択し、以下のようにフィールドを入力します: - **Available Options**: Data Structure Field - **Select Field**: accessLevelIdentifier 3. フィルター演算子を **Equal to** に設定します。 4. **Second value** の隣にある **UNSET** をクリックし、**Value** フィールドにアクセスレベルのIDを入力します。この例では `premium` を使用します。 <img src="/assets/shared/img/ff-filter.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '500px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. **Confirm** をクリックし、以下の他のフィールドへの入力を続けます。 - **Available Options**: Item at Index - **List Index Options**: First - **Available Options**: Data Structure Field - **Select Field**: accessLevel - **Available Options**: Data Structure Field - **Select Field**: isActive 7. **Confirm** をクリックします。 次に、ユーザーが適切なサブスクリプションを持っているかどうかに応じて、次に何が起こるかのアクションを追加します。プレミアムサブスクライバーが利用できるページに移動させるか、アクセスを購入できるようにペイウォールページを開きます。 --- # File: ff-resources --- --- title: "Adapty FlutterFlow プラグインのアクションとデータ型" description: "Adaptyの機能フラグリソースにアクセスして、サブスクリプションベースの機能を効率化しましょう。" --- ## カスタムアクション \{#custom-actions\} 以下は、Adapty プラグインを通じて FlutterFlow に提供される Adapty メソッドです。FlutterFlow のカスタムアクションとして使用できます。 | カスタムアクション | 説明 | アクション引数 | Adapty データ型 - アクション出力変数 | |---|----|--------|----| | activate | Adapty SDK を初期化します | なし || | <p id="getPaywall">getPaywall</p> | ペイウォールを取得します。ペイウォールのプロダクトは返しません。実際のプロダクトを取得するには `getPaywallProducts` アクションを使用してください | <ul><li>[Placement_ID](placements)</li><li>[Locale](localizations-and-locale-codes)</li></ul> | [AdaptyGetPaywallResult](ff-resources#adaptygetpaywallresult)| | <p id="getPaywallProducts">getPaywallProducts</p> | 実際のペイウォールプロダクトのリストを返します | [AdaptyPaywall](ff-resources#adaptypaywall) | [AdaptyGetProductsResult](ff-resources#adaptygetproductsresult) | | <p id="getproductsintroductoryoffereligibility">getProductsIntroductoryOfferEligibility</p> | ユーザーが iOS サブスクリプションの初回オファーを利用できるか確認します | [AdaptyPaywallProduct](product) | [AdaptyGetIntroEligibilitiesResult](ff-resources#adaptygetintroeligibilitiesresult) | | <p id="makePurchase">makePurchase</p> | 購入を完了してコンテンツを解放します。ペイウォールにプロモーションオファーがある場合、Adapty は自動的にチェックアウト時に適用します | <ul><li> **product**: ペイウォールから取得した AdaptyPaywallProduct オブジェクト。</li><li> **subscriptionUpdateParams**: サブスクリプションのアップグレードまたはダウングレードに使用する [`AdaptySubscriptionUpdateParameters`](ff-resources#adaptysubscriptionupdateparameters) オブジェクト(Android で使用)。</li><li>**isOfferPersonalized**: オファーが購入者にパーソナライズされているかどうかを指定します(Android で使用)。</li></ul> | [AdaptyMakePurchaseResult](ff-resources#adaptymakepurchaseresult) | | <p id="getprofile">getProfile</p> | <p>現在のアプリユーザーのプロファイルを取得します。これによりアクセスレベルやその他のパラメーターを設定できます。</p><p>失敗した場合(例: インターネット接続なし)、キャッシュされたデータが返されます。Adapty はプロファイルのキャッシュを定期的に更新し、情報をできる限り最新の状態に保ちます。</p> | なし | [AdaptyGetProfileResult](ff-resources#adaptygetprofileresult) | | updateProfile | メールアドレスや電話番号などの現在のユーザープロファイルのオプション属性を変更します。属性を使ってユーザーの[セグメント](segments)を作成したり、CRM で閲覧したりすることができます | [AdaptyProfile](ff-resources#adaptyprofile) の ID および更新が必要なパラメーター | [AdaptyError](ff-resources#adaptyerror)(オプション) | | restorePurchases | ユーザーが行った購入を復元します | なし | [AdaptyGetProfileResult](ff-resources#adaptygetprofileresult) | | logShowPaywall | 特定のペイウォールがユーザーに表示されたときにログを記録します | [AdaptyPaywall](ff-resources#adaptypaywall) | [AdaptyError](ff-resources#adaptyerror)(オプション) | | identify | システムの `customerUserId` を使用してユーザーを識別します | customerUserId | [AdaptyError](ff-resources#adaptyerror)(オプション) | | logout | 現在のユーザーをアプリからログアウトします | なし | [AdaptyError](ff-resources#adaptyerror)(オプション)| | presentCodeRedemptionSheet | ユーザーがコードを引き換えるためのシートを表示します(iOS のみ) | なし | なし | ## データ型 \{#data-types\} Adapty プラグインを通じて FlutterFlow に届く Adapty のデータ型(データ値のコレクション)です。 ### AdaptyAccessLevel ユーザーの[アクセスレベル](access-level)に関する情報。 | フィールド名 | 型 | 説明 | |--------------------------|----------|-------------| | activatedAt | DateTime | このアクセスレベルが有効化された日時 | | activeIntroductoryOfferType | String | 有効な初回オファーのタイプ。設定されている場合、このサブスクリプション期間中にオファーが適用されたことを意味します | | activePromotionalOfferId | String | 有効なプロモーションオファーのID(iOSから購入) | | activePromotionalOfferType | String | 有効なプロモーションオファーのタイプ(iOSから購入)。設定されている場合、このサブスクリプション期間中にオファーが適用されたことを意味します | | billingIssueDetectedAt | DateTime | 請求の問題が検出された日時。サブスクリプションは引き続き有効な場合があります。支払いが正常に処理された場合はnullに設定されます | | cancellationReason | String | サブスクリプションがキャンセルされた理由 | | expiresAt | DateTime | アクセスレベルの有効期限(過去の日時になる場合や、永続アクセスの場合は未設定になる場合があります) | | id | String | アクセスレベルの識別子 | | isActive | Boolean | このアクセスレベルが有効な場合はtrue。一般的に、ユーザーがプレミアム機能にアクセスできるかどうかの判定にこのプロパティを使用できます | | isInGracePeriod | Boolean | この自動更新サブスクリプションが[グレース期間](https://developer.apple.com/help/app-store-connect/manage-subscriptions/enable-billing-grace-period-for-auto-renewable-subscriptions)中の場合はtrue | | isLifetime | Boolean | このアクセスレベルが永続的に有効(有効期限なし)な場合はtrue | | isRefund | Boolean | この購入が返金された場合はtrue | | offerId | String | 有効なプロモーションオファーのID(Androidから購入) | | renewedAt | DateTime | アクセスレベルが最後に更新された日時 | | startsAt | DateTime | このアクセスレベルの開始日時(将来の日時になる場合があります) | | store | String | 購入が行われたストア | | unsubscribedAt | DateTime | サブスクリプションの自動更新がオフになった日時。サブスクリプションは引き続き有効な場合があります。未設定の場合、ユーザーはサブスクリプションを再有効化しています | | vendorProductId | String | このアクセスレベルを解放したストアのプロダクトID | | willRenew | Boolean | この自動更新サブスクリプションが更新設定になっている場合はtrue | ### AdaptyAccessLevelIdentifiers この構造体は、`Map<String, AdaptyAccessLevel` [AdaptyAccessLevel](ff-resources#adaptyaccesslevel) のキーと値のペアを置き換えるためのものです。 | フィールド名 | 型 | 説明 | |------------|------|-------------| | accessLevelIdentifier | String | アクセスレベルの ID | | accessLevel | Data ([AdaptyAccessLevel](ff-resources#adaptyaccesslevel)) | 関連する [AdaptyAccessLevel](ff-resources#adaptyaccesslevel) | ### AdaptyCustomDoubleAttribute [ユーザー](ff-resources#adaptyprofile)に定義されたカスタムDouble属性に関する情報です。 | フィールド名 | 型 | 説明 | |------------|------|-------------| | key | String | カスタムDouble属性のID | | value | Double | カスタムDouble属性の値 | ### AdaptyCustomStringAttribute [ユーザー](ff-resources#adaptyprofile)に定義されたカスタム文字列属性の情報です。 | フィールド名 | 型 | 説明 | |------------|------|-------------| | key | String | カスタム文字列属性のID | | value | String | カスタム文字列属性の値 | ### AdaptyError エラーの詳細情報を含みます。エラーコードの完全なリストについては、[React Native、Flutter、Unity - エラー処理](error-handling-on-flutter-react-native-unity)を参照してください。 | フィールド名 | 型 | 説明 | |--------------------------|----------|-------------| | errorMessage | String | エラーの人間が読める説明 | | errorCode | Integer | エラーを識別する数値コード | ### AdaptyGetIntroEligibilitiesResult `getProductsIntroductoryOfferEligibility` カスタムアクションの結果を含みます。 | フィールド名 | 型 | 説明 | |--------------------------|----------|-------------| | value | List < Data ([AdaptyProductIntroEligibility](ff-resources#adaptyproductintroeligibility)) > | ユーザーのプロモーションオファー利用資格のリスト | | error | Data ([AdaptyError](ff-resources#adaptyerror)) | [`AdaptyError`](ff-resources#adaptyerror) を通じたエラーの詳細 | ### AdaptyGetPaywallResult `getPaywall` カスタムアクションの結果を格納します。 | フィールド名 | 型 | 説明 | |--------------------------|----------|-------------| | value | Data ([AdaptyPaywall](ff-resources#adaptypaywall)) | [AdaptyPaywall](ff-resources#adaptypaywall) オブジェクトのリストを格納します | | error | Data ([AdaptyError](ff-resources#adaptyerror)) | [AdaptyError](ff-resources#adaptyerror) を通じたエラー情報を格納します | ### AdaptyGetProductsResult `getPaywallProducts` カスタムアクションの結果を格納します。 | フィールド名 | 型 | 説明 | |--------------------------|----------|-------------| | value | List < Data ([AdaptyPaywallProduct](product)) > | [AdaptyPaywallProduct](product) のリストを格納します | | error | Data ([AdaptyError](ff-resources#adaptyerror)) | [AdaptyError](ff-resources#adaptyerror) を通じてエラー情報を格納します | ### AdaptyGetProfileResult `getProfile` カスタムアクションの結果を含みます。 | フィールド名 | 型 | 説明 | |--------------------------|----------|-------------| | value | Data ([AdaptyProfile](ff-resources#adaptyprofile)) | [AdaptyProfile](ff-resources#adaptyprofile) としてユーザープロファイルを含みます | | error | Data (AdaptyError) | [AdaptyError](ff-resources#adaptyerror) を通じてエラー情報を含みます | ### AdaptyMakePurchaseResult `makePurchase` カスタムアクションの結果を含みます。 | フィールド名 | 型 | 説明 | |--------------------------|----------|-------------| | value | Data ([AdaptyProfile](ff-resources#adaptyprofile)) | [AdaptyProfile](ff-resources#adaptyprofile) としてユーザーのプロファイルを含みます | | error | Data ([AdaptyError](ff-resources#adaptyerror)) | [AdaptyError](ff-resources#adaptyerror) を通じたエラー情報を含みます | ### AdaptyNonSubscription サブスクリプション以外の購入に関する情報です。これには、消耗型アイテム(一度限りの購入)やアンロック(ゲームの新しいマップのアンロックなど)が含まれます。 | フィールド名 | 型 | 説明 | |--------------------------|----------|-------------| | isConsumable | Boolean | プロダクトが消耗型アイテムかどうかを示す | | isOneTime | Boolean | プロダクトが買い切り購入かどうかを示す(true の場合、購入は一度だけ処理される) | | isRefund | Boolean | プロダクトが返金済みかどうかを示す | | isSandbox | Boolean | プロダクトがサンドボックス環境で購入されたかどうかを示す | | purchasedAt | DateTime | プロダクトが購入された日時 | | purchaseId | String | Adapty における購入の ID。買い切り購入のトラッキングに使用できる | | store | String | プロダクトが購入されたストア(App Store、Google Play など) | | vendorProductId | String | ベンダーのシステムにおけるプロダクト ID | | vendorTransactionId | String | ベンダーのシステムにおけるトランザクション ID | ### AdaptyPaywall [ペイウォール](paywalls)に関する情報です。 | フィールド名 | 型 | 説明 | |----------------------|----------|-------------| | abTestName | String | 親 A/B テストの名前 | | hasViewConfiguration | Boolean | ペイウォールにビュー設定があるかどうかを示す | | locale | String | ペイウォールのロケール ID | | name | String | ペイウォール名 | | placement.id | String | 親プレースメントの ID | | remoteConfigString | String | このペイウォールに関連付けられた Adapty ダッシュボードのカスタムディクショナリ | | placement.revision | Integer | ペイウォールの現在のリビジョン/バージョン。変更のたびに新しいリビジョンが生成される | | variationId | String | このペイウォールへの購入を紐付けるために使用するバリエーション ID | | vendorProductIds | String | ペイウォールに関連するプロダクト ID の配列 | ### AdaptyPaywallProduct [プロダクト](product)に関する情報です。 | フィールド名 | 型 | 説明 | | -------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | | vendorProductId | String | アプリストアのプロダクトID | | localizedDescription | String | ユーザーの言語によるプロダクトの説明 | | localizedTitle | String | ユーザーの言語によるプロダクト名 | | regionCode | String | プロダクトの価格をフォーマットする際に使用するロケールのリージョンコード(iOS用) | | isFamilyShareable | Boolean | App Store Connectでプロダクトのファミリー共有が有効かどうかを示すBoolean値。iOS 14.0未満およびmacOS 11.0未満では常にFALSEになります(iOS用) | | paywallVariationId | String | バリアントのID。購入をこのペイウォールにアトリビュートするために使用します | | paywallABTestName | String | 親A/B テスト名 | | paywallName | String | 親ペイウォール名 | | price | Data ([AdaptyPriceData](#adaptyprice)) | プロダクトの価格 | | subscriptionDetails | Data ([AdaptySubscriptionDetails](#adaptysubscriptiondetails)) | サブスクリプションに関する情報 | ### AdaptyPrice プロダクトの価格に関する情報です。 | フィールド名 | 型 | 説明 | | --------------- | ------ | ------------------------------ | | amount | Double | 価格の数値 | | currencyCode | String | 価格の通貨コード | | currencySymbol | String | 通貨に使用される記号 | | localizedString | String | ユーザーの言語で表示された価格 | ### AdaptyProductIntroEligibility iOSサブスクリプションの初回オファー対象資格をユーザーが持っているかどうかを定義します。 | フィールド名 | 型 | 説明 | | --------------- | ----------------------------------------------------------- | ------------------------------------------------------------ | | vendorProductId | String | アプリストアのプロダクトID | | eligibility | [AdaptyEligibilityEnum](ff-resources#adaptyeligibilityenum) | iOSサブスクリプションの初回オファーにユーザーが適格かどうかの定義 | ### AdaptyProductNonsubscriptions このプロダクトに紐づくアクティブな買い切り購入の詳細。 | フィールド名 | 型 | 説明 | | ---------------- | ----------------------------------------------------------- | ------------------------------------------------------------ | | productId | String | アプリストアにおけるプロダクトのID | | nonsubscriptions | [AdaptyNonSubscription](ff-resources#adaptynonsubscription) | サブスクリプション以外の購入に関する情報。消耗型アイテム(コンシューマブル)や、ゲームの新マップ解放などの買い切り購入が含まれます。 | ### AdaptyProductSubscriptions このプロダクトに紐づくアクティブなサブスクリプションの詳細。 | フィールド名 | 型 | 説明 | | ------------ | ----------------------------------------------------- | ---------------------------------------- | | productId | String | ストアのプロダクトID | | subscription | [AdaptySubscription](ff-resources#adaptysubscription) | サブスクリプション購入に関する情報 | ### AdaptyProfile ユーザーのプロファイルに関する情報 | フィールド名 | 型 | 説明 | | ---------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | | accessLevels | List < Data ([AdaptyAccessLevelIdentifiers](ff-resources#adaptyaccesslevelidentifiers)) > | ユーザーに紐づくすべてのアクセスレベルのリスト | | profileId | String | ユーザープロファイルのID | | customerUserId | String | ベンダーシステム上のユーザーID | | subscriptions | List < Data ([MapKeySubscriptions](#mapkeysubscriptions)) > | ユーザーが購入したすべてのサブスクリプションのリスト | | nonSubscriptions | List < Data ([MapKeyNonSubscriptions](#mapkeynonsubscriptions)) > | ユーザーが購入したすべての非サブスクリプションプロダクトのリスト | ### AdaptyProfileParameters ユーザーに関する情報。 | フィールド名 | 型 | 説明 | | ----------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | | firstName | String | ユーザーの名前 | | lastName | String | ユーザーの苗字 | | gender | [AdaptyGenderEnum](#adaptygenderenum) | ユーザーの性別 | | birthday | String | ユーザーの生年月日 | | email | String | ユーザーのメールアドレス | | phoneNumber | String | ユーザーの電話番号 | | facebookAnonymousId | String | [Facebook Ads 連携](facebook-ads)におけるユーザーの ID | | amplitudeUserId | String | [Amplitude 連携](amplitude)におけるユーザーの ID | | amplitudeDeviceId | String | [Amplitude 連携](amplitude)におけるユーザーのデバイス ID | | mixpanelUserId | String | [Mixpanel 連携](mixpanel)におけるユーザーの ID | | appmetricaProfileId | String | [AppMetrica 連携](appmetrica)におけるユーザーの ID | | appmetricaDeviceId | String | [AppMetrica 連携](appmetrica)におけるユーザーのデバイス ID | | oneSignalPlayerId | String | [OneSignal 連携](onesignal)におけるユーザーの ID | | pushwooshHWID | String | [Pushwoosh 連携](pushwoosh)におけるユーザーのデバイス ID | | firebaseAppInstanceId | String | [Firebase 連携](firebase-and-google-analytics)におけるユーザーの ID | | airbridgeDeviceId | String | [Airbridge 連携](airbridge)におけるユーザーのデバイス ID | | appTrackingTransparencyStatus | AdaptyATTStatus | IDFA へのアクセスステータス(iOS 用) | | analyticsDisabled | Boolean | [特定のユーザーに対して外部アナリティクスをオプトアウト](analytics-integration#disabling-external-analytics-for-a-specific-customer)するかどうかの設定 | | customStringAttributes | List < Data ([AdaptyCustomStringAttribute](ff-resources#adaptycustomstringattribute)) > | ユーザーのカスタム文字列属性のリスト | | customDoubleAttributes | List < Data ([AdaptyCustomDoubleAttribute](ff-resources#adaptycustomdoubleattribute)) > | ユーザーのカスタム数値(double)属性のリスト | ### AdaptySubscription 既存のユーザーサブスクリプションに関する情報。 | フィールド名 | 型 | 説明 | | --------------------------- | -------- | ------------------------------------------------------------ | | activatedAt | DateTime | このサブスクリプションがアクティベートされた日時 | | activeIntroductoryOfferType | String | 有効な初回オファーのタイプ。設定されている場合、このサブスクリプション期間中にオファーが適用されたことを意味します | | activePromotionalOfferId | String | 有効なプロモーションオファーのID(iOS用) | | activePromotionalOfferType | String | 有効なプロモーションオファーのタイプ(iOS用)。設定されている場合、このサブスクリプション期間中にオファーが適用されたことを意味します | | cancellationReason | String | サブスクリプションがキャンセルされた理由 | | expiresAt | DateTime | サブスクリプションの有効期限 | | renewedAt | DateTime | サブスクリプションが最後に更新された日時 | | unsubscribedAt | DateTime | サブスクリプションの自動更新がオフになった日時。サブスクリプション自体はまだ有効な場合があります。設定されていない場合、ユーザーがサブスクリプションを再有効化したことを意味します | | billingIssueDetectedAt | DateTime | 請求の問題が検出された日時。サブスクリプション自体はまだ有効な場合があります。支払いが正常に処理された場合はnullに設定されます | | isActive | Boolean | このサブスクリプションが有効な場合はTrue。一般的に、ユーザーがプレミアム機能にアクセスできるかどうかを判断するにはこのプロパティを確認します | | isInGracePeriod | Boolean | この自動更新サブスクリプションが[グレース期間](https://developer.apple.com/help/app-store-connect/manage-subscriptions/enable-billing-grace-period-for-auto-renewable-subscriptions)内にある場合はTrue | | isLifetime | Boolean | このサブスクリプションが永続アクセス(有効期限なし)の場合はTrue | | isRefund | Boolean | この購入が返金された場合はTrue | | isSandbox | Boolean | プロダクトがサンドボックス環境で購入されたかどうかを示します | | offerId | String | 有効なプロモーションオファーのID(Android用) | | startsAt | DateTime | このアクセスレベルの開始日時(将来の日時になる場合もあります) | | store | String | プロダクトが購入されたストア(例:App Store、Google Play) | | vendorOriginalTransactionId | String | ベンダーシステムにおける最初のサブスクリプションのID | | vendorProductId | String | ベンダーシステムにおけるプロダクトのID | | vendorTransactionId | String | ベンダーシステムにおけるトランザクションID | | willRenew | Boolean | この自動更新サブスクリプションが更新される設定になっている場合はTrue | ### AdaptySubscriptionDetails [AdaptyPaywallProduct](product) の一部である Subscription オブジェクトのスキーマ。 | フィールド名 | 型 | 説明 | | ----------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | | androidBasePlanId | String | Google Play ストアの[ベースプランID](https://support.google.com/googleplay/android-developer/answer/12154973)、またはStripeの[価格ID](https://docs.stripe.com/products-prices/how-products-and-prices-work#use-products-and-prices)。 | | androidIntroductoryOfferEligibility | [AdaptyEligibilityEnum](ff-resources#adaptyeligibilityenum) | iOSサブスクリプションの初回オファーにユーザーが適格かどうかの定義 | | androidOfferId | String | アクティブなプロモーションオファーのID(Android用) | | androidOfferTags | List < String > | ベースプランおよびサブスクリプションオファーに指定された[カスタムタグ](https://developers.google.com/android-publisher/api-ref/rest/v3/OfferTag)のリスト。 | | introductoryOffer | List < Data ([AdaptySubscriptionPhase](ff-resources#adaptysubscriptionphase)) > | 初回オファーのID(iOS用) | | localizedSubscriptionPeriod | String | ユーザーの言語によるサブスクリプション期間 | | promotionalOffer | Data ([AdaptySubscriptionPhase](ff-resources#adaptysubscriptionphase)) | プロモーションオファーの詳細(iOS用) | | promotionalOfferEligibility | Boolean | iOSサブスクリプションのプロモーションオファーにユーザーが適格かどうかの定義 | | promotionalOfferId | String | プロモーションオファーのID(iOS用) | | renewalType | [AdaptyRenewalTypeEnum](#adaptyrenewaltypeenum) | [AdaptyRenewalTypeEnum](ff-resources#adaptyrenewaltypeenum) によって、サブスクリプションが自動更新かどうかを定義する | | subscriptionGroupIdentifier | String | プロダクトが属するプロダクトグループのID(iOS用) | | subscriptionPeriod | Data ([AdaptySubscriptionPeriod](#adaptysubscriptionperiod)) | サブスクリプションの期間 | ### AdaptySubscriptionPeriod サブスクリプションの期間。 | フィールド名 | 型 | 説明 | | ------------- | --------------------------------------------- | ----------------------------------------------------------- | | numberOfUnits | Integer | サブスクリプションの期間(日数・週数・月数・年数)。 | | unit | [AdaptyPeriodUnitEnum](#adaptyperiodunitenum) | 期間の単位(日・週・月・年)。 | ### AdaptySubscriptionPhase サブスクリプションのフェーズ(無料トライアルや初回オファー期間など)を表します。 | フィールド名 | 型 | 説明 | | --------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | | identifier | String | フェーズのID | | localizedNumberOfPeriods | String | フェーズの長さ。たとえば、6ヶ月のオファーはユーザーの言語で `6 months` のように表示されます。 | | localizedSubscriptionPeriod | String | ユーザーの言語でのサブスクリプション期間(例:`3 months`)。 | | numberOfPeriods | Integer | このフェーズのサブスクリプション期間の数。たとえば、6ヶ月のオファーは3ヶ月の期間が2つになります。 | | paymentMode | [AdaptyPaymentModeEnum](#adaptypaymentmodeenum) | このフェーズに使用される支払いモデル。 | | price | Data ([AdaptyPrice](#adaptyprice)) | このフェーズの価格。 | | subscriptionPeriod | Data ([AdaptySubscriptionPeriod](#adaptysubscriptionperiod)) | このフェーズが基づくサブスクリプション期間。 | ### AdaptySubscriptionUpdateParameters (*Android のみ*) サブスクリプションを別のサブスクリプションに切り替えるためのパラメーター。 | フィールド名 | 型 | 説明 | | ---------- | ------------------------------------------------------------ | ---------- | | oldSubVendorProductId | String | 置き換えたい現在のサブスクリプションの Play Store 上の ID。 | | replacementMode | [AdaptySubscriptionUpdateReplacementMode](ff-resources#adaptysubscriptionupdatereplacementmode) | [`BillingFlowParams.ProrationMode`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode) の値に対応する Enum。 | ### MapKeyNonSubscriptions [AdaptyNonSubscription](ff-resources#adaptynonsubscription) の辞書の代替です。 | フィールド名 | 型 | | ------------ | ------------------------------------------------------------ | | key | String | | value | List < Data ([AdaptyNonSubscription](ff-resources#adaptynonsubscription)) > | ### MapKeySubscriptions [AdaptySubscription](ff-resources#adaptysubscription) の辞書の代替。 | フィールド名 | 型 | | ------------ | ------------------------------------------------------------ | | key | String | | value | List < Data ([AdaptySubscription](ff-resources#adaptysubscription)) > | ## 列挙型 \{#enums\} Adapty プラグインを通じて FlutterFlow に提供される Adapty の列挙型(あらかじめ定義された定数の集合)です。 ### AdaptyEligibilityEnum iOSサブスクリプションの初回オファーにユーザーが適格かどうかを定義します。 | フィールド名 | 説明 | |--------------------------|-------------| | eligible | ユーザーは初回オファーの対象です。この情報をUIに表示しても問題ありません | | ineligible | ユーザーはいかなるオファーの対象でもありません。UIに表示しないでください | | notApplicable | このプロダクトにはオファーが設定されていません | ### AdaptyGenderEnum ユーザーの性別を定義します。 | フィールド名 | 説明 | | ------------ | ---------------------------------- | | none | 性別が設定されていない | | female | ユーザーの性別が女性 | | male | ユーザーの性別が男性 | | Other | ユーザーが性別を「その他」と設定した | ### AdaptyPaymentModeEnum 支払いモデルを定義します。 | フィールド名 | 説明 | | ---------- | ------------------------------------------------------------ | | payAsYouGo | 固定料金を前払いするのではなく、プロダクト/サービスの実際の使用量や消費量に基づいて請求される料金モデル | | payUpFront | プロダクト/サービスを受け取る前に請求される料金モデル | | freeTrial | 無料トライアル期間中のユーザー | | unknown | 料金モデルが定義されていない | ### AdaptyPeriodUnitEnum 期間を計測する単位を定義します。 | フィールド名 | 説明 | | ---------- | ----------- | | day | 日単位 | | week | 週単位 | | month | 月単位 | | year | 年単位 | | unknown | 未定義 | ### AdaptyRenewalTypeEnum サブスクリプションが自動更新かどうかを定義します。 | フィールド名 | 説明 | | ------------- | -------------------------------------------- | | prepaid | サブスクリプションはプリペイドで、自動更新ではありません。 | | autorenewable | サブスクリプションは自動更新です。 | ### AdaptySubscriptionUpdateReplacementMode Androidのサブスクリプション更新モードを定義します。 | フィールド名 | 説明 | | ------------- | --------------------------------------------------- | | withTimeProration | (デフォルト)新しいプランはすぐに有効になり、残り期間は日割り計算されてユーザーにクレジットされます。 | | chargeProratedPrice | 新しいプランはすぐに有効になり、請求サイクルはそのまま維持されます。残り期間分の料金が請求されます。このオプションはサブスクリプションのアップグレード時のみ使用できます。 | | withoutProration | 新しいプランはすぐに有効になり、次回の更新タイミングで新しい料金が請求されます。請求サイクルはそのまま維持されます。 | | deferred | 新しい購入はすぐに有効になり、古いアイテムの有効期限が切れた時点で新しいプランが適用されます。 | | chargeFullPrice | 新しいプランはすぐに有効になり、請求サイクルはそのまま維持されます。残り期間分の料金が請求されます。このオプションはサブスクリプションのアップグレード時のみ使用できます。 | ### アプリの状態 \{#app-states\} アプリ状態変数は、アプリケーションの現在の状態を保持する特別な変数です。すべてのページやコンポーネントにわたってアプリ全体からアクセス・変更できます。この種の変数は、ユーザー設定や認証トークンなど、アプリのさまざまな部分で共有する必要があるデータを保存する際に役立ちます。 | フィールド名 | データ型 | 永続化 | 説明 | | -------------- | -------------------------------------------------- | --------- | ------------------------------------------------------------ | | currentProfile | Data ([AdaptyProfile](ff-resources#adaptyprofile)) | False | 現在のユーザープロファイルの情報を格納する変数です。常に最新の状態を保つようにしてください。 | --- # End of Documentation _Generated on: 2026-06-24T14:36:28.745Z_ _Successfully processed: 265/265 files_ # UNITY - Adapty Documentation (Full Content) This file contains the complete content of all documentation pages for this platform. Locale: ja Generated on: 2026-06-24T14:36:28.752Z Total files: 41 --- # File: sdk-installation-unity --- --- title: "Unity SDK のインストールと設定" description: "サブスクリプション型アプリ向けに Unity に Adapty SDK をインストールするためのステップバイステップガイド。" --- Adapty SDK には、Unity アプリへのシームレスな統合を実現するための 2 つの主要モジュールが含まれています。 - **Core Adapty**: アプリで Adapty を正常に動作させるために必要な SDK です。 - **AdaptyUI**: クロスプラットフォーム対応のペイウォールをノーコードで簡単に作成できるツール [Adapty ペイウォールビルダー](adapty-paywall-builder) を使用する場合に必要なモジュールです。 :::tip Adapty SDK がモバイルアプリにどのように統合されているかの実例を確認したい場合は、[サンプルアプリ](https://github.com/adaptyteam/AdaptySDK-Unity/tree/main/Assets)をご覧ください。ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを確認できます。 ::: ## 要件 \{#requirements\} Adapty SDK は iOS 13.0 以上をサポートしていますが、ペイウォールビルダーで作成したペイウォールを使用するには iOS 15.0 以上が必要です。 :::info Adapty は Google Play Billing Library 8.x 以下と互換性があります。デフォルトでは、Adapty は Google Play Billing Library v7.0.0 を使用します。新しいバージョンを使用するには、Android ビルドで [Billing の依存関係を上書き](https://developer.android.com/google/play/billing/integrate#dependency)してください。 ::: --- no_index: true --- import Callout from '../../../components/Callout.astro'; <Callout type="info"> SDKのインストールは、Adaptyセットアップのステップ5です。アプリ内で課金が機能するようにするには、アプリをストアに接続し、Adapty ダッシュボードでプロダクト、ペイウォール、プレースメントを作成する必要があります。[クイックスタートガイド](quickstart)では、必要なすべての手順を説明しています。 </Callout> ## Adapty SDK のインストール \{#install-adapty-sdk\} [![Release](https://img.shields.io/github/v/release/adaptyteam/AdaptySDK-Unity.svg?style=flat&logo=unity)](https://github.com/adaptyteam/AdaptySDK-Unity/releases) 1. GitHub から [`adapty-unity-plugin-*.unitypackage`](https://github.com/adaptyteam/AdaptySDK-Unity/tree/main/Releases) をダウンロードし、プロジェクトにインポートします。 <img src="/assets/shared/img/456bd98-adapty-unity-plugin.webp" style={{ border: 'none', /* border width and color */ width: '400px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. [External Dependency Manager プラグイン](https://github.com/googlesamples/unity-jar-resolver)をダウンロードしてインポートします。 3. SDK は「External Dependency Manager」プラグインを使用して iOS Cocoapods の依存関係と Android gradle の依存関係を管理します。インストール後、依存関係マネージャーを手動で実行する必要がある場合があります。 `Assets -> External Dependency Manager -> Android Resolver -> Force Resolve` および `Assets -> External Dependency Manager -> iOS Resolver -> Install Cocoapods` 4. Unity プロジェクトを iOS 向けにビルドすると `Unity-iPhone.xcworkspace` ファイルが生成されます。Cocoapods の依存関係を使用するために、`Unity-iPhone.xcodeproj` ではなく、この `Unity-iPhone.xcworkspace` を開いてください。 ## Adapty SDK の Adapty モジュールを有効化する \{#activate-adapty-module-of-adapty-sdk\} アプリのコードで Adapty SDK を有効化します。 :::note Adapty SDK はアプリ内で一度だけ有効化する必要があります。 ::: **Public SDK Key** を取得するには: 1. Adapty ダッシュボードを開き、[**App settings → General**](https://app.adapty.io/settings/general) に移動します。 2. **Api keys** セクションから **Public SDK Key**(Secret Key ではない方)をコピーします。 3. コード内の `"YOUR_PUBLIC_SDK_KEY"` を置き換えます。 :::important - Adapty の初期化には必ず **Public SDK key** を使用してください。**Secret key** は[サーバーサイド API](getting-started-with-server-side-api) 専用です。 - **SDK keys** はアプリごとに固有です。複数のアプリがある場合は、正しいキーを選択してください。 ::: ```csharp showLineNumbers title="C#" using UnityEngine; using AdaptySDK; public class AdaptyListener : MonoBehaviour, AdaptyEventListener { void Start() { DontDestroyOnLoad(this.gameObject); Adapty.SetEventListener(this); var builder = new AdaptyConfiguration.Builder("YOUR_PUBLIC_SDK_KEY"); Adapty.Activate(builder.Build(), (error) => { if (error != null) { // handle the error return; } }); } public void OnLoadLatestProfile(AdaptyProfile profile) { } public void OnInstallationDetailsSuccess(AdaptyInstallationDetails details) { } public void OnInstallationDetailsFail(AdaptyError error) { } } ``` :::important 他の Adapty SDK メソッドを呼び出す前に、`Activate` のコールバックが完了するまで待機してください。詳細な呼び出し順序については [Unity SDK の呼び出し順序](unity-sdk-call-order)を参照してください。 ::: ## イベントリスニングの設定 \{#set-up-event-listening\} Adapty のイベントを受け取るスクリプトを作成し、シーン内で `AdaptyListener` という名前を付けます。このオブジェクトにはアプリのライフサイクル全体を通じて持続させるため `DontDestroyOnLoad` メソッドの使用を推奨します。 <img src="/assets/shared/img/2ccd564-create_adapty_listener.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> Adapty は `AdaptySDK` 名前空間を使用します。Adapty SDK を使用するスクリプトファイルの先頭に以下を追加できます。 ```csharp showLineNumbers title="C#" using AdaptySDK; ``` Adapty のイベントを購読します。 ```csharp showLineNumbers title="C#" using UnityEngine; using AdaptySDK; public class AdaptyListener : MonoBehaviour, AdaptyEventListener { public void OnLoadLatestProfile(AdaptyProfile profile) { // handle updated profile data } public void OnInstallationDetailsSuccess(AdaptyInstallationDetails details) { } public void OnInstallationDetailsFail(AdaptyError error) { } } ``` Adapty ができるだけ早く初期化されるよう、スクリプト実行順序を調整して AdaptyListener をデフォルト時間より前に配置することをお勧めします。 <img src="/assets/shared/img/activate_unity.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## プロジェクトに Kotlin プラグインを追加する \{#add-kotlin-plugin-to-your-project\} :::warning この手順は必須です。スキップすると、ペイウォールの表示時にモバイルアプリがクラッシュする可能性があります。 ::: 1. **Player Settings** で、**Custom Launcher Gradle Template** と **Custom Base Gradle Template** のオプションが選択されていることを確認します。 <img src="/assets/shared/img/kotlin-plugin1.webp" style={{ border: 'none', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. `/Assets/Plugins/Android/launcherTemplate.gradle` に以下の行を追加します。 ```groovy showLineNumbers apply plugin: 'com.android.application' // highlight-next-line apply plugin: 'kotlin-android' apply from: 'setupSymbols.gradle' apply from: '../shared/keepUnitySymbols.gradle' ``` 3. `/Assets/Plugins/Android/baseProjectTemplate.gradle` に以下の行を追加します。 ```groovy showLineNumbers plugins { // If you are changing the Android Gradle Plugin version, make sure it is compatible with the Gradle version preinstalled with Unity // See which Gradle version is preinstalled with Unity here https://docs.unity3d.com/Manual/android-gradle-overview.html // See official Gradle and Android Gradle Plugin compatibility table here https://developer.android.com/studio/releases/gradle-plugin#updating-gradle // To specify a custom Gradle version in Unity, go do "Preferences > External Tools", uncheck "Gradle Installed with Unity (recommended)" and specify a path to a custom Gradle version id 'com.android.application' version '8.3.0' apply false id 'com.android.library' version '8.3.0' apply false // highlight-next-line id 'org.jetbrains.kotlin.android' version '1.8.0' apply false **BUILD_SCRIPT_DEPS** } ``` 次に、アプリのペイウォールを設定します。 - [Adapty ペイウォールビルダー](adapty-paywall-builder)を使用する場合は、まず以下の [AdaptyUI モジュールを有効化する](#activate-adaptyui-module-of-adapty-sdk)手順を完了してから、[ペイウォールビルダーのクイックスタート](unity-quickstart-paywalls)に従ってください。 - 独自のペイウォール UI を構築する場合は、[カスタムペイウォールのクイックスタート](unity-quickstart-manual)を参照してください。 ## Adapty SDK の AdaptyUI モジュールを有効化する \{#activate-adaptyui-module-of-adapty-sdk\} [ペイウォールビルダー](adapty-paywall-builder)を使用する予定があり、AdaptyUI モジュールをインストール済みの場合は、AdaptyUI を有効化する必要があります。設定時に有効化できます。 ```csharp showLineNumbers title="C#" var builder = new AdaptyConfiguration.Builder("YOUR_PUBLIC_SDK_KEY") .SetActivateUI(true); ``` ## オプション設定 \{#optional-setup\} ### ログ \{#logging\} #### ログシステムの設定 \{#set-up-the-logging-system\} Adapty は、何が起きているかを把握できるようにエラーやその他の重要な情報をログに記録します。以下のログレベルが利用可能です。 | レベル | 説明 | | ---------- | ----------------------------------------------------------------------------------------------------------- | | `error` | エラーのみ記録されます | | `warn` | エラーと、致命的なエラーではないものの注意が必要な SDK からのメッセージが記録されます | | `info` | エラー、警告、および各種情報メッセージが記録されます | | `verbose` | 関数呼び出し、API クエリなど、デバッグ中に役立つ可能性のある追加情報が記録されます | Adapty の設定時にアプリのログレベルを設定できます。 ```csharp showLineNumbers title="C#" // 'verbose' is recommended for development and the first production release var builder = new AdaptyConfiguration.Builder("YOUR_PUBLIC_SDK_KEY"); builder.LogLevel = AdaptyLogLevel.Verbose; ``` 実行時にログレベルを変更することもできます。 ```csharp showLineNumbers title="C#" Adapty.SetLogLevel(AdaptyLogLevel.Verbose, (error) => { // handle result }); ``` ### データポリシー \{#data-policies\} Adapty は明示的に送信しない限りユーザーの個人データを保存しませんが、ストアや国のガイドラインに準拠するための追加のデータセキュリティポリシーを実装できます。 #### IP アドレスの収集と共有を無効にする \{#disable-ip-address-collection-and-sharing\} Adapty モジュールを有効化する際に、`SetIPAddressCollectionDisabled` を `true` に設定すると、ユーザーの IP アドレスの収集と共有が無効になります。デフォルト値は `false` です。 このパラメータは、ユーザーのプライバシーを強化したり、GDPR や CCPA などの地域のデータ保護規制に準拠したり、IP ベースの機能がアプリに不要な場合に不要なデータ収集を減らすために使用してください。 ```csharp showLineNumbers title="C#" var builder = new AdaptyConfiguration.Builder("YOUR_PUBLIC_SDK_KEY") .SetIPAddressCollectionDisabled(true); ``` #### 広告 ID の収集と共有を無効にする \{#disable-advertising-id-collection-and-sharing\} Adapty モジュールを有効化する際に、`SetAppleIDFACollectionDisabled` および/または `SetGoogleAdvertisingIdCollectionDisabled` を `true` に設定すると、広告識別子の収集が無効になります。デフォルト値は `false` です。 このパラメータは、App Store / Google Play のポリシーに準拠したり、App Tracking Transparency プロンプトの表示を回避したり、アプリで広告 ID に基づくアトリビューションやアナリティクスが不要な場合に使用してください。 ```csharp showLineNumbers title="C#" var builder = new AdaptyConfiguration.Builder("YOUR_PUBLIC_SDK_KEY") .SetAppleIDFACollectionDisabled(true) .SetGoogleAdvertisingIdCollectionDisabled(true); ``` #### AdaptyUI のメディアキャッシュ設定を行う \{#set-up-media-cache-configuration-for-adaptyui\} デフォルトでは、AdaptyUI はパフォーマンスの向上とネットワーク使用量の削減のために画像や動画などのメディアをキャッシュします。カスタム設定を提供することでキャッシュの設定をカスタマイズできます。 `SetAdaptyUIMediaCache` を使用してデフォルトのキャッシュ設定を上書きします。 ```csharp showLineNumbers title="C#" var builder = new AdaptyConfiguration.Builder("YOUR_PUBLIC_SDK_KEY") .SetAdaptyUIMediaCache( 100 * 1024 * 1024, // MemoryStorageTotalCostLimit 100MB null, // MemoryStorageCountLimit 100 * 1024 * 1024 // DiskStorageSizeLimit 100MB ); ``` パラメータ: | パラメータ | 必須 | 説明 | |-----------------------------|----------|----------------------------------------------------------------------------------| | memoryStorageTotalCostLimit | 任意 | メモリ内の合計キャッシュサイズ(バイト)。プラットフォーム固有のデフォルト値を使用します。 | | memoryStorageCountLimit | 任意 | メモリストレージのアイテム数の上限。プラットフォーム固有のデフォルト値を使用します。 | | diskStorageSizeLimit | 任意 | ディスク上のファイルサイズの上限(バイト)。プラットフォーム固有のデフォルト値を使用します。 | ### ローカルアクセスレベルを有効にする(Android)\{#enable-local-access-levels-android\} デフォルトでは、[ローカルアクセスレベル](local-access-levels)は iOS で有効、Android で無効になっています。Android でも有効にするには、`SetGoogleLocalAccessLevelAllowed` を `true` に設定します。 ```csharp showLineNumbers title="C#" var builder = new AdaptyConfiguration.Builder("YOUR_PUBLIC_SDK_KEY") .SetGoogleLocalAccessLevelAllowed(true); ``` ### バックアップ復元時にデータを消去する \{#clear-data-on-backup-restore\} `SetAppleClearDataOnBackup` を `true` に設定すると、SDK はアプリが iCloud バックアップから復元されたことを検知し、キャッシュされたプロファイル情報、プロダクト詳細、ペイウォールを含むローカルに保存されたすべての SDK データを削除します。その後、SDK はクリーンな状態で初期化されます。デフォルト値は `false` です。 :::note 削除されるのはローカルの SDK キャッシュのみです。Apple とのトランザクション履歴および Adapty サーバー上のユーザーデータは変更されません。 ::: ```csharp showLineNumbers title="C#" var builder = new AdaptyConfiguration.Builder("YOUR_PUBLIC_SDK_KEY") .SetAppleClearDataOnBackup(true); ``` ## トラブルシューティング \{#troubleshooting\} #### Android バックアップルール(自動バックアップ設定)\{#android-backup-rules-auto-backup-configuration\} 一部のSDK(Adaptyを含む)には、独自のAndroid Auto Backup設定が含まれています。バックアップルールを定義する複数のSDKを使用している場合、Androidのマニフェストマージャーが `android:fullBackupContent`、`android:dataExtractionRules`、または `android:allowBackup` に関するエラーで失敗することがあります。 よくあるエラーの症状: `Manifest merger failed: Attribute application@dataExtractionRules value=(@xml/your_data_extraction_rules) is also present at [com.other.sdk:library:1.0.0] value=(@xml/other_sdk_data_extraction_rules)` :::note これらの変更は、Androidプラットフォームのディレクトリ(通常はプロジェクトの `android/` フォルダー内)で行う必要があります。 ::: この問題を解決するには、以下が必要です: - バックアップ関連の属性に対して、アプリの値を使用するようマニフェストマージャーに指示する。 - AdaptyのルールとほかのSDKのルールをマージしたバックアップルールファイルを作成する。 #### 1. マニフェストに `tools` 名前空間を追加する \{#1-add-the-tools-namespace-to-your-manifest\} `AndroidManifest.xml` ファイルのルートの `<manifest>` タグに tools が含まれていることを確認してください: ```xml <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="com.example.app"> ... </manifest> ``` #### 2. `<application>` でバックアップ属性を上書きする \{#2-override-backup-attributes-in-application\} 同じ `AndroidManifest.xml` ファイルで、`<application>` タグを更新して、アプリが最終的な値を提供し、マニフェストマージャーにライブラリの値を置き換えるよう指示します: ```xml <application android:name=".App" android:allowBackup="true" android:fullBackupContent="@xml/sample_backup_rules" android:dataExtractionRules="@xml/sample_data_extraction_rules" tools:replace="android:fullBackupContent,android:dataExtractionRules"> ... </application> ``` いずれかのSDKが `android:allowBackup` も設定している場合は、`tools:replace` に含めてください: ```xml tools:replace="android:allowBackup,android:fullBackupContent,android:dataExtractionRules" ``` #### 3. マージしたバックアップルールファイルを作成する \{#3-create-merged-backup-rules-files\} AndroidプロジェクトのAdaptyのルールとほかのSDKのルールを組み合わせた `res/xml/` ディレクトリにXMLファイルを作成します。AndroidはOSのバージョンによって異なるバックアップルール形式を使用するため、両方のファイルを作成することで、アプリがサポートするすべてのAndroidバージョンとの互換性が確保されます。 :::note 以下の例では、サンプルのサードパーティSDKとしてAppsFlyerを使用しています。アプリで使用しているほかのSDKのルールに置き換えるか、追加してください。 ::: **Android 12以降**(新しいデータ抽出ルール形式を使用): ```xml title="sample_data_extraction_rules.xml" <?xml version="1.0" encoding="utf-8"?> <data-extraction-rules> <cloud-backup> <exclude domain="sharedpref" path="appsflyer-data"/> <exclude domain="sharedpref" path="appsflyer-purchase-data"/> <exclude domain="database" path="afpurchases.db"/> <exclude domain="sharedpref" path="AdaptySDKPrefs.xml"/> </cloud-backup> <device-transfer> <exclude domain="sharedpref" path="appsflyer-data"/> <exclude domain="sharedpref" path="appsflyer-purchase-data"/> <exclude domain="database" path="afpurchases.db"/> <exclude domain="sharedpref" path="AdaptySDKPrefs.xml"/> </device-transfer> </data-extraction-rules> ``` **Android 11以前**(従来のフルバックアップコンテンツ形式を使用): ```xml title="sample_backup_rules.xml" <?xml version="1.0" encoding="utf-8"?> <full-backup-content> <exclude domain="sharedpref" path="appsflyer-data"/> <exclude domain="sharedpref" path="AdaptySDKPrefs.xml"/> :::important Unity では、これらの変更を `Assets/Plugins/Android/AndroidManifest.xml` に適用し、バックアップルールファイルを `Assets/Plugins/Android/res/xml/` 以下に作成してください。 ::: #### Android で別のアプリから戻った後に購入が失敗する \{#purchases-fail-after-returning-from-another-app-in-android\} 購入フローを開始する Activity が非デフォルトの `launchMode` を使用している場合、ユーザーが Google Play、銀行アプリ、またはブラウザから戻ったときに Android が Activity を誤って再作成または再利用する可能性があります。これにより、購入結果が失われたりキャンセルとして処理されたりすることがあります。 購入が正常に機能するよう、購入フローを開始する Activity には `standard` または `singleTop` の起動モードのみを使用し、他のモードは避けてください。 `AndroidManifest.xml` で、購入フローを開始する Activity が `standard` または `singleTop` に設定されていることを確認してください。 ```xml <activity android:name=".MainActivity" android:launchMode="standard" /> ``` --- # File: unity-quickstart-paywalls --- --- title: "Unity SDK のペイウォールを使って購入を有効にする" description: "Adapty SDK を使って Unity アプリでペイウォールを表示する方法を学ぶ" --- アプリ内課金を有効にするには、3 つの重要な概念を理解する必要があります。 - [**プロダクト**](product) – ユーザーが購入できるもの(サブスクリプション、消耗型アイテム、永続アクセスなど) - [**ペイウォール**](paywalls) – どのプロダクトを提供するかを定義する設定です。Adapty では、プロダクトの取得はペイウォールを通じてのみ行えます。この設計により、アプリのコードを変更せずにオファー内容、価格、プロダクトの組み合わせを変更できます。 - [**プレースメント**](placements) – アプリ内でペイウォールを表示する場所とタイミング(`main`、`onboarding`、`settings` など)。ダッシュボードでプレースメントに対してペイウォールを設定し、コード内でプレースメント ID を使ってリクエストします。これにより、A/B テストの実施や、ユーザーごとに異なるペイウォールの表示が容易になります。 Adapty では、アプリ内で購入を有効にする 3 つの方法を提供しています。アプリの要件に応じて選択してください。 | 実装方法 | 複雑さ | 使用場面 | |---------------------------|------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Adapty ペイウォールビルダー | ✅ 簡単 | [ノーコードビルダーで完全な購入対応ペイウォールを作成します](quickstart-paywalls)。Adapty が自動的にレンダリングし、複雑な購入フロー、レシート検証、サブスクリプション管理をすべて裏側で処理します。 | | 手動作成のペイウォール | 🟡 中程度 | ペイウォールの UI をアプリのコードで実装しますが、プロダクトオファーの柔軟性を保つため、Adapty からペイウォールオブジェクトを取得します。[ガイド](unity-quickstart-manual)を参照してください。 | | オブザーバーモード | 🔴 難しい | 独自の購入処理インフラを既に持っており、それを引き続き使用したい場合に選びます。オブザーバーモードには Adapty における制限があることに注意してください。[記事](observer-vs-full-mode)を参照してください。 | :::important **以下の手順は、Adapty ペイウォールビルダーで作成したペイウォールの実装方法を示しています。** ペイウォールビルダーを使用しない場合は、[手動作成ペイウォールでの購入処理ガイド](unity-making-purchases)を参照してください。 ::: Adapty ペイウォールビルダーで作成したペイウォールを表示するには、アプリのコードで以下の手順を実行するだけです。 1. **ペイウォールを取得する**: Adapty からペイウォールを取得します。 2. **ペイウォールを表示する(購入処理は Adapty が行います)**: 取得したペイウォールコンテナをアプリに表示します。 3. **ボタンアクションを処理する**: ペイウォール上のユーザー操作とアプリのレスポンスを紐付けます。たとえば、ユーザーがボタンをクリックしたときにリンクを開いたり、ペイウォールを閉じたりします。 ## 始める前に \{#before-you-start\} 始める前に、以下の手順を完了してください。 1. Adapty ダッシュボードでアプリを [App Store](initial_ios) および/または [Google Play](initial-android) に接続します。 2. Adapty で[プロダクトを作成します](create-product)。 3. [ペイウォールを作成してプロダクトを追加します](create-paywall)。 4. [プレースメントを作成してペイウォールを追加します](create-placement)。 5. アプリのコードに [Adapty SDK をインストールして有効化します](sdk-installation-unity)。 :::tip これらの手順を最短で完了するには、[クイックスタートガイド](quickstart)に従うか、[Developer CLI](developer-cli-quickstart) を使ってペイウォールとプレースメントを作成してください。 ::: ## 1. ペイウォールを取得する \{#1-get-the-paywall\} ペイウォールはダッシュボードで設定したプレースメントに紐付けられています。プレースメントを使うと、異なるオーディエンスに対して別々のペイウォールを表示したり、[A/B テスト](ab-tests)を実施したりできます。 Adapty ペイウォールビルダーで作成したペイウォールを取得するには、以下の手順を実行します。 1. `GetPaywall` メソッドを使って[プレースメント](placements) ID から `paywall` オブジェクトを取得し、`HasViewConfiguration` プロパティでビルダーで作成されたペイウォールかどうかを確認します。 2. `CreatePaywallView` メソッドを使ってペイウォールビューを作成します。このビューには、ペイウォールを表示するために必要な UI 要素とスタイルが含まれています。 :::important ビュー設定を取得するには、ペイウォールビルダーで **Show on device** トグルをオンにする必要があります。オフのままにすると、空のビュー設定が返され、ペイウォールが表示されません。 ::: ```csharp showLineNumbers Adapty.GetPaywall("YOUR_PLACEMENT_ID", (paywall, error) => { if(error != null) { // handle the error return; } // Create paywall view parameters var parameters = new AdaptyUICreatePaywallViewParameters(); // Create the paywall view AdaptyUI.CreatePaywallView(paywall, parameters, (view, error) => { if(error != null) { // handle the error return; } // view - the paywall view ready to be presented }); }); ``` :::info このクイックスタートはペイウォールを表示するための最小限の設定を提供しています。高度な設定の詳細については、[ペイウォールの取得に関するガイド](unity-get-pb-paywalls)を参照してください。 ::: ## 2. ペイウォールを表示する \{#2-display-the-paywall\} ペイウォール設定を取得したら、数行追加するだけでペイウォールを表示できます。 ペイウォールを表示するには、`CreatePaywallView` メソッドで作成した `view` に対して `view.Present()` メソッドを呼び出します。各 `view` は一度しか使用できません。ペイウォールを再度表示する必要がある場合は、`CreatePaywallView` をもう一度呼び出して新しい `view` インスタンスを作成してください。 ```csharp showLineNumbers title="Unity" view.Present((error) => { // handle the error }); ``` :::info ペイウォールの表示方法の詳細については、[ガイド](unity-present-paywalls)を参照してください。 ::: ## 3. ボタンアクションを処理する \{#3-handle-button-actions\} ユーザーがペイウォール内のボタンをクリックすると、Unity SDK が購入と復元を自動的に処理します。ただし、カスタムまたは事前定義された ID を持つその他のボタンについては、コードでアクションを処理する必要があります。 たとえば、ペイウォールには通常、閉じるボタンや開くべき URL(利用規約やプライバシーポリシーなど)があります。これらのアクションを処理するには、クラスが `AdaptyPaywallsEventsListener` インターフェースを実装し、リスナーとして登録する必要があります。 :::tip ボタンの[アクション](unity-handle-paywall-actions)と[イベント](unity-handling-events)の処理方法については、各ガイドを参照してください。 ::: ```csharp showLineNumbers title="Unity" public class YourClass : MonoBehaviour, AdaptyPaywallsEventsListener { void Start() { // Register this class as the paywall events listener Adapty.SetPaywallsEventsListener(this); } // AdaptyPaywallsEventsListener method - handles button actions public void PaywallViewDidPerformAction( AdaptyUIPaywallView view, AdaptyUIUserAction action ) { switch (action.Type) { case AdaptyUIUserActionType.Close: view.Dismiss(null); break; case AdaptyUIUserActionType.OpenUrl: Application.OpenURL(action.Value); break; default: break; } } } ``` ## 次のステップ \{#next-steps\} --- no_index: true --- import Callout from '../../../components/Callout.astro'; <Callout type="tip"> ご質問やお困りのことがあれば、[サポートフォーラム](https://adapty.featurebase.app/)をご覧ください。よくある質問への回答を見つけたり、ご自身の質問を投稿することができます。チームとコミュニティがサポートいたします! </Callout> ペイウォールをアプリに表示する準備が整いました。[App Store サンドボックス](test-purchases-in-sandbox)または [Google Play ストア](testing-on-android)でテスト購入を行い、ペイウォールからテスト購入を完了できることを確認してください。 次に、[ユーザーのアクセスレベルを確認し](unity-check-subscription-status)、適切なユーザーにペイウォールを表示したり、有料機能へのアクセスを付与したりできるようにする必要があります。 ## 完全な実装例 \{#full-example\} 以下は、すべての手順をアプリに統合した場合の例です。 ```csharp showLineNumbers using System; using UnityEngine; using AdaptySDK; public class PaywallManager : MonoBehaviour, AdaptyPaywallsEventsListener { [SerializeField] private string placementId = "YOUR_PLACEMENT_ID"; private AdaptyUIPaywallView currentPaywallView; void Start() { // Register for paywall events Adapty.SetPaywallsEventsListener(this); GetAndDisplayPaywall(); } private void GetAndDisplayPaywall() { Adapty.GetPaywall(placementId, (paywall, error) => { if (error != null) { Debug.LogError("Error getting paywall: " + error.Message); return; } if (paywall.HasViewConfiguration) { CreateAndPresentPaywallView(paywall); } else { Debug.LogWarning("Paywall was not created using the builder"); } }); } private void CreateAndPresentPaywallView(AdaptyPaywall paywall) { var parameters = new AdaptyUICreatePaywallViewParameters(); AdaptyUI.CreatePaywallView(paywall, parameters, (view, error) => { if (error != null) { Debug.LogError("Error creating paywall view: " + error.Message); return; } currentPaywallView = view; view.Present((presentError) => { if (presentError != null) { Debug.LogError("Error presenting paywall: " + presentError.Message); return; } Debug.Log("Paywall presented successfully"); }); }); } // AdaptyPaywallsEventsListener implementation public void PaywallViewDidPerformAction( AdaptyUIPaywallView view, AdaptyUIUserAction action ) { switch (action.Type) { case AdaptyUIUserActionType.Close: Debug.Log("Close button pressed"); view.Dismiss(null); break; case AdaptyUIUserActionType.OpenUrl: Application.OpenURL(action.Value); break; default: break; } } // Required interface methods (implement as needed) public void PaywallViewDidAppear(AdaptyUIPaywallView view) { } public void PaywallViewDidDisappear(AdaptyUIPaywallView view) { } public void PaywallViewDidSelectProduct(AdaptyUIPaywallView view, string productId) { } public void PaywallViewDidStartPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product) { } public void PaywallViewDidFinishPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product, AdaptyPurchaseResult purchasedResult) { } public void PaywallViewDidFailPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product, AdaptyError error) { } public void PaywallViewDidStartRestore(AdaptyUIPaywallView view) { } public void PaywallViewDidFinishRestore(AdaptyUIPaywallView view, AdaptyProfile profile) { } public void PaywallViewDidFailRestore(AdaptyUIPaywallView view, AdaptyError error) { } public void PaywallViewDidFailRendering(AdaptyUIPaywallView view, AdaptyError error) { } public void PaywallViewDidFailLoadingProducts(AdaptyUIPaywallView view, AdaptyError error) { } public void PaywallViewDidFinishWebPaymentNavigation(AdaptyUIPaywallView view, AdaptyPaywallProduct product, AdaptyError error) { } public void ShowPaywall() { GetAndDisplayPaywall(); } void OnDestroy() { if (currentPaywallView != null) { currentPaywallView.Dismiss(null); } } } ``` --- # File: unity-check-subscription-status --- --- title: "Unity SDKでサブスクリプションステータスを確認する" description: "AdaptyでUnityアプリのサブスクリプションステータスを確認する方法を学びます。" --- ユーザーが有料コンテンツにアクセスできるか、またはペイウォールを表示するかどうかを判断するには、プロファイル内の[アクセスレベル](access-level)を確認する必要があります。 この記事では、プロファイルの状態にアクセスして、ユーザーにペイウォールを表示するか有料機能へのアクセスを許可するかを判断する方法を説明します。 ## サブスクリプションステータスを取得する \{#get-subscription-status\} ユーザーにペイウォールを表示するか有料コンテンツを表示するかを判断する際は、プロファイル内の[アクセスレベル](access-level)を確認します。2つの方法があります: - アプリ起動時などに最新のプロファイルデータがすぐに必要な場合や、強制的に更新したい場合は `GetProfile` を呼び出します。 - サブスクリプションステータスが変わるたびに自動的に更新されるローカルコピーを保持するために、**プロファイルの自動更新**を設定します。 ### プロファイルを取得する \{#get-profile\} サブスクリプションステータスを取得するもっとも簡単な方法は、`GetProfile` メソッドを使ってプロファイルにアクセスすることです: ```csharp showLineNumbers Adapty.GetProfile((profile, error) => { if (error != null) { // handle the error return; } // check the access }); ``` ### サブスクリプションの更新を受け取る \{#listen-to-subscription-updates\} アプリでプロファイルの更新を自動的に受け取るには: 1. `AdaptyEventListener` を継承して `OnLoadLatestProfile` メソッドを実装します。ユーザーのサブスクリプションステータスが変わると、Adaptyが自動的にこのメソッドを呼び出します。 2. このメソッドが呼び出されたときに更新されたプロファイルデータを保存しておくと、追加のネットワークリクエストなしにアプリ全体で利用できます。 ```csharp public class SubscriptionManager : MonoBehaviour, AdaptyEventListener { private AdaptyProfile currentProfile; void Start() { // Register this object as an Adapty event listener Adapty.SetEventListener(this); } // Store the profile when it updates public void OnLoadLatestProfile(AdaptyProfile profile) { currentProfile = profile; // Update UI, unlock content, etc. } public void OnInstallationDetailsSuccess(AdaptyInstallationDetails details) { } public void OnInstallationDetailsFail(AdaptyError error) { } // Use stored profile instead of calling getProfile() public bool HasAccess() { if (currentProfile?.AccessLevels != null && currentProfile.AccessLevels.ContainsKey("premium")) { return currentProfile.AccessLevels["premium"].IsActive; } return false; } } ``` :::note Adaptyはアプリ起動時に自動的に `OnLoadLatestProfile` を呼び出し、デバイスがオフラインでもキャッシュされたサブスクリプションデータを提供します。 ::: ## プロファイルとペイウォールロジックを連携させる \{#connect-profile-with-paywall-logic\} ペイウォールの表示や有料機能へのアクセス許可をすぐに判断したい場合は、ユーザーのプロファイルを直接確認できます。この方法は、アプリ起動時、プレミアムセクションに入るとき、特定のコンテンツを表示する前など、さまざまなシナリオで役立ちます。 ```csharp private void CheckAccessLevel() { Adapty.GetProfile((profile, error) => { if (error != null) { Debug.LogError("Error checking access level: " + error.Message); // Show paywall if access check fails return; } var accessLevel = profile.AccessLevels["YOUR_ACCESS_LEVEL"]; if (accessLevel == null || !accessLevel.IsActive) { // Show paywall if no access } }); } private void InitializePaywall() { LoadPaywall(); CheckAccessLevel(); } ``` ## 次のステップ \{#next-steps\} サブスクリプションステータスの追跡方法を確認したら、次は[ユーザープロファイルの操作](unity-quickstart-identify)を学んで、ユーザーが購入したものにアクセスできるようにしましょう。 --- # File: unity-quickstart-identify --- --- title: "Unity SDKでユーザーを識別する" description: "UnityでのアプリNの課金管理のためのAdaptyセットアップクイックスタートガイド。" --- :::important このガイドは、独自の認証システムをお持ちの方向けです。ここでは、既存の認証システムと連携するために、Adaptyのユーザープロファイルをどのように扱うかを説明します。 ::: ユーザーの購入管理の方法は、アプリの認証モデルによって異なります。 - アプリがバックエンド認証を使用せず、ユーザーデータを保存しない場合は、[匿名ユーザーのセクション](#anonymous-users)をご覧ください。 - アプリにバックエンド認証がある(または予定している)場合は、[識別済みユーザーのセクション](#identified-users)をご覧ください。 **主要な概念**: - **プロファイル**はSDKが動作するために必要なエンティティです。Adaptyが自動的に作成します。 - 匿名(**カスタマーユーザーIDなし**)または識別済み(**カスタマーユーザーIDあり**)のいずれかになります。 - **カスタマーユーザーID**を提供することで、Adaptyのプロファイルと内部認証システムを相互参照できます。 匿名ユーザーと識別済みユーザーの違いは次のとおりです。 | | 匿名ユーザー | 識別済みユーザー | |-------------------------|---------------------------------------------------|-------------------------------------------------------------------------| | **購入管理** | ストアレベルの購入復元 | カスタマーユーザーIDを通じてデバイス間で購入履歴を維持 | | **プロファイル管理** | 再インストールのたびに新しいプロファイルが作成される | セッションやデバイスをまたいで同じプロファイルを使用 | | **データの永続性** | 匿名ユーザーのデータはアプリのインストールに紐付けられる | 識別済みユーザーのデータはアプリのインストールをまたいで保持される | ## 匿名ユーザー \{#anonymous-users\} バックエンド認証を使用しない場合、**アプリコードで認証を処理する必要はありません**。 1. アプリの初回起動時にSDKがアクティベートされると、Adaptyは**そのユーザーの新しいプロファイルを作成**します。 2. ユーザーがアプリ内で何かを購入すると、その購入は**Adaptyプロファイルとストアアカウントに関連付け**られます。 3. ユーザーがアプリを**再インストール**したり、**新しいデバイス**にインストールしたりすると、Adaptyはアクティベーション時に**新しい匿名プロファイルを作成**します。 4. ユーザーが以前にアプリで購入していた場合、デフォルトではSDKのアクティベーション時にApp Storeから購入履歴が自動的に同期されます。 匿名ユーザーの場合、インストールのたびに新しいプロファイルが作成されますが、Adaptyのアナリティクスでは[新規インストールとして見なす基準を設定](general#4-installs-definition-for-analytics)できるため、問題はありません。 匿名ユーザーの場合、**デバイスID**でインストールをカウントする必要があります。この場合、再インストールを含む、デバイスへのアプリインストールのたびにインストールとしてカウントされます。 ## 識別済みユーザー \{#identified-users\} アプリでユーザーを識別するには、2つの方法があります。 - [**ログイン/サインアップ時:**](#during-loginsignup) アプリ起動後にユーザーがサインインする場合、認証時に`identify()`をカスタマーユーザーIDとともに呼び出します。 - [**SDKアクティベーション時:**](#during-the-sdk-activation) アプリ起動時にすでにカスタマーユーザーIDが保存されている場合は、`activate()`の呼び出し時に渡します。 :::important デフォルトでは、Adaptyが現在別のカスタマーユーザーIDに関連付けられているカスタマーユーザーIDからの購入を受け取った場合、アクセスレベルは共有されるため、両方のプロファイルが有料アクセスを持ちます。この設定を変更して、有料アクセスを一方のプロファイルから他方に移譲したり、共有を完全に無効にしたりすることができます。詳細は[こちらの記事](general#6-sharing-paid-access-between-user-accounts)をご覧ください。 ::: <img src="/assets/shared/img/identify-diagram.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ### ログイン/サインアップ時 \{#during-loginsignup\} アプリ起動後にユーザーを識別する場合(例:アプリへのログイン後やサインアップ後)、`identify`メソッドを使用してカスタマーユーザーIDを設定します。 - **このカスタマーユーザーIDを以前に使用したことがない**場合、Adaptyは自動的に現在のプロファイルに紐付けます。 - **このカスタマーユーザーIDでユーザーを以前に識別したことがある**場合、AdaptyはそのカスタマーユーザーIDに関連付けられたプロファイルに切り替えて処理を行います。 :::important カスタマーユーザーIDは各ユーザーで一意である必要があります。パラメータ値をハードコードすると、すべてのユーザーが同一人物として扱われます。 ::: 他のSDKメソッドを呼び出す前に、`Identify`の完了コールバックを待ってください。同時に呼び出すと`#3006 profileWasChanged`が発生するか、匿名プロファイルに対して処理が行われます。詳細は[Unity SDKの呼び出し順序](unity-sdk-call-order)をご覧ください。 ```csharp showLineNumbers Adapty.Identify("YOUR_USER_ID", (error) => { // Unique for each user if(error == null) { // successful identify } }); ``` ### SDKアクティベーション時 \{#during-the-sdk-activation\} SDKをアクティベートする際にすでにカスタマーユーザーIDがわかっている場合は、`identify`を別途呼び出す代わりに、`activate`メソッドに渡すことができます。 カスタマーユーザーIDがわかっているのにアクティベーション後にのみ設定する場合、アクティベーション時にAdaptyが新しい匿名プロファイルを作成し、`identify`を呼び出した後にのみ既存のプロファイルに切り替わります。 既存のカスタマーユーザーID(以前に使用したもの)または新しいものを渡すことができます。新しいものを渡すと、アクティベーション時に作成された新しいプロファイルが自動的にそのカスタマーユーザーIDに紐付けられます。 :::note デフォルトでは、匿名プロファイルの作成はアナリティクスダッシュボードに影響しません。インストールはデバイスIDに基づいてカウントされるためです。 デバイスIDはデバイスへのアプリのストアからの単一インストールを表し、アプリの再インストール後にのみ再生成されます。 初回インストールか再インストールか、または既存のカスタマーユーザーIDが使用されているかどうかには依存しません。 プロファイルの作成(SDKのアクティベーション時またはログアウト時)、ログイン、またはアプリの再インストールなしのアップグレードは、追加のインストールイベントを生成しません。 デバイスではなく一意のユーザーに基づいてインストールをカウントしたい場合は、**App settings**に移動して[**Installs definition for analytics**](general#4-installs-definition-for-analytics)を設定してください。 ::: ```csharp showLineNumbers using UnityEngine; using AdaptySDK; var builder = new AdaptyConfiguration.Builder("YOUR_API_KEY") .SetCustomerUserId("YOUR_USER_ID"); // Customer user IDs must be unique for each user. If you hardcode the parameter value, all users will be considered as one. Adapty.Activate(builder.Build(), (error) => { if (error != null) { // handle the error return; } }); ``` ### ユーザーをログアウトする \{#log-users-out\} ユーザーをログアウトさせるボタンがある場合は、`logout`メソッドを使用します。 :::important ユーザーをログアウトすると、そのユーザーの新しい匿名プロファイルが作成されます。 ::: ```csharp showLineNumbers Adapty.Logout((error) => { if(error == null) { // successful logout } }); ``` :::info ユーザーをアプリに再度ログインさせるには、`identify`メソッドを使用します。 ::: ### ログインなしでの購入を許可する \{#allow-purchases-without-login\} ユーザーがアプリへのログイン前後の両方で購入できる場合、ログイン後もアクセスが維持されるよう対応が必要です。 1. ログアウト状態のユーザーが購入すると、AdaptyはそれをそのユーザーのアノニマスプロファイルIDに紐付けます。 2. ユーザーがアカウントにログインすると、Adaptyはその識別済みプロファイルへの処理に切り替えます。 - 新しいカスタマーユーザーIDの場合(例:登録前に購入が行われた場合)、Adaptyはカスタマーユーザーをを現在のプロファイルに割り当てるため、すべての購入履歴が維持されます。 - 既存のカスタマーユーザーIDの場合(カスタマーユーザーIDがすでにプロファイルに紐付けられている場合)、プロファイルの切り替え後に実際のアクセスレベルを取得する必要があります。識別後すぐに[`getProfile`](unity-check-subscription-status)を呼び出すか、[プロファイルの更新をリッスン](unity-check-subscription-status)してデータを自動的に同期させることができます。 ## 次のステップ \{#next-steps\} おめでとうございます!アプリにアプリ内課金のロジックを実装できました!アプリの収益化がうまくいくことを願っています! Adaptyをさらに活用するために、以下のトピックも探ってみてください。 - [**テスト**](troubleshooting-test-purchases): すべてが期待どおりに動作することを確認する - [**オンボーディング**](onboardings): オンボーディングでユーザーを引き込み、継続率を高める - [**インテグレーション**](configuration): マーケティングアトリビューションや分析サービスをたった1行のコードで統合する - [**カスタムプロファイル属性を設定する**](unity-setting-user-attributes): ユーザープロファイルにカスタム属性を追加してセグメントを作成し、A/B テストを実施したり、異なるユーザーに異なるペイウォールを表示したりする --- # File: adapty-sdk-integration-skill-unity --- --- title: "SDKインテグレーションスキルを使ってAdaptyをUnityアプリに統合する" description: "adapty-sdk-integrationスキルを使用して、AIコーディングツールでAdapty SDKをUnityアプリにエンドツーエンドで統合します。" --- :::important このスキルはベータ版です。スキルが途中で止まったり予期しない動作をする場合は、代わりに[ステップバイステップの統合ガイド](adapty-cursor-unity)を参照してください。AIツールが各ステージを適切なドキュメントとともに順を追って進められるようになっています。 ::: --- no_index: true --- [adapty-sdk-integration スキル](https://github.com/adaptyteam/adapty-sdk-integration-skill)は、Adapty のインテグレーションをエンドツーエンドで自動化します。ダッシュボードのセットアップ、SDK のインストール、ペイウォール、各ステージの検証まで対応しています。プラットフォームを自動検出し、各ステージで関連する Adapty ドキュメントを取得します。 **対応ツール**: Claude Code、GitHub Copilot CLI、OpenAI Codex、Gemini CLI。 インストールするには、お使いのツール向けのフォームを選択してください。完全なリストは[スキルの README](https://github.com/adaptyteam/adapty-sdk-integration-skill) をご覧ください。 **Claude Code** ``` claude plugin marketplace add adaptyteam/adapty-sdk-integration-skill claude plugin install adapty-sdk-integration@adapty ``` **GitHub Copilot CLI** ``` gh skill install adaptyteam/adapty-sdk-integration-skill ``` **Gemini CLI** ``` gemini skills install https://github.com/adaptyteam/adapty-sdk-integration-skill ``` **OpenAI Codex またはその他のツール**: リポジトリをクローンし、`plugins/adapty-sdk-integration/skills/adapty-sdk-integration/` をツールのスキルディレクトリにコピーしてください。 インストール後、プロジェクト内でスキルを実行します: ``` /adapty-sdk-integration ``` スキルがいくつかのセットアップ質問を行い、その後ダッシュボードのセットアップ、SDK のインストール、ペイウォール、検証の手順を案内します。 --- # File: adapty-cursor-unity --- --- title: "AIアシスタンスを使ってUnityアプリにAdaptyを統合する" description: "Cursor、Context7、ChatGPT、Claude、その他のAIツールを使用して、UnityアプリにAdaptyを統合するためのステップバイステップガイド。" --- このガイドでは、AIコーディングツールを使ってUnityアプリにAdaptyを段階的に統合する手順を説明します。適切なAdaptyドキュメントを正しい順序でAIに提供することがポイントです。 For a fully automated integration, use the [adapty-sdk-integration skill](https://github.com/adaptyteam/adapty-sdk-integration-skill): it runs the whole integration from your AI coding tool in one command. ## 始める前に:ダッシュボードの設定 \{#before-you-start-dashboard-setup\} AdaptyはSDKコードを書く前に、ダッシュボードでの設定が必要です。インタラクティブなLLMスキルを使うか、ダッシュボードから手動で設定できます。 ### スキルを使うアプローチ(推奨) \{#skill-approach-recommended\} Adapty CLIスキルを使うと、LLMがアプリ、プロダクト、アクセスレベル、ペイウォール、プレースメントを直接設定できます。ダッシュボードを都度開く必要がなく、[ストアの接続](integrate-payments)だけダッシュボードで行えば大丈夫です。 ``` npx skills add adaptyteam/adapty-cli --skill adapty-cli ``` スキルを追加したら、エージェントで `/adapty-cli` を実行してください。各ステップをガイドしてくれます。ストアの接続が必要なタイミングも案内してくれます。 ### ダッシュボードを使うアプローチ \{#dashboard-approach\} すべてを手動で設定したい場合は、コードを書く前に以下の準備が必要です。ダッシュボードの値はLLMが調べることができないため、ご自身で用意してください。 1. **アプリストアを接続する**: Adapty ダッシュボードで **App settings → General** に移動し、UnityアプリがiOSとAndroid両方を対象としている場合はApp StoreとGoogle Playの両方を接続してください。購入機能を動作させるために必須です。 [アプリストアを接続する](integrate-payments) 2. **Public SDKキーをコピーする**: Adapty ダッシュボードで **App settings → General** に移動し、**API keys** セクションを見つけてください。コード上ではAdaptyの設定ビルダーに渡す文字列として使用します。 3. **プロダクトを少なくとも1つ作成する**: Adapty ダッシュボードで **Products** ページに移動してください。プロダクトはコードから直接参照しません。Adaptyはペイウォールを通じてプロダクトを配信します。 [プロダクトを追加する](quickstart-products) 4. **ペイウォールとプレースメントを作成する**: Adapty ダッシュボードの **Paywalls** ページでペイウォールを作成し、**Placements** ページでプレースメントに割り当てます。コードでは、プレースメントIDが `Adapty.GetPaywall("YOUR_PLACEMENT_ID")` に渡す文字列になります。 [ペイウォールを作成する](quickstart-paywalls) 5. **アクセスレベルを設定する**: Adapty ダッシュボードの **Products** ページでプロダクトごとに設定します。コードでは `profile.AccessLevels["premium"]?.IsActive` で確認する文字列です。デフォルトの `premium` アクセスレベルはほとんどのアプリで機能します。プロダクトによって異なる機能へのアクセス権を付与する場合(例:`basic` プランと `pro` プラン)は、コーディングを始める前に[追加のアクセスレベルを作成](assigning-access-level-to-a-product)してください。 :::tip 5つすべて揃ったら、コードを書く準備完了です。LLMに「Public SDKキーはX、プレースメントIDはY」と伝えると、正確な初期化コードとペイウォール取得コードを生成してもらえます。 ::: ### 準備ができたら設定する \{#set-up-when-ready\} コーディングを始めるにあたって必須ではありませんが、統合が成熟するにつれて必要になります: - **A/B テスト**: **Placements** ページで設定します。コードの変更は不要です。 [A/B テスト](ab-tests) - **追加のペイウォールとプレースメント**: 異なるプレースメントIDで `GetPaywall` の呼び出しを追加します。 - **アナリティクス統合**: **Integrations** ページで設定します。統合によって設定方法が異なります。[アナリティクス統合](analytics-integration)と[アトリビューション統合](attribution-integration)を参照してください。 ## AdaptyドキュメントをLLMに提供する \{#feed-adapty-docs-to-your-llm\} ### Context7を使う(推奨) \{#use-context7-recommended\} [Context7](https://context7.com)は、LLMが最新のAdaptyドキュメントに直接アクセスできるMCPサーバーです。質問の内容に基づいて適切なドキュメントを自動的に取得するため、URLを手動で貼り付ける必要がありません。 Context7は**Cursor**、**Claude Code**、**Windsurf**、その他のMCP対応ツールで使用できます。セットアップするには以下を実行してください: ``` npx ctx7 setup ``` エディタを自動検出してContext7サーバーを設定します。手動設定については[Context7 GitHubリポジトリ](https://github.com/upstash/context7)を参照してください。 設定が完了したら、プロンプトでAdaptyライブラリを参照してください: ``` Use the adaptyteam/adapty-docs library to look up how to install the Unity SDK ``` :::warning Context7を使うとドキュメントのリンクを手動で貼り付ける必要がなくなりますが、実装の順序は重要です。すべてが正しく動作するよう、以下の[実装ウォークスルー](#implementation-walkthrough)をステップ順に進めてください。 ::: ### プレーンテキストのドキュメントを使う \{#use-plain-text-docs\} AdaptyのドキュメントはプレーンテキストのMarkdownとしてアクセスできます。URLの末尾に `.md` を追加するか、記事タイトルの下にある **Copy for LLM** をクリックしてください。例:[adapty-cursor-unity.md](https://adapty.io/docs/ja/adapty-cursor-unity.md)。 以下の[実装ウォークスルー](#implementation-walkthrough)の各ステージには、貼り付け用の `.md` リンクを含む「LLMに送信するもの」ブロックが含まれています。 より多くのドキュメントが必要な場合は、以下の[インデックスファイルとプラットフォーム別サブセット](#plain-text-doc-index-files)を参照してください。 ## 実装ウォークスルー \{#implementation-walkthrough\} このガイドの残りの部分では、実装の順序でAdapty統合を進めていきます。各ステージにはLLMに送るドキュメント、完了時の確認事項、よくある問題が含まれています。 ### 統合の計画を立てる \{#plan-your-integration\} コードを書き始める前に、LLMにプロジェクトを分析させて実装計画を立ててもらいましょう。AIツールがプランニングモードをサポートしている場合(CursorやClaude Codeのプランモードなど)、コードを書く前にLLMがプロジェクト構造とAdaptyドキュメントの両方を読めるよう、それを使用してください。 購入に使用するアプローチをLLMに伝えてください。これによって参照すべきガイドが変わります: - [**Adapty ペイウォールビルダー**](adapty-paywall-builder): Adaptyのノーコードビルダーでペイウォールを作成し、SDKが自動的にレンダリングします。 - [**手動で作成したペイウォール**](unity-making-purchases): コードで独自のペイウォールUIを構築しますが、プロダクトの取得と購入処理にはAdaptyを使用します。 - [**オブザーバーモード**](observer-vs-full-mode): 既存の購入インフラを維持し、アナリティクスと統合のみにAdaptyを使用します。 どれを選べばいいか迷っていますか?[クイックスタートの比較表](unity-quickstart-paywalls)を読んでください。 ### SDKをインストールして設定する \{#install-and-configure-the-sdk\} Unity Package ManagerでAdapty SDKパッケージを追加し、Public SDKキーで有効化します。これが基盤となり、他のすべての機能はこれなしでは動作しません。 **ガイド:** [Adapty SDKをインストールして設定する](sdk-installation-unity) LLMに送信するもの: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/sdk-installation-unity.md ``` :::tip[チェックポイント] - **期待される結果:** プロジェクトがビルドされ実行されます。UnityコンソールにAdaptyのアクティベーションログが表示されます。 - **注意点:** 「Public API key is missing」→ プレースホルダーをApp settingsの実際のキーに置き換えたか確認してください。 ::: ### ペイウォールを表示して購入を処理する \{#show-paywalls-and-handle-purchases\} プレースメントIDでペイウォールを取得し、表示して、購入イベントを処理します。必要なガイドは購入の処理方法によって異なります。 進めながらサンドボックスで各購入をテストしてください。最後まで待たないようにしましょう。設定手順については[サンドボックスで購入をテストする](test-purchases-in-sandbox)を参照してください。 <Tabs groupId="paywall-approach"> <TabItem value="builder" label="Paywall Builder" default> **ガイド:** - [ペイウォールを使って購入を有効にする(クイックスタート)](unity-quickstart-paywalls) - [ペイウォールビルダーのペイウォールと設定を取得する](unity-get-pb-paywalls) - [ペイウォールを表示する](unity-present-paywalls) - [ペイウォールイベントを処理する](unity-handling-events) - [ボタンアクションに応答する](unity-handle-paywall-actions) LLMに送信するもの: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/unity-quickstart-paywalls.md - https://adapty.io/docs/ja/unity-get-pb-paywalls.md - https://adapty.io/docs/ja/unity-present-paywalls.md - https://adapty.io/docs/ja/unity-handling-events.md - https://adapty.io/docs/ja/unity-handle-paywall-actions.md ``` :::tip[チェックポイント] - **期待される結果:** 設定したプロダクトとともにペイウォールが表示されます。プロダクトをタップするとサンドボックスの購入ダイアログが表示されます。 - **注意点:** ペイウォールが空または `GetPaywall` エラー → プレースメントIDがダッシュボードと完全に一致しているか、またプレースメントにオーディエンスが割り当てられているか確認してください。 ::: </TabItem> <TabItem value="manual" label="Manual paywalls"> **ガイド:** - [カスタムペイウォールで購入を有効にする(クイックスタート)](unity-quickstart-manual) - [ペイウォールとプロダクトを取得する](fetch-paywalls-and-products-unity) - [リモートコンフィグで設計されたペイウォールをレンダリングする](present-remote-config-paywalls-unity) - [購入を行う](unity-making-purchases) - [購入を復元する](unity-restore-purchase) LLMに送信するもの: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/unity-quickstart-manual.md - https://adapty.io/docs/ja/fetch-paywalls-and-products-unity.md - https://adapty.io/docs/ja/present-remote-config-paywalls-unity.md - https://adapty.io/docs/ja/unity-making-purchases.md - https://adapty.io/docs/ja/unity-restore-purchase.md ``` :::tip[チェックポイント] - **期待される結果:** カスタムペイウォールにAdaptyから取得したプロダクトが表示されます。プロダクトをタップするとサンドボックスの購入ダイアログが表示されます。 - **注意点:** プロダクト配列が空 → ダッシュボードでペイウォールにプロダクトが割り当てられているか、またプレースメントにオーディエンスが設定されているか確認してください。 ::: </TabItem> <TabItem value="observer" label="Observer mode"> **ガイド:** - [オブザーバーモードの概要](observer-vs-full-mode) - [オブザーバーモードを実装する](implement-observer-mode-unity) - [オブザーバーモードでトランザクションを報告する](report-transactions-observer-mode-unity) LLMに送信するもの: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/observer-vs-full-mode.md - https://adapty.io/docs/ja/implement-observer-mode-unity.md - https://adapty.io/docs/ja/report-transactions-observer-mode-unity.md ``` :::tip[チェックポイント] - **期待される結果:** 既存の購入フローでサンドボックス購入を行った後、Adapty ダッシュボードの **Event Feed** にトランザクションが表示されます。 - **注意点:** イベントが表示されない → トランザクションをAdaptyに報告しているか確認し、両ストアのサーバー通知が設定されているか確認してください。 ::: </TabItem> </Tabs> ### サブスクリプションのステータスを確認する \{#check-subscription-status\} 購入後、ユーザープロファイルのアクティブなアクセスレベルを確認してプレミアムコンテンツへのアクセスを制御します。 **ガイド:** [サブスクリプションのステータスを確認する](unity-check-subscription-status) LLMに送信するもの: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/unity-check-subscription-status.md ``` :::tip[チェックポイント] - **期待される結果:** サンドボックスで購入した後、`profile.AccessLevels["premium"]?.IsActive` が `true` を返します。 - **注意点:** 購入後に `AccessLevels` が空 → ダッシュボードでプロダクトにアクセスレベルが割り当てられているか確認してください。 ::: ### ユーザーを識別する \{#identify-users\} アプリのユーザーアカウントをAdaptyプロファイルに紐付けて、デバイスをまたいで購入情報が保持されるようにします。 :::important アプリに認証機能がない場合はこのステップをスキップしてください。 ::: **ガイド:** [ユーザーを識別する](unity-quickstart-identify) LLMに送信するもの: ``` Read these Adapty docs before writing code: - https://adapty.io/docs/ja/unity-quickstart-identify.md ``` :::tip[チェックポイント] - **期待される結果:** `Adapty.Identify("your-user-id")` を呼び出した後、ダッシュボードの **Profiles** セクションにカスタムユーザーIDが表示されます。 - **注意点:** 匿名プロファイルのアトリビューションを防ぐため、`Identify` はアクティベーション後、ペイウォール取得前に呼び出してください。 ::: ### リリースの準備をする \{#prepare-for-release\} サンドボックスで統合が正常に動作したら、リリースチェックリストを確認してすべてが本番環境に対応しているか確認します。 **ガイド:** [リリースチェックリスト](release-checklist) LLMに送信するもの: ``` Read these Adapty docs before releasing: - https://adapty.io/docs/ja/release-checklist.md ``` :::tip[チェックポイント] - **期待される結果:** すべてのチェックリスト項目が確認済み:ストア接続、サーバー通知、購入フロー、アクセスレベルの確認、プライバシー要件。 - **注意点:** サーバー通知が未設定 → **App settings → iOS SDK** でApp Store Server Notificationsを設定し、**App settings → Android SDK** でGoogle Play Real-Time Developer Notificationsを設定してください。 ::: ## プレーンテキストのドキュメントインデックスファイル \{#plain-text-doc-index-files\} 個々のページを超えてLLMにより広いコンテキストを提供する必要がある場合、すべてのAdaptyドキュメントをリストアップまたは結合したインデックスファイルを提供しています: - [`llms.txt`](https://adapty.io/docs/ja/llms.txt): `.md` リンク付きで全ページをリスト表示します。LLMがウェブサイトにアクセスできるようにするための[新興標準](https://llmstxt.org/)です。一部のAIエージェント(例:ChatGPT)では、`llms.txt` をダウンロードしてチャットにファイルとしてアップロードする必要があります。 - [`llms-full.txt`](https://adapty.io/docs/ja/llms-full.txt): Adaptyドキュメントサイト全体を1つのファイルにまとめたものです。非常に大きなファイルのため、全体像が必要な場合のみ使用してください。 - Unity専用の [`unity-llms.txt`](https://adapty.io/docs/ja/unity-llms.txt) と [`unity-llms-full.txt`](https://adapty.io/docs/ja/unity-llms-full.txt): サイト全体と比べてトークンを節約できるプラットフォーム別サブセットです。 --- # File: unity-get-pb-paywalls --- --- title: "Unity SDKでペイウォールビルダーのペイウォールと設定を取得する" description: "Adaptyでペイウォールビルダーのペイウォールを取得し、Unityアプリのサブスクリプション管理を改善する方法を学びます。" --- Adapty ダッシュボードの新しいペイウォールビルダーで[ペイウォールのビジュアルを設計](adapty-paywall-builder)したら、モバイルアプリに表示できます。まずは、プレースメントに関連付けられたペイウォールとそのビュー設定を取得する必要があります。 :::warning 新しいペイウォールビルダーは Unity SDK バージョン 3.3.0 以降で動作します。 ::: このトピックはペイウォールビルダーでカスタマイズされたペイウォールに関するものです。ペイウォールを手動で実装する場合は、[モバイルアプリでリモートコンフィグペイウォールのペイウォールとプロダクトを取得する](fetch-paywalls-and-products-unity)をご参照ください。 :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: <details> <summary>モバイルアプリでペイウォールを表示する前に(クリックして展開)</summary> 1. Adapty ダッシュボードで[プロダクトを作成](create-product)します。 2. Adapty ダッシュボードで[ペイウォールを作成し、プロダクトを追加](create-paywall)します。 3. Adapty ダッシュボードで[プレースメントを作成し、ペイウォールを追加](create-placement)します。 4. モバイルアプリに [Adapty SDK](sdk-installation-unity) をインストールします。 </details> ## ペイウォールビルダーで設計したペイウォールを取得する \{#fetch-paywall-designed-with-paywall-builder\} [ペイウォールビルダーでペイウォールを設計](adapty-paywall-builder)した場合、ユーザーに表示するためにモバイルアプリのコードでレンダリング処理を書く必要はありません。このようなペイウォールには、表示内容と表示方法の両方が含まれています。ただし、プレースメントからペイウォールのIDを取得し、ビュー設定を取得してからモバイルアプリに表示する必要があります。 最適なパフォーマンスを確保するために、ペイウォールと[ビュー設定](unity-get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder)はできるだけ早く取得し、ユーザーに表示する前に画像のダウンロードに十分な時間を確保することが重要です。 ペイウォールを取得するには、`GetPaywall` メソッドを使用します: ```csharp showLineNumbers Adapty.GetPaywall("YOUR_PLACEMENT_ID", "en", (paywall, error) => { if(error != null) { // handle the error return; } // paywall - the resulting object }); ``` パラメーター: | パラメーター | 必須/任意 | 説明 | |---------|--------|-----------| | **placementId** | 必須 | 対象の[プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** | <p>任意</p><p>デフォルト: `en`</p> | <p>[ペイウォールのローカライズ](add-paywall-locale-in-adapty-paywall-builder)の識別子。マイナス(**-**)文字で区切られた1つまたは2つのサブタグからなる言語コードを指定します。最初のサブタグは言語、2番目は地域を表します。</p><p></p><p>例:`en` は英語、`pt-br` はブラジルポルトガル語を表します。</p><p>ロケールコードと推奨される使用方法については、[ローカライズとロケールコード](localizations-and-locale-codes)を参照してください。</p> | | **fetchPolicy** | デフォルト: `.reloadRevalidatingCacheData` | <p>デフォルトでは、SDKはサーバーからデータの読み込みを試み、失敗した場合はキャッシュされたデータを返します。ユーザーが常に最新のデータを取得できるため、このオプションを推奨します。</p><p></p><p>ただし、ユーザーの接続が不安定な場合は、`.returnCacheDataElseLoad` を使用してキャッシュデータが存在する場合はそれを返すことを検討してください。この場合、最新のデータが得られないことがありますが、接続状況にかかわらず読み込み時間が短縮されます。キャッシュは定期的に更新されるため、セッション中にネットワークリクエストを避けるために使用しても安全です。</p><p></p><p>キャッシュはアプリの再起動後も保持され、アプリの再インストールまたは手動クリーンアップ時にのみクリアされます。</p><p></p><p>Adapty SDK はペイウォールをローカルに2層で保存します:上述の定期更新キャッシュと[フォールバックペイウォール](fallback-paywalls)です。また、CDNを使用してペイウォールをより高速に取得し、CDNが利用できない場合のためにスタンドアロンのフォールバックサーバーも用意しています。このシステムは、インターネット接続が不安定な場合でも常に最新バージョンのペイウォールを取得できるよう設計されています。</p> | | **loadTimeout** | デフォルト: 5秒 | <p>このメソッドのタイムアウトを制限する値です。タイムアウトに達した場合、キャッシュデータまたはローカルフォールバックが返されます。</p><p>内部で複数のリクエストが発生する場合があるため、まれに `loadTimeout` で指定した時間より少し遅くタイムアウトすることがあります。</p> | レスポンスパラメーター: | パラメーター | 説明 | | :-------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------- | | Paywall | プロダクトIDのリスト、ペイウォール識別子、リモートコンフィグ、その他のプロパティを含む [`AdaptyPaywall`](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_paywall.html) オブジェクト。 | ## ペイウォールビルダーで設計したペイウォールのビュー設定を取得する \{#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder\} :::important ペイウォールビルダーで **Show on device** トグルが有効になっていることを確認してください。このオプションがオンになっていない場合、ビュー設定を取得できません。 ::: ペイウォールを取得したら、`ViewConfiguration` が含まれているかどうかを確認します。これはペイウォールビルダーで作成されたことを示します。`ViewConfiguration` が存在する場合はペイウォールビルダーのペイウォールとして扱い、存在しない場合は[リモートコンフィグペイウォールとして処理](present-remote-config-paywalls-unity)します。 Unity SDK では、ビュー設定を手動で取得せずに、直接 `CreatePaywallView` メソッドを呼び出します。 :::warning `CreatePaywallView` メソッドの結果は1回のみ使用できます。再度使用する必要がある場合は、`CreatePaywallView` メソッドを再度呼び出してください。再作成せずに2回呼び出すと、`AdaptyUIError.viewAlreadyPresented` エラーが発生する場合があります。 ::: ```csharp showLineNumbers var parameters = new AdaptyUICreatePaywallViewParameters() .SetPreloadProducts(preloadProducts) .SetLoadTimeout(new TimeSpan(0, 0, 3)); AdaptyUI.CreatePaywallView(paywall, parameters, (view, error) => { // handle the result }); ``` パラメーター: | パラメーター | 必須/任意 | 説明 | | :------------------ | :------------- | :----------------------------------------------------------- | | **paywall** | 必須 | 対象のペイウォールのコントローラーを取得するための `AdaptyPaywall` オブジェクト。 | | **loadTimeout** | デフォルト: 5秒 | このメソッドのタイムアウトを制限する値です。タイムアウトに達した場合、キャッシュデータまたはローカルフォールバックが返されます。内部で複数のリクエストが発生する場合があるため、まれに `loadTimeout` で指定した時間より少し遅くタイムアウトすることがあります。 | | **PreloadProducts** | 任意 | `AdaptyPaywallProducts` の配列を提供して、画面上のプロダクト表示タイミングを最適化します。`nil` が渡された場合、AdaptyUI は必要なプロダクトを自動的に取得します。 | | **CustomTags** | 任意 | カスタムタグとその解決済みの値の辞書を定義します。カスタムタグはペイウォールコンテンツのプレースホルダーとして機能し、ペイウォール内のパーソナライズされたコンテンツのために特定の文字列に動的に置き換えられます。詳細はペイウォールビルダーのカスタムタグのトピックを参照してください。 | | **CustomTimers** | 任意 | カスタムタイマーとその終了日時の辞書を定義します。カスタムタイマーを使用すると、ペイウォールにカウントダウンタイマーを表示できます。 | :::note 複数の言語を使用する場合、[ペイウォールビルダーのローカライズ](add-paywall-locale-in-adapty-paywall-builder)を追加する方法と、ロケールコードを正しく使用する方法を[こちら](localizations-and-locale-codes)で確認してください。 ::: ビューを取得したら、[ペイウォールを表示](unity-present-paywalls)します。 ## アセットをカスタマイズする \{#customize-assets\} ペイウォール内の画像や動画をカスタマイズするには、カスタムアセットを実装します。 ヒーロー画像と動画には事前定義されたID(`hero_image` と `hero_video`)があります。カスタムアセットバンドルでは、これらのIDでターゲット要素を指定してカスタマイズします。 その他の画像や動画については、Adapty ダッシュボードで[カスタムIDを設定](custom-media)する必要があります。 例えば、以下のことができます: - 一部のユーザーに異なる画像や動画を表示する。 - リモートのメイン画像の読み込み中にローカルのプレビュー画像を表示する。 - 動画再生前にプレビュー画像を表示する。 :::important この機能を使用するには、Adapty Unity SDK をバージョン 3.8.0 以降に更新してください。 ::: シンプルな辞書でカスタムアセットを提供する例: ```csharp showLineNumbers var customAssets = new Dictionary<string, AdaptyCustomAsset> { { "custom_image", AdaptyCustomAsset.LocalImageFile("custom_assets/images/custom_image.png") }, { "hero_video", AdaptyCustomAsset.LocalVideoFile("custom_assets/videos/custom_video.mp4") } }; var parameters = new AdaptyUICreatePaywallViewParameters() .SetCustomAssets(customAssets) .SetLoadTimeout(new TimeSpan(0, 0, 3)); AdaptyUI.CreatePaywallView(paywall, parameters, (view, error) => { // handle the result }); ``` :::note アセットが見つからない場合、ペイウォールはデフォルトの表示にフォールバックします。 ::: ## 開発者定義のタイマーを設定する \{#set-up-developer-defined-timers\} Unity アプリでカスタムタイマーを使用するには、タイマーIDと終了日時の辞書を `SetCustomTimers` メソッドに直接渡します。以下に例を示します: ```csharp showLineNumbers var customTimers = new Dictionary<string, DateTime> { { "CUSTOM_TIMER_6H", DateTime.Now.AddHours(6) }, { "CUSTOM_TIMER_NY", new DateTime(2025, 1, 1) } }; var parameters = new AdaptyUICreatePaywallViewParameters() .SetCustomTimers(customTimers) .SetLoadTimeout(new TimeSpan(0, 0, 3)); AdaptyUI.CreatePaywallView(paywall, parameters, (view, error) => { // handle the result }); ``` この例では、`CUSTOM_TIMER_NY` と `CUSTOM_TIMER_6H` は Adapty ダッシュボードで設定した開発者定義タイマーの **Timer ID** です。タイマーリゾルバーにより、アプリは各タイマーを正しい値で動的に更新します。例えば: - `CUSTOM_TIMER_NY`:元旦などのタイマー終了までの残り時間。 - `CUSTOM_TIMER_6H`:ユーザーがペイウォールを開いてから始まる6時間の残り時間。 ## デフォルトオーディエンスのペイウォールでペイウォール取得を高速化する \{#speed-up-paywall-fetching-with-default-audience-paywall\} 通常、ペイウォールはほぼ即座に取得されるため、このプロセスを高速化することを心配する必要はありません。ただし、オーディエンスやペイウォールが多数あり、ユーザーのインターネット接続が弱い場合、ペイウォールの取得に想定より時間がかかることがあります。そのような場合、ペイウォールをまったく表示しないよりも、デフォルトのペイウォールを表示してスムーズなユーザー体験を確保したいことがあります。 これに対応するために、`GetPaywallForDefaultAudience` メソッドを使用できます。このメソッドは **All Users** オーディエンスの指定されたプレースメントのペイウォールを取得します。ただし、推奨されるアプローチは上記の[ペイウォールを取得する](#fetch-paywall)セクションで詳述されている `getPaywall` メソッドを使用することであることを理解しておくことが重要です。 :::warning `GetPaywallForDefaultAudience` の代わりに `GetPaywall` の使用を検討してください。前者には重要な制限があります: - **互換性の問題**:複数のアプリバージョンをサポートする際に問題が生じる可能性があり、後方互換性のあるデザインを作成するか、古いバージョンで正しく表示されないことを許容する必要があります。 - **パーソナライズなし**:「All Users」オーディエンスのコンテンツのみが表示され、国、アトリビューション、カスタム属性に基づくターゲティングが利用できません。 ユースケースにおいて高速な取得がこれらのデメリットを上回る場合は、以下のように `GetPaywallForDefaultAudience` を使用してください。それ以外の場合は、[上記](#fetch-paywall)で説明した `GetPaywall` を使用してください。 ::: ```csharp showLineNumbers Adapty.GetPaywallForDefaultAudience("YOUR_PLACEMENT_ID", "en", (paywall, error) => { if(error != null) { // handle the error return; } // paywall - the resulting object }); ``` パラメーター: | パラメーター | 必須/任意 | 説明 | |---------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **placementId** | 必須 | 対象の[プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** | <p>任意</p><p>デフォルト: `en`</p> | <p>ペイウォールのローカライズの識別子。マイナス(**-**)文字で区切られた1つまたは2つのサブタグからなる言語コードを指定します。最初のサブタグは言語、2番目は地域を表します。</p><p></p><p>例:`en` は英語、`pt-br` はブラジルポルトガル語を表します。</p> | | **fetchPolicy** | デフォルト: `.reloadRevalidatingCacheData` | <p>デフォルトでは、SDKはサーバーからデータの読み込みを試み、失敗した場合はキャッシュされたデータを返します。ユーザーが常に最新のデータを取得できるため、このオプションを推奨します。</p><p></p><p>ただし、ユーザーの接続が不安定な場合は、`.returnCacheDataElseLoad` を使用してキャッシュデータが存在する場合はそれを返すことを検討してください。この場合、最新のデータが得られないことがありますが、接続状況にかかわらず読み込み時間が短縮されます。キャッシュは定期的に更新されるため、セッション中にネットワークリクエストを避けるために使用しても安全です。</p><p></p><p>キャッシュはアプリの再起動後も保持され、アプリの再インストールまたは手動クリーンアップ時にのみクリアされます。</p><p></p><p>Adapty SDK はペイウォールをローカルに2層で保存します:上述の定期更新キャッシュとフォールバックペイウォールです。また、CDNを使用してペイウォールをより高速に取得し、CDNが利用できない場合のためにスタンドアロンのフォールバックサーバーも用意しています。このシステムは、インターネット接続が不安定な場合でも常に最新バージョンのペイウォールを取得できるよう設計されています。</p> | --- # File: unity-present-paywalls --- --- title: "ペイウォールを表示する" description: "Adapty SDK を使用して Unity アプリでペイウォールを表示する方法を学びましょう。" --- ペイウォールビルダーを使ってペイウォールをカスタマイズしている場合、モバイルアプリのコード内でユーザーに表示するためのレンダリング処理は不要です。このようなペイウォールには、表示する内容と表示方法の両方が含まれています。 :::warning このガイドは、Adapty SDK 3.3.0 以降が必要な**新しいペイウォールビルダー**を対象としています。 リモートコンフィグのペイウォールを表示する場合は、[リモートコンフィグで設計したペイウォールのレンダリング](present-remote-config-paywalls)を参照してください。 ::: ペイウォールを表示するには、[`CreatePaywallView`](unity-get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder) メソッドで作成した `view` に対して `view.Present()` メソッドを使用します。各 `view` は一度しか使用できません。ペイウォールを再度表示する必要がある場合は、`CreatePaywallView` をもう一度呼び出して新しい `view` インスタンスを作成してください。 :::warning `view` を再作成せずに再利用すると、`AdaptyUIError.viewAlreadyPresented` エラーが発生する場合があります。 ::: ```csharp showLineNumbers title="Unity" view.Present((error) => { // handle the error }); ``` :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: ## ダイアログを表示する \{#show-dialog\} Android でペイウォールビューが表示されている場合は、ネイティブのアラートダイアログの代わりにこのメソッドを使用してください。Android では、通常のアラートはペイウォールビューの背面に表示されるため、ユーザーには見えません。このメソッドを使用すると、すべてのプラットフォームでペイウォールの上に正しくダイアログが表示されます。 ```csharp showLineNumbers title="Unity" var dialog = new AdaptyUIDialogConfiguration() .SetTitle("Close paywall?") .SetContent("You will lose access to exclusive offers.") .SetDefaultActionTitle("Stay") .SetSecondaryActionTitle("Close"); AdaptyUI.ShowDialog(view, dialog, (action, error) => { if (error == null) { if (action == AdaptyUIDialogActionType.Secondary) { // User confirmed - close the paywall view.Dismiss(); } // If primary - do nothing, user stays } }); ``` ## iOS の表示スタイルを設定する \{#configure-ios-presentation-style\} `Present()` メソッドに `iosPresentationStyle` パラメーターを渡すことで、iOS でのペイウォールの表示方法を設定できます。パラメーターには `AdaptyUIIOSPresentationStyle.FullScreen`(デフォルト)または `AdaptyUIIOSPresentationStyle.PageSheet` を指定できます。 ```csharp showLineNumbers title="Unity" view.Present(AdaptyUIIOSPresentationStyle.PageSheet, (error) => { // handle the error }); ``` --- # File: unity-handle-paywall-actions --- --- title: "Unity SDKでボタンアクションに応答する" description: "AdaptyのUnityでペイウォールのボタンアクションを処理して、アプリのマネタイズを改善します。" --- Adaptyのペイウォールビルダーを使ってペイウォールを作成する場合、ボタンを適切に設定することが重要です。 1. [ペイウォールビルダーでボタンを追加](paywall-buttons)し、既存のアクションを割り当てるか、カスタムアクションIDを作成します。 2. 割り当てた各アクションを処理するコードをアプリに実装します。 このガイドでは、カスタムアクションと既存のアクションをコードで処理する方法を説明します。 :::warning **購入と復元のみ自動的に処理されます。** ペイウォールを閉じる、リンクを開くなど、その他のボタンアクションはすべて、アプリのコードに適切な処理を実装する必要があります。 ::: ## ペイウォールを閉じる \{#close-paywalls\} ペイウォールを閉じるボタンを追加するには、次の手順に従います。 1. ペイウォールビルダーでボタンを追加し、**Close** アクションを割り当てます。 2. アプリのコードに、ペイウォールを閉じる `close` アクションのハンドラーを実装します。 ```csharp showLineNumbers title="Unity" public void PaywallViewDidPerformAction( AdaptyUIPaywallView view, AdaptyUIUserAction action ) { switch (action.Type) { case AdaptyUIUserActionType.Close: view.Dismiss(null); break; default: // handle other events break; } } ``` ## ペイウォールからURLを開く \{#open-urls-from-paywalls\} :::tip リンクのグループ(利用規約や購入の復元など)を追加したい場合は、ペイウォールビルダーで **Link** 要素を追加し、**Open URL** アクションが設定されたボタンと同じ方法で処理します。 ::: ペイウォールからリンクを開くボタン(**Terms of use** や **Privacy policy** など)を追加するには、次の手順に従います。 1. ペイウォールビルダーでボタンを追加し、**Open URL** アクションを割り当て、開きたいURLを入力します。 2. アプリのコードに、受け取ったURLをブラウザで開く `openUrl` アクションのハンドラーを実装します。 ```csharp showLineNumbers title="Unity" public void PaywallViewDidPerformAction( AdaptyUIPaywallView view, AdaptyUIUserAction action ) { switch (action.Type) { case AdaptyUIUserActionType.OpenUrl: var urlString = action.Value; if(!string.IsNullOrWhiteSpace(urlString)) { Application.OpenURL(urlString); } break; default: // handle other events break; } } ``` ## アプリへのログイン \{#log-into-the-app\} ユーザーをアプリにログインさせるボタンを追加するには、次の手順に従います。 1. ペイウォールビルダーでボタンを追加し、ID `login` の **Custom** アクションを割り当てます。 2. アプリのコードに、ユーザーを識別する `login` カスタムアクションのハンドラーを実装します。 ```csharp showLineNumbers title="Unity" public void PaywallViewDidPerformAction( AdaptyUIPaywallView view, AdaptyUIUserAction action ) { switch (action.Type) { case AdaptyUIUserActionType.Custom: if (action.Value == "login") { // Navigate to login scene SceneManager.LoadScene("LoginScene"); } break; default: // handle other events break; } } ``` ## カスタムアクションを処理する \{#handle-custom-actions\} その他のアクションを処理するボタンを追加するには、次の手順に従います。 1. ペイウォールビルダーでボタンを追加し、**Custom** アクションを割り当て、IDを設定します。 2. アプリのコードに、作成したアクションIDのハンドラーを実装します。 たとえば、別のサブスクリプションオファーや買い切り購入がある場合、別のペイウォールを表示するボタンを追加できます。 ```csharp showLineNumbers title="Unity" public void PaywallViewDidPerformAction( AdaptyUIPaywallView view, AdaptyUIUserAction action ) { switch (action.Type) { case AdaptyUIUserActionType.Custom: if (action.Value == "openNewPaywall") { // Display another paywall ShowAlternativePaywall(); } break; default: // handle other events break; } } private void ShowAlternativePaywall() { // Implement your logic to show alternative paywall } ``` --- # File: unity-handling-events --- --- title: "ペイウォールイベントの処理" description: "Adapty SDK を使用して Unity アプリでペイウォールイベントを処理する方法を学びましょう。" --- :::important このガイドでは、購入・復元・プロダクト選択・ペイウォールのレンダリングに関するイベント処理を説明します。ボタン操作(ペイウォールを閉じる、リンクを開くなど)の実装も必要です。詳細は[ボタンアクションの処理ガイド](unity-handle-paywall-actions)をご覧ください。 ::: [ペイウォールビルダー](adapty-paywall-builder)で設定されたペイウォールは、購入や復元のために追加コードは不要です。ただし、アプリが応答できるいくつかのイベントが生成されます。これらのイベントには、ボタン操作(閉じるボタン、URL、プロダクト選択など)や、ペイウォール上で行われた購入関連のアクションへの通知が含まれます。以下でこれらのイベントへの対応方法を説明します。 :::warning このガイドは、Adapty SDK v3.3.0 以降が必要な**新しいペイウォールビルダーのペイウォール**専用です。 ::: :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: ## イベントの処理 \{#handling-events\} モバイルアプリ内のペイウォール画面で発生するプロセスを制御・監視するには、`AdaptyPaywallsEventsListener` インターフェースを実装します。 ```csharp showLineNumbers title="Unity" using UnityEngine; using AdaptySDK; public class PaywallEventsHandler : MonoBehaviour, AdaptyPaywallsEventsListener { void Start() { Adapty.SetPaywallsEventsListener(this); } // Implement all required interface methods below } ``` ### ユーザーが生成するイベント \{#user-generated-events\} #### ペイウォールの表示 \{#paywall-appeared\} ペイウォールビューが画面に表示されたときに呼び出されます。 :::note iOS では、ユーザーがペイウォール内の[ウェブペイウォールボタン](web-paywall#step-2a-add-a-web-purchase-button)をタップして、インアプリブラウザでウェブペイウォールが開いたときにも呼び出されます。 ::: ```csharp showLineNumbers title="Unity" public void PaywallViewDidAppear(AdaptyUIPaywallView view) { } ``` #### ペイウォールの非表示 \{#paywall-disappeared\} ペイウォールビューが画面から閉じられたときに呼び出されます。 :::note iOS では、ペイウォールからインアプリブラウザで開いた[ウェブペイウォール](web-paywall#step-2a-add-a-web-purchase-button)が画面から消えたときにも呼び出されます。 ::: ```csharp showLineNumbers title="Unity" public void PaywallViewDidDisappear(AdaptyUIPaywallView view) { } ``` #### プロダクト選択 \{#product-selection\} プロダクトが購入対象として選択されたとき(ユーザーまたはシステムによる)に呼び出されます。 ```csharp showLineNumbers title="Unity" public void PaywallViewDidSelectProduct( AdaptyUIPaywallView view, string productId ) { } ``` <Details> <summary>イベント例(クリックして展開)</summary> ```javascript { "productId": "premium_monthly" } ``` </Details> #### 購入開始 \{#started-purchase\} ユーザーが購入プロセスを開始したときに呼び出されます。 ```csharp showLineNumbers title="Unity" public void PaywallViewDidStartPurchase( AdaptyUIPaywallView view, AdaptyPaywallProduct product ) { } ``` <Details> <summary>イベント例(クリックして展開)</summary> ```javascript { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" } } ``` </Details> #### 購入成功・キャンセル・保留 \{#successful-canceled-or-pending-purchase\} 購入が成功した場合、ユーザーが購入をキャンセルした場合、または購入が保留中になった場合に、このメソッドが呼び出されます。ユーザーによるキャンセルや保留中の支払い(保護者の承認が必要な場合など)は、`PaywallViewDidFailPurchase` ではなくこのメソッドをトリガーします。 ```csharp showLineNumbers title="Unity" public void PaywallViewDidFinishPurchase( AdaptyUIPaywallView view, AdaptyPaywallProduct product, AdaptyPurchaseResult purchasedResult ) { } ``` <Details> <summary>イベント例(クリックして展開)</summary> ```javascript // Successful purchase { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "purchaseResult": { "type": "Success", "profile": { "accessLevels": { "premium": { "id": "premium", "isActive": true, "expiresAt": "2024-02-15T10:30:00Z" } } } } } // Cancelled purchase { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "purchaseResult": { "type": "UserCancelled" } } // Pending purchase { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "purchaseResult": { "type": "Pending" } } ``` </Details> その場合は画面を閉じることをお勧めします。 #### 購入失敗 \{#failed-purchase\} エラーにより購入が失敗した場合に、このメソッドが呼び出されます。StoreKit/Google Play Billing のエラー(支払い制限、無効なプロダクト、ネットワーク障害)、トランザクション検証の失敗、システムエラーが含まれます。なお、ユーザーによるキャンセルはキャンセル結果として `PaywallViewDidFinishPurchase` をトリガーし、保留中の支払いはこのメソッドをトリガーしません。 ```csharp showLineNumbers title="Unity" public void PaywallViewDidFailPurchase( AdaptyUIPaywallView view, AdaptyPaywallProduct product, AdaptyError error ) { } ``` <Details> <summary>イベント例(クリックして展開)</summary> ```javascript { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "error": { "code": "purchase_failed", "message": "Purchase failed due to insufficient funds", "details": { "underlyingError": "Insufficient funds in account" } } } ``` </Details> #### 復元開始 \{#started-restore\} ユーザーが復元プロセスを開始したときに呼び出されます。 ```csharp showLineNumbers title="Unity" public void PaywallViewDidStartRestore(AdaptyUIPaywallView view) { } ``` #### 復元成功 \{#successful-restore\} 購入の復元が成功したときに呼び出されます。 ```csharp showLineNumbers title="Unity" public void PaywallViewDidFinishRestore( AdaptyUIPaywallView view, AdaptyProfile profile ) { } ``` <Details> <summary>イベント例(クリックして展開)</summary> ```javascript { "profile": { "accessLevels": { "premium": { "id": "premium", "isActive": true, "expiresAt": "2024-02-15T10:30:00Z" } }, "subscriptions": [ { "vendorProductId": "premium_monthly", "isActive": true, "expiresAt": "2024-02-15T10:30:00Z" } ] } } ``` </Details> ユーザーが必要な `accessLevel` を持っている場合は、画面を閉じることをお勧めします。確認方法については、[サブスクリプションのステータス](unity-listen-subscription-changes)を参照してください。 #### 復元失敗 \{#failed-restore\} 購入の復元が失敗したときに呼び出されます。 ```csharp showLineNumbers title="Unity" public void PaywallViewDidFailRestore( AdaptyUIPaywallView view, AdaptyError error ) { } ``` <Details> <summary>イベント例(クリックして展開)</summary> ```javascript { "error": { "code": "restore_failed", "message": "Purchase restoration failed", "details": { "underlyingError": "No previous purchases found" } } } ``` </Details> #### ウェブ支払いナビゲーション完了 \{#finished-web-payment-navigation\} 購入のために[ウェブペイウォール](web-paywall)を開こうとした後(成功・失敗に関わらず)、このメソッドが呼び出されます。 ```csharp showLineNumbers title="Unity" public void PaywallViewDidFinishWebPaymentNavigation( AdaptyUIPaywallView view, AdaptyPaywallProduct product, AdaptyError error ) { } ``` **パラメータ:** - `product`: ウェブペイウォールが開かれた(または開こうとした)プロダクト - `error`: ウェブペイウォールが正常に開いた場合は `null`、失敗した場合は `AdaptyError` <Details> <summary>イベント例(クリックして展開)</summary> ```javascript // Successful navigation { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "error": null } // Failed navigation { "product": { "vendorProductId": "premium_monthly", "localizedTitle": "Premium Monthly", "localizedDescription": "Premium subscription for 1 month", "localizedPrice": "$9.99", "price": 9.99, "currencyCode": "USD" }, "error": { "code": "wrong_param", "message": "Current method is not available for this product", "details": { "underlyingError": "Product not configured for web purchases" } } } ``` </Details> ### データ取得とレンダリング \{#data-fetching-and-rendering\} #### プロダクト読み込みエラー \{#product-loading-errors\} プロダクトの読み込みに失敗し、`AdaptyError` が提供されたときに呼び出されます。初期化時にプロダクト配列を渡さなかった場合、AdaptyUI はサーバーから必要なオブジェクトを自動的に取得します。この処理が失敗した場合、AdaptyUI はこのメソッドを呼び出してエラーを報告します。 ```csharp showLineNumbers title="Unity" public void PaywallViewDidFailLoadingProducts( AdaptyUIPaywallView view, AdaptyError error ) { } ``` <Details> <summary>イベント例(クリックして展開)</summary> ```javascript { "error": { "code": "products_loading_failed", "message": "Failed to load products from the server", "details": { "underlyingError": "Network timeout" } } } ``` </Details> #### レンダリングエラー \{#rendering-errors\} インターフェースのレンダリング中にエラーが発生し、`AdaptyError` が提供されたときに呼び出されます。 ```csharp showLineNumbers title="Unity" public void PaywallViewDidFailRendering( AdaptyUIPaywallView view, AdaptyError error ) { } ``` <Details> <summary>イベント例(クリックして展開)</summary> ```javascript { "error": { "code": "rendering_failed", "message": "Failed to render paywall interface", "details": { "underlyingError": "Invalid paywall configuration" } } } ``` </Details> 通常の状況ではこのようなエラーは発生しないはずです。もし遭遇した場合はお知らせください。 --- # File: unity-web-paywalls --- --- title: "Unity SDKでWebペイウォールを実装する" description: "App Storeの手数料や審査なしで支払いを受け取るWebペイウォールを設定します。" --- :::important 始める前に、[ダッシュボードでWebペイウォールを設定](web-paywall)し、Adapty SDK バージョン3.14以降をインストールしていることを確認してください。 ::: ## Webペイウォールを開く \{#open-web-paywalls\} 自分で開発したペイウォールを使用している場合は、SDKメソッドでWebペイウォールを処理する必要があります。`Adapty.OpenWebPaywall`メソッドは以下を行います: 1. 特定のユーザーに表示された特定のペイウォールを、リダイレクト先のWebページに紐付けるための一意のURLを生成します。 2. ユーザーがアプリに戻ったタイミングを検知し、短い間隔で`Adapty.GetProfile`をリクエストして、プロファイルのアクセス権が更新されたかどうかを確認します。 これにより、支払いが成功してアクセス権が更新された場合、サブスクリプションはほぼ即座にアプリ内で有効になります。 ```csharp showLineNumbers title="Unity" Adapty.OpenWebPaywall( product, (error) => { if (error != null) { Debug.LogError($"Failed to open web paywall: {error.Message}"); } else { Debug.Log("Web paywall opened successfully"); } } ); ``` :::note `OpenWebPaywall`メソッドには2つのバージョンがあります: 1. `OpenWebPaywall(product)` — ペイウォールでURLを生成し、プロダクトデータもURLに追加します。 2. `OpenWebPaywall(paywall)` — プロダクトデータを追加せず、ペイウォールでURLを生成します。AdaptyペイウォールのプロダクトとWebペイウォールのプロダクトが異なる場合に使用してください。 ::: #### エラーの処理 \{#handle-errors\} | エラーコード | 説明 | 推奨アクション | |-----------|--------------------------------------------------------|---------------------------------------------------------------------------| | `AdaptyErrorCode.WrongParam` | ペイウォールまたはプロダクトにWeb購入URLが設定されていない、またはブラウザでURLを開くことができなかった | エラーメッセージで詳細を確認してください。Adapty ダッシュボードでペイウォール/プロダクトの設定を確認するか、デバイスの設定を確認してください。 | | `AdaptyErrorCode.DecodingFailed` | URLのパラメーターを正しくエンコードできなかった | URLパラメーターが有効で適切な形式になっているか確認してください | :::note `WrongParam`は複数の問題(購入URLの欠如、ブラウザを開けないなど)を示す可能性があるため、何が問題だったかの詳細を取得するにはエラーの`Message`プロパティを確認してください。 ::: ## アプリ内ブラウザでWebペイウォールを開く \{#open-web-paywalls-in-an-in-app-browser\} :::important アプリ内ブラウザでWebペイウォールを開く機能は、Adapty SDK v3.15以降でサポートされています。 ::: デフォルトでは、WebペイウォールはアプリのExternalBrowserで開き、ユーザーはアプリの外に移動します。 シームレスなユーザー体験を提供するために、代わりにアプリ内ブラウザでWebペイウォールを開くことができます。これにより、Web購入ページがアプリ内に表示され、ユーザーはアプリを切り替えることなく取引を完了できます。 これを有効にするには、`OpenWebPaywall`メソッドに`AdaptyWebPresentation.InAppBrowser`を渡します: ```csharp showLineNumbers title="Unity" Adapty.OpenWebPaywall( product, AdaptyWebPresentation.InAppBrowser, // default — ExternalBrowser (error) => { if (error != null) { Debug.LogError($"Failed to open web paywall: {error.Message}"); } else { Debug.Log("Web paywall opened successfully"); } } ); ``` --- # File: unity-use-fallback-paywalls --- --- title: "Unity - フォールバックペイウォールの使用" description: "ユーザーがオフラインのとき、またはAdaptyサーバーが利用できないときの処理" --- :::warning フォールバックペイウォールは Unity SDK v2.11 以降でサポートされています。 ::: スムーズなユーザー体験を維持するために、フロー、[ペイウォール](paywalls)、[オンボーディング](onboardings)に[フォールバック](/fallback-paywalls)を設定することが重要です。この対策により、インターネット接続が部分的または完全に失われた場合でも、アプリケーションの機能を維持できます。 * **アプリケーションが Adapty サーバーにアクセスできない場合:** フォールバックのフローまたはペイウォールを表示し、ローカルのオンボーディング設定にアクセスできます。 * **アプリケーションがインターネットにアクセスできない場合:** フォールバックのフローまたはペイウォールを表示できます。オンボーディングはリモートコンテンツを含むため、動作にはインターネット接続が必要です。 :::important このガイドの手順を進める前に、Adapty からフォールバック設定ファイルを[ダウンロード](/local-fallback-paywalls)してください。 ::: ## 設定 \{#configuration\} 1. フォールバック設定ファイルをプロジェクトの共通ディレクトリ `Assets/StreamingAssets` に追加してください。 2. 対象のペイウォールまたはオンボーディングを取得する**前に** `.setFallback` メソッドを呼び出してください。 ```csharp using UnityEngine; using AdaptySDK; #if UNITY_IOS string fileName = "ios_fallback.json"; #elif UNITY_ANDROID string fileName = "android_fallback.json"; #else // Optional: handle Editor or other platforms string fileName = "fallback.json"; #endif Adapty.SetFallback(fileName, (error) => { if (error != null) { Debug.LogError($"Failed to set fallback: {error}"); return; } // Fallback set successfully }); ``` パラメーター: | パラメーター | 説明 | |:-------------|:-----------------------------------------------------| | **fileName** | フォールバック設定ファイルの名前を表す文字列。 | --- # File: unity-localizations-and-locale-codes --- --- title: "Unity SDKでローカライゼーションとロケールコードを使用する" description: "Adapty SDKを使用してUnityアプリのペイウォールをローカライズする方法を説明します。" --- ## なぜこれが重要なのか \{#why-this-is-important\} ロケールコードが関係するシナリオはいくつかあります。たとえば、アプリの現在のローカライゼーションに合った正しいペイウォールを取得しようとする場合などです。 ロケールコードは複雑で、プラットフォームによって異なるため、Adaptyではサポートするすべてのプラットフォームに対して独自の標準を採用しています。ただし、これらのコードが複雑であるがゆえに、サーバーに何を送信して正しいローカライゼーションを取得するのか、そしてその後何が起こるのかを正確に理解することが非常に重要です。そうすれば、常に期待通りの結果を受け取ることができます。 ## AdaptyのロケールコードI標準 \{#locale-code-standard-at-adapty\} ロケールコードについて、Adaptyはわずかに修正された[BCP 47標準](https://en.wikipedia.org/wiki/IETF_language_tag)を使用しています。各コードは小文字のサブタグで構成され、ハイフンで区切られています。例:`en`(英語)、`pt-br`(ポルトガル語(ブラジル))、`zh`(簡体字中国語)、`zh-hant`(繁体字中国語)。 ## ロケールコードのマッチング \{#locale-code-matching\} Adaptyがクライアント側のSDKからロケールコード付きの呼び出しを受け取り、ペイウォールの対応するローカライゼーションを検索する際、以下の処理が行われます: 1. 受信したロケール文字列が小文字に変換され、アンダースコア(`_`)がすべてハイフン(`-`)に置き換えられます 2. 完全に一致するロケールコードを持つローカライゼーションを検索します 3. 一致するものが見つからない場合、最初のハイフンより前の部分文字列(`pt-br`なら`pt`)を取り出して、一致するローカライゼーションを検索します 4. それでも一致するものが見つからない場合、デフォルトの`en`ローカライゼーションを返します これにより、`'pt_BR'`を送信したiOSデバイス、`pt-BR`を送信したAndroidデバイス、`pt-br`を送信した別のデバイスはすべて同じ結果を受け取ります。 ## ローカライゼーションの実装:推奨方法 \{#implementing-localizations-recommended-way\} ローカライゼーションについて検討しているなら、すでにプロジェクトでローカライズされた文字列ファイルを扱っているかもしれません。その場合、各ローカライゼーションに対応するファイルに、意図したAdaptyロケールコードをキーと値のペアとして追加することをお勧めします。そして、SDKを呼び出す際にそのキーの値を取り出します: ```csharp showLineNumbers // 1. Modify your localization files (e.g., using Unity's Localization package) /* en.json */ { "adapty_paywalls_locale": "en" } /* es.json */ { "adapty_paywalls_locale": "es" } /* pt-BR.json */ { "adapty_paywalls_locale": "pt-br" } // 2. Extract and use the locale code using UnityEngine; using UnityEngine.Localization; using UnityEngine.Localization.Settings; using AdaptySDK; public class PaywallManager : MonoBehaviour { public async void FetchPaywall() { // Get the current locale from Unity's Localization system var locale = LocalizationSettings.SelectedLocale; var localeCode = GetAdaptyLocaleCode(locale); // Pass locale code to Adapty.GetPaywall or Adapty.GetPaywallForDefaultAudience method Adapty.GetPaywall("placement_id", localeCode, (paywall, error) => { if (error != null) { // handle the error return; } // Use the paywall }); } private string GetAdaptyLocaleCode(Locale locale) { // Convert Unity locale to Adapty format var localeIdentifier = locale.Identifier.Code; return localeIdentifier.ToLower().Replace('_', '-'); } } ``` これにより、アプリのすべてのユーザーに対してどのローカライゼーションが取得されるかを完全にコントロールできます。 ## ローカライゼーションの実装:別の方法 \{#implementing-localizations-the-other-way\} すべてのローカライゼーションに対してロケールコードを明示的に定義せずに、同様の(ただし同一ではない)結果を得ることもできます。その場合、プラットフォームが提供する他のオブジェクトからロケールコードを抽出します: ```csharp showLineNumbers using UnityEngine; using System.Globalization; using AdaptySDK; public class PaywallManager : MonoBehaviour { public void FetchPaywall() { var localeCode = GetSystemLocaleCode(); // Pass locale code to Adapty.GetPaywall or Adapty.GetPaywallForDefaultAudience method Adapty.GetPaywall("placement_id", localeCode, (paywall, error) => { if (error != null) { // handle the error return; } // Use the paywall }); } private string GetSystemLocaleCode() { // Get the system's current culture var culture = CultureInfo.CurrentCulture; var languageCode = culture.TwoLetterISOLanguageName; var regionCode = culture.Name.Contains('-') ? culture.Name.Split('-')[1] : null; if (!string.IsNullOrEmpty(regionCode)) { return $"{languageCode}-{regionCode.ToLower()}"; } return languageCode; } } ``` この方法はいくつかの理由からお勧めしません: 1. iOSでは優先言語と現在のロケールは同一ではありません。ローカライゼーションを正しく選択したい場合は、Appleのロジックに頼るか(ローカライズされた文字列ファイルを使った推奨アプローチを使用すれば自動的に機能します)、またはそのロジックを再実装する必要があります。 2. Adaptyのサーバーが受け取る内容を正確に予測することが難しくなります。たとえばiOSでは、デバイスから`ar_OM@numbers='latn'`のようなロケールを取得してサーバーに送信することがあります。この呼び出しに対して、期待していた`ar-om`ローカライゼーションではなく、`ar`が返されることになり、予期しない結果となる可能性があります。 それでもこのアプローチを使用する場合は、関連するユースケースをすべて網羅していることを確認してください。 --- # File: unity-troubleshoot-paywall-builder --- --- title: "Troubleshoot Paywall Builder in Unity SDK" description: "Troubleshoot Paywall Builder in Unity SDK" --- このガイドでは、Unity SDK でAdapty ペイウォールビルダーを使用してデザインしたペイウォールに関する一般的な問題の解決方法を説明します。 ## ペイウォール設定の取得に失敗する \{#getting-a-paywall-configuration-fails\} **問題**: `CreateView` メソッドがペイウォール設定の取得に失敗する。 **原因**: ペイウォールビルダーでデバイス表示が有効になっていない。 **解決策**: ペイウォールビルダーの **Show on device** トグルを有効にしてください。 <img src="/assets/shared/img/show-on-device.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## ペイウォールのビュー数が多すぎる \{#the-paywall-view-number-is-too-big\} **問題**: ペイウォールのビュー数が期待値の2倍になっている。 **原因**: コード内で `LogShowPaywall` を呼び出している可能性があります。ペイウォールビルダーを使用している場合、この呼び出しによってビュー数が重複します。ペイウォールビルダーでデザインされたペイウォールでは、アナリティクスが自動的に追跡されるため、このメソッドを使用する必要はありません。 **解決策**: ペイウォールビルダーを使用している場合は、コード内で `LogShowPaywall` を呼び出していないことを確認してください。 ## その他の問題 \{#other-issues\} **問題**: 上記以外のペイウォールビルダー関連の問題が発生している。 **解決策**: 必要に応じて[マイグレーションガイド](unity-sdk-migration-guides)を参照し、SDKを最新バージョンに移行してください。多くの問題は新しいSDKバージョンで解決されています。 --- # File: unity-quickstart-manual --- --- title: "Unity SDKでカスタムペイウォールの購入を有効にする" description: "Adapty SDKをUnityのカスタムペイウォールに統合してアプリ内課金を有効にします。" --- このガイドでは、カスタムペイウォールへのAdapty統合方法を説明します。ペイウォールの実装を完全にコントロールしながら、Adapty SDKがプロダクトの取得、新規購入の処理、過去の購入の復元を担当します。 :::important **このガイドはカスタムペイウォールを実装する開発者向けです。** 購入を最も簡単に有効にする方法をお探しの場合は、[Adapty ペイウォールビルダー](unity-quickstart-paywalls)をご利用ください。ペイウォールビルダーを使えば、ノーコードのビジュアルエディターでペイウォールを作成でき、購入ロジックはAdaptyが自動処理します。また、アプリを再公開することなく異なるデザインをテストできます。 ::: ## 始める前に \{#before-you-start\} ### プロダクトのセットアップ \{#set-up-products\} アプリ内課金を有効にするには、次の3つの重要な概念を理解する必要があります: - [**プロダクト**](product) – ユーザーが購入できるもの(サブスクリプション、消耗型アイテム、永続アクセス) - [**ペイウォール**](paywalls) – どのプロダクトを提供するかを定義する設定。Adaptyではペイウォールがプロダクトを取得する唯一の方法ですが、この設計によりアプリコードを変更せずにプロダクト、価格、オファーを変更できます。 - [**プレースメント**](placements) – アプリ内でペイウォールを表示する場所とタイミング(`main`、`onboarding`、`settings`など)。ダッシュボードでプレースメントにペイウォールを設定し、コード内でプレースメントIDを使ってリクエストします。これにより、A/Bテストの実施や異なるユーザーへの異なるペイウォール表示が簡単になります。 カスタムペイウォールを使う場合でも、これらの概念を理解しておくことが重要です。基本的に、アプリで販売するプロダクトを管理するための手段です。 カスタムペイウォールを実装するには、**ペイウォール**を作成して**プレースメント**に追加する必要があります。この設定によりプロダクトを取得できます。ダッシュボードで何をすべきかを理解するには、[こちら](quickstart)のクイックスタートガイドをご覧ください。 ### ユーザーの管理 \{#manage-users\} バックエンド認証の有無にかかわらず利用できます。 ただし、Adapty SDKは匿名ユーザーと識別済みユーザーを異なる方法で扱います。詳細を確認し、ユーザーを適切に扱うために[識別クイックスタートガイド](unity-quickstart-identify)をお読みください。 ## ステップ1. プロダクトを取得する \{#step-1-get-products\} カスタムペイウォール用のプロダクトを取得するには、次の手順が必要です: 1. `getPaywall`メソッドに[プレースメント](placements)IDを渡して`paywall`オブジェクトを取得します。 2. `getPaywallProducts`メソッドを使ってこのペイウォールのプロダクト配列を取得します。 ```csharp showLineNumbers using AdaptySDK; void LoadPaywall() { Adapty.GetPaywall("YOUR_PLACEMENT_ID", (paywall, error) => { if (error != null) { // Handle the error return; } Adapty.GetPaywallProducts(paywall, (products, productsError) => { if (productsError != null) { // Handle the error return; } // Use products to build your custom paywall UI }); }); } ``` ## ステップ2. 購入を受け付ける \{#step-2-accept-purchases\} ユーザーがカスタムペイウォールでプロダクトをタップしたら、選択されたプロダクトを引数に`makePurchase`メソッドを呼び出します。購入フローが処理され、更新されたプロファイルが返されます。 ```csharp showLineNumbers using AdaptySDK; void PurchaseProduct(AdaptyPaywallProduct product) { Adapty.MakePurchase(product, (result, error) => { if (error != null) { // Handle the error return; } switch (result.Type) { case AdaptyPurchaseResultType.Success: var profile = result.Profile; // Purchase successful, profile updated break; case AdaptyPurchaseResultType.UserCancelled: // User canceled the purchase break; case AdaptyPurchaseResultType.Pending: // Purchase is pending (e.g., user will pay offline with cash) break; } }); } ``` ## ステップ3. 購入を復元する \{#step-3-restore-purchases\} アプリストアは、サブスクリプションのあるすべてのアプリに対して、ユーザーが購入を復元できる手段を提供することを要求しています。 ユーザーが復元ボタンをタップしたら`restorePurchases`メソッドを呼び出します。購入履歴がAdaptyと同期され、更新されたプロファイルが返されます。 ```csharp showLineNumbers using AdaptySDK; void RestorePurchases() { Adapty.RestorePurchases((profile, error) => { if (error != null) { // Handle the error return; } // Restore successful, profile updated }); } ``` ## 次のステップ \{#next-steps\} --- no_index: true --- import Callout from '../../../components/Callout.astro'; <Callout type="tip"> ご質問やお困りのことがあれば、[サポートフォーラム](https://adapty.featurebase.app/)をご覧ください。よくある質問への回答を見つけたり、ご自身の質問を投稿することができます。チームとコミュニティがサポートいたします! </Callout> ペイウォールをアプリに表示する準備が整いました。[App Storeサンドボックス](test-purchases-in-sandbox)または[Google Play Store](testing-on-android)でテスト購入を実施して、ペイウォールからテスト購入を完了できることを確認してください。 次に、[ユーザーが購入を完了したかどうか確認](unity-check-subscription-status)して、ペイウォールを表示するか有料機能へのアクセスを許可するかを判断します。 --- # File: fetch-paywalls-and-products-unity --- --- title: "Unity SDKでリモートコンフィグペイウォールのペイウォールとプロダクトを取得する" description: "Adapty Unity SDKでペイウォールとプロダクトを取得し、ユーザーのマネタイズを強化する。" --- リモートコンフィグやカスタムペイウォールを表示する前に、それらの情報を取得する必要があります。このトピックはリモートコンフィグおよびカスタムペイウォールに関するものです。ペイウォールビルダーでカスタマイズしたペイウォールの取得方法については、[ペイウォールビルダーのペイウォールと設定の取得](unity-get-pb-paywalls)を参照してください。 :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: <details> <summary>モバイルアプリでペイウォールとプロダクトの取得を始める前に(クリックして展開)</summary> 1. Adapty ダッシュボードで[プロダクトを作成する](create-product)。 2. Adapty ダッシュボードで[ペイウォールを作成し、プロダクトをペイウォールに組み込む](create-paywall)。 3. Adapty ダッシュボードで[プレースメントを作成し、ペイウォールをプレースメントに組み込む](create-placement)。 4. モバイルアプリに[Adapty SDKをインストールする](sdk-installation-unity)。 </details> ## ペイウォール情報の取得 \{#fetch-paywall-information\} Adaptyでは、[プロダクト](product)はApp StoreとGoogle Play両方のプロダクトを組み合わせたものです。これらのクロスプラットフォームプロダクトはペイウォールに統合され、特定のモバイルアプリのプレースメント内で表示できます。 プロダクトを表示するには、`getPaywall` メソッドを使って[プレースメント](placements)のいずれかから[ペイウォール](paywalls)を取得する必要があります。 :::important **プロダクトIDをハードコードしないでください。** ハードコードすべき唯一のIDはプレースメントIDです。ペイウォールはリモートで設定されるため、プロダクトの数や利用可能なオファーはいつでも変わる可能性があります。アプリはこれらの変更を動的に処理する必要があります。今日ペイウォールが2つのプロダクトを返し、明日3つ返しても、コード変更なしにすべて表示できるようにしてください。 ::: ```csharp showLineNumbers Adapty.GetPaywall("YOUR_PLACEMENT_ID", "en", (paywall, error) => { if(error != null) { // handle the error return; } // paywall - the resulting object }); ``` | パラメータ | 必須/任意 | 説明 | |---------|--------|-----------| | **placementId** | 必須 | [プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** | <p>任意</p><p>デフォルト: `en`</p> | <p>[ペイウォールのローカライゼーション](add-remote-config-locale)の識別子。このパラメータはマイナス(**-**)文字で区切られた1つ以上のサブタグで構成される言語コードを指定します。最初のサブタグは言語、2番目は地域を表します。</p><p></p><p>例: `en` は英語、`pt-br` はブラジルポルトガル語を表します。</p><p></p><p>ロケールコードの詳細と推奨される使い方については、[ローカライゼーションとロケールコード](unity-localizations-and-locale-codes)を参照してください。</p> | | **fetchPolicy** | デフォルト: `.reloadRevalidatingCacheData` | <p>デフォルトでは、SDKはサーバーからデータを読み込もうとし、失敗した場合はキャッシュデータを返します。ユーザーが常に最新のデータを取得できるため、この設定を推奨します。</p><p></p><p>ただし、ユーザーのインターネット接続が不安定だと思われる場合は、`.returnCacheDataElseLoad` を使用してキャッシュデータが存在する場合に返すことを検討してください。この場合、ユーザーは最新データを取得できないことがありますが、通信状況に関わらず読み込みが速くなります。キャッシュは定期的に更新されるため、セッション中のネットワークリクエスト削減に安全に使用できます。</p><p></p><p>キャッシュはアプリの再起動後も保持され、アプリの再インストールまたは手動でのクリア時のみ削除されます。</p><p></p><p>Adapty SDKはペイウォールを2層で保存します。上記の定期更新キャッシュと[フォールバックペイウォール](unity-use-fallback-paywalls)です。また、CDNを使用してペイウォールを高速に取得し、CDNが利用できない場合のスタンドアロンフォールバックサーバーも用意しています。このシステムは、インターネット接続が不安定な環境でも常に最新バージョンのペイウォールを確実に取得できるよう設計されています。</p> | | **loadTimeout** | デフォルト: 5秒 | <p>このメソッドのタイムアウトを制限します。タイムアウトに達した場合、キャッシュデータまたはローカルフォールバックが返されます。</p><p></p><p>このメソッドは内部で複数のリクエストを実行する場合があるため、まれに `loadTimeout` で指定した時間よりわずかに遅れてタイムアウトすることがあります。</p> | プロダクトIDはハードコードしないでください!ペイウォールはリモートで設定されるため、利用可能なプロダクト、プロダクトの数、特典(無料トライアルなど)は時間とともに変わる場合があります。これらのシナリオをコードで処理するようにしてください。 例えば、最初に2つのプロダクトを取得した場合、アプリはその2つを表示します。後で3つのプロダクトを取得した場合も、コード変更なしにすべての3つを表示できるようにしてください。ハードコードが必要なのはプレースメントIDだけです。 レスポンスパラメータ: | パラメータ | 説明 | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- | | Paywall | プロダクトIDのリスト、ペイウォール識別子、リモートコンフィグ、その他いくつかのプロパティを含む [`AdaptyPaywall`](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_paywall.html) オブジェクト。 | ## プロダクトの取得 \{#fetch-products\} ペイウォールを取得したら、対応するプロダクト配列を取得できます: ```csharp showLineNumbers Adapty.GetPaywallProducts(paywall, (products, error) => { if(error != null) { // handle the error return; } // products - the requested products array }); ``` レスポンスパラメータ: | パラメータ | 説明 | | :-------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Products | プロダクト識別子、プロダクト名、価格、通貨、サブスクリプション期間、その他いくつかのプロパティを含む [`AdaptyPaywallProduct`](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_paywall_product.html) オブジェクトのリスト。 | 独自のペイウォールデザインを実装する場合、[`AdaptyPaywallProduct`](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_paywall_product.html) オブジェクトのプロパティへのアクセスが必要になるでしょう。以下によく使用されるプロパティを示しますが、すべての利用可能なプロパティの詳細はリンク先のドキュメントを参照してください。 | プロパティ | 説明 | |-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Title** | プロダクトのタイトルを表示するには `product.LocalizedTitle` を使用してください。ローカライゼーションはデバイス自体のロケールではなく、ユーザーが選択しているストアの国に基づきます。 | | **Price** | ローカライズされた価格を表示するには `product.Price.LocalizedString` を使用してください。このローカライゼーションはデバイスのロケール情報に基づきます。`product.Price.Amount` を使用して価格を数値として取得することもできます。値はローカル通貨で提供されます。関連する通貨記号を取得するには `product.Price.CurrencySymbol` を使用してください。 | | **Subscription Period** | 期間(週、月、年など)を表示するには `product.Subscription?.LocalizedPeriod` を使用してください。このローカライゼーションはデバイスのロケールに基づきます。プログラムでサブスクリプション期間を取得するには `product.Subscription?.Period` を使用してください。そこから `Unit` 列挙型にアクセスして長さを取得できます(`AdaptySubscriptionPeriodUnit.Day`、`AdaptySubscriptionPeriodUnit.Week`、`AdaptySubscriptionPeriodUnit.Month`、`AdaptySubscriptionPeriodUnit.Year`、または `AdaptySubscriptionPeriodUnit.Unknown`)。`NumberOfUnits` の値で期間単位の数を取得できます。例えば、四半期サブスクリプションの場合、Unit プロパティに `AdaptySubscriptionPeriodUnit.Month`、NumberOfUnits プロパティに `3` が表示されます。 | | **Introductory Offer** | サブスクリプションに初回オファーが含まれているかをバッジなどで示すには、`product.Subscription?.Offer?.Phases` プロパティを確認してください。これは最大2つの割引フェーズ(無料トライアルフェーズと初回価格フェーズ)を含むことができるリストです。各フェーズオブジェクトには以下の便利なプロパティが含まれます:<br/>• `PaymentMode`: `AdaptyPaymentMode.FreeTrial`、`AdaptyPaymentMode.PayAsYouGo`、`AdaptyPaymentMode.PayUpFront`、`AdaptyPaymentMode.Unknown` の値を持つ列挙型。無料トライアルは `AdaptyPaymentMode.FreeTrial` 型になります。<br/>• `Price`: 割引価格(数値)。無料トライアルの場合は `0` になります。<br/>• `LocalizedNumberOfPeriods`: オファーの長さをデバイスのロケールでローカライズした文字列。例えば、3日間のトライアルオファーの場合、このフィールドに `"3 days"` が表示されます。<br/>• `SubscriptionPeriod`: オファー期間の個別の詳細をこのプロパティで取得することもできます。オファーに対しても前のセクションと同様に機能します。<br/>• `LocalizedSubscriptionPeriod`: ユーザーのロケールに対応した割引のサブスクリプション期間のフォーマット済み文字列。 | ## デフォルトオーディエンスペイウォールでペイウォール取得を高速化する \{#speed-up-paywall-fetching-with-default-audience-paywall\} 通常、ペイウォールはほぼ即座に取得されるため、このプロセスを高速化することを心配する必要はありません。ただし、多数のオーディエンスやペイウォールがあり、ユーザーのインターネット接続が弱い場合、ペイウォールの取得に予想以上の時間がかかることがあります。そのような状況では、ペイウォールをまったく表示しないよりも、デフォルトのペイウォールを表示してスムーズなユーザー体験を確保したい場合があります。 この問題に対処するには、`GetPaywallForDefaultAudience` メソッドを使用します。このメソッドは **All Users** オーディエンス向けの指定プレースメントのペイウォールを取得します。ただし、上記の[ペイウォールの取得](#fetch-paywall)セクションで詳述した `getPaywall` メソッドでペイウォールを取得することが推奨アプローチであることを理解しておくことが重要です。 :::warning `GetPaywallForDefaultAudience` の代わりに `GetPaywall` の使用を検討してください。前者には以下の重要な制限があります: - **互換性の問題**: 複数のアプリバージョンをサポートする際に問題が生じる可能性があり、後方互換性のあるデザインが必要か、古いバージョンで表示が崩れることを許容する必要があります。 - **パーソナライゼーションなし**: 「All Users」オーディエンス向けのコンテンツのみ表示され、国、アトリビューション、カスタム属性に基づくターゲティングが無効になります。 ユースケースでこれらのデメリットよりも高速な取得が重要な場合は、以下のように `GetPaywallForDefaultAudience` を使用してください。それ以外の場合は、[上記](#fetch-paywall)で説明した `GetPaywall` を使用してください。 ::: ```csharp showLineNumbers Adapty.GetPaywallForDefaultAudience("YOUR_PLACEMENT_ID", "en", (paywall, error) => { if(error != null) { // handle the error return; } // paywall - the resulting object }); ``` パラメータ: | パラメータ | 必須/任意 | 説明 | |---------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **placementId** | 必須 | 対象の[プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** | <p>任意</p><p>デフォルト: `en`</p> | <p>ペイウォールのローカライゼーションの識別子。このパラメータはマイナス(**-**)文字で区切られた1つまたは2つのサブタグで構成される言語コードを指定します。最初のサブタグは言語、2番目は地域を表します。</p><p></p><p>例: `en` は英語、`pt-br` はブラジルポルトガル語を表します。</p> | | **fetchPolicy** | デフォルト: `.reloadRevalidatingCacheData` | <p>デフォルトでは、SDKはサーバーからデータを読み込もうとし、失敗した場合はキャッシュデータを返します。ユーザーが常に最新のデータを取得できるため、このオプションを推奨します。</p><p></p><p>ただし、ユーザーのインターネット接続が不安定だと思われる場合は、`.returnCacheDataElseLoad` を使用してキャッシュデータが存在する場合に返すことを検討してください。この場合、ユーザーは最新データを取得できないことがありますが、通信状況に関わらず読み込みが速くなります。キャッシュは定期的に更新されるため、セッション中のネットワークリクエスト削減に安全に使用できます。</p><p></p><p>キャッシュはアプリの再起動後も保持され、アプリの再インストールまたは手動でのクリア時のみ削除されます。</p><p></p><p>Adapty SDKはペイウォールをローカルに2層で保存します。上記の定期更新キャッシュとフォールバックペイウォールです。また、CDNを使用してペイウォールを高速に取得し、CDNが利用できない場合のスタンドアロンフォールバックサーバーも用意しています。このシステムは、インターネット接続が不安定な環境でも常に最新バージョンのペイウォールを確実に取得できるよう設計されています。</p> | --- # File: present-remote-config-paywalls-unity --- --- title: "Unity SDKでリモートコンフィグによるペイウォールをレンダリングする" description: "Adapty Unity SDKでリモートコンフィグのペイウォールを表示し、ユーザー体験をパーソナライズする方法を解説します。" --- リモートコンフィグを使ってペイウォールをカスタマイズした場合、ユーザーに表示するためにモバイルアプリのコードでレンダリングを実装する必要があります。リモートコンフィグはニーズに合わせた柔軟性を提供するため、何を含めるか、ペイウォールのビューがどのように表示されるかはすべて開発者が管理します。リモートコンフィグを取得するメソッドを提供しているので、リモートコンフィグで設定したカスタムペイウォールを自由に表示できます。 ## ペイウォールのリモートコンフィグを取得して表示する \{#get-paywall-remote-config-and-present-it\} ペイウォールのリモートコンフィグを取得するには、`remoteConfig` プロパティにアクセスして必要な値を取り出します。 ```csharp showLineNumbers Adapty.GetPaywall("YOUR_PLACEMENT_ID", (paywall, error) => { if (error != null) { // handle the error return; } // Access remote config dictionary var dictionary = paywall.RemoteConfig?.Dictionary; var headerText = dictionary?["header_text"] as string; // Or access raw JSON data var jsonData = paywall.RemoteConfig?.Data; }); ``` 必要な値をすべて取得したら、それらをレンダリングして視覚的に魅力的なページに組み立てます。さまざまなモバイル端末の画面サイズや向きに対応したデザインにして、異なるデバイスでもシームレスで使いやすい体験を提供してください。 :::warning Adapty アナリティクスがファネルや A/B テストのデータを取得できるよう、以下で説明する[ペイウォール表示イベントの記録](present-remote-config-paywalls-unity#track-paywall-view-events)を必ず行ってください。 ::: ペイウォールの表示が完了したら、購入フローの設定に進みます。ユーザーが購入する際は、ペイウォールのプロダクトを引数として `.MakePurchase()` を呼び出すだけです。`.MakePurchase()` メソッドの詳細については、[購入の実装](unity-making-purchases)をご覧ください。 インターネット接続やキャッシュが利用できない場合にユーザーに表示される[フォールバックペイウォールの作成](unity-use-fallback-paywalls)をお勧めします。これにより、そのような状況でもスムーズな体験が確保されます。 ## ペイウォール表示イベントをトラッキングする \{#track-paywall-view-events\} Adapty はペイウォールのパフォーマンス測定をサポートしています。購入データは自動的に収集されますが、ペイウォールの表示ログはユーザーがペイウォールを見たタイミングを把握しているのは開発者だけのため、手動での記録が必要です。 ペイウォール表示イベントをログに記録するには `.LogShowPaywall(paywall)` を呼び出すだけで、ファネルや A/B テストのペイウォール指標に反映されます。 :::important [ペイウォールビルダー](adapty-paywall-builder)で作成したペイウォールを表示する場合は、`.LogShowPaywall(paywall)` を呼び出す必要はありません。 ::: ```csharp showLineNumbers Adapty.LogShowPaywall(paywall, (error) => { // handle the error }); ``` リクエストパラメーター: | パラメーター | 必須 | 説明 | | :---------- | :------- |:------------------------------------------------------------------| | **paywall** | 必須 | [`AdaptyPaywall`](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_paywall.html) オブジェクト。 | --- # File: unity-making-purchases --- --- title: "Unity SDKでモバイルアプリ内購入を行う" description: "Adaptyを使用したアプリ内課金とサブスクリプションの処理ガイド。" --- モバイルアプリ内にペイウォールを表示することは、ユーザーにプレミアムコンテンツやサービスへのアクセスを提供するための重要なステップです。ただし、[ペイウォールビルダー](adapty-paywall-builder)を使ってペイウォールをカスタマイズしている場合は、ペイウォールを表示するだけで購入処理が完結します。 ペイウォールビルダーを使用しない場合は、`.makePurchase()` という別のメソッドを使って購入を完了し、対象のコンテンツをアンロックする必要があります。このメソッドは、ユーザーがペイウォールを操作して購入を進めるための入口となります。 ペイウォールに購入しようとしているプロダクトに対して有効なプロモーションオファーが設定されている場合、Adaptyは購入時に自動的にそのオファーを適用します。 :::warning 初回オファーが自動的に適用されるのは、ペイウォールビルダーで設定されたペイウォールを使用している場合のみです。 それ以外の場合は、[iOS での初回オファーの適用資格をユーザーごとに確認する](fetch-paywalls-and-products#check-intro-offer-eligibility-on-ios)必要があります。このステップを省略すると、リリース時にアプリが審査でリジェクトされる可能性があります。また、初回オファーの対象となるユーザーに通常価格が請求されてしまう場合もあります。 ::: [初期設定](quickstart)をすべてのステップを漏らさず完了していることを確認してください。設定が完了していないと、購入の検証ができません。 ## 購入を行う \{#make-purchase\} :::note **[ペイウォールビルダー](adapty-paywall-builder)を使用していますか?** 購入は自動的に処理されるため、このステップは省略できます。 **ステップバイステップのガイドをお探しですか?** エンドツーエンドの実装手順については、[クイックスタートガイド](unity-implement-paywalls-manually)をご確認ください。 ::: ```csharp showLineNumbers using AdaptySDK; void MakePurchase(AdaptyPaywallProduct product) { Adapty.MakePurchase(product, (result, error) => { switch (result.Type) { case AdaptyPurchaseResultType.Pending: // handle pending purchase break; case AdaptyPurchaseResultType.UserCancelled: // handle purchase cancellation break; case AdaptyPurchaseResultType.Success: var profile = result.Profile; // handle successfull purchase break; default: break; } }); } ``` リクエストパラメーター: | パラメーター | 必須/任意 | 説明 | | :---------- | :------- |:------------------------------------------------------------------------------------------------------| | **Product** | 必須 | ペイウォールから取得した [`AdaptyPaywallProduct`](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_paywall_product.html) オブジェクト。 | レスポンスパラメーター: | パラメーター | 説明 | |---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Profile** | <p>リクエストが成功した場合、このオブジェクトがレスポンスに含まれます。[AdaptyProfile](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_profile.html) オブジェクトは、ユーザーのアクセスレベル、サブスクリプション、アプリ内の買い切り購入に関する包括的な情報を提供します。</p><p>アクセスレベルのステータスを確認して、ユーザーが必要なアクセス権を持っているかどうかを判断してください。</p> | :::warning **注意:** Apple の StoreKit バージョンが v2.0 未満、かつ Adapty SDK バージョンが v2.9.0 未満の場合は、代わりに [Apple App Store 共有シークレット](app-store-connection-configuration#step-5-enter-app-store-shared-secret)を提供する必要があります。この方法は現在 Apple によって非推奨とされています。 ::: ## 購入時にサブスクリプションを変更する \{#change-subscription-when-making-a-purchase\} ユーザーが現在のサブスクリプションを更新する代わりに新しいサブスクリプションを選択する場合、動作はアプリストアによって異なります。 - App Storeでは、サブスクリプショングループ内でサブスクリプションが自動的に更新されます。ユーザーがあるグループのサブスクリプションを購入した際に、別のグループのサブスクリプションがすでに有効な場合、両方のサブスクリプションが同時に有効になります。 - Google Playでは、サブスクリプションは自動的に更新されません。以下に説明するように、モバイルアプリのコードで切り替え処理を管理する必要があります。 Androidで別のサブスクリプションに切り替えるには、追加パラメーターを指定して `.makePurchase()` メソッドを呼び出します。 ```csharp showLineNumbers // Create subscription update parameters var subscriptionUpdateParams = new AdaptySubscriptionUpdateParameters( "old_product_id", // Product ID of the current subscription AdaptySubscriptionUpdateReplacementMode.WithTimeProration ); Adapty.MakePurchase(product, subscriptionUpdateParams, (profile, error) => { if(error != null) { // Handle the error return; } // successful cross-grade }); ``` 追加のリクエストパラメーター: | パラメーター | 必須/任意 | 説明 | | :--------------------------- | :------- |:-------------------------------------------------------------------------------------------------------| | **subscriptionUpdateParams** | 必須 | [`AdaptySubscriptionUpdateParameters`](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_subscription_update_parameters.html) オブジェクト。 | サブスクリプションと置き換えモードの詳細については、Google Developerのドキュメントをご参照ください。 - [置き換えモードについて](https://developer.android.com/google/play/billing/subscriptions#replacement-modes) - [置き換えモードに関するGoogleの推奨事項](https://developer.android.com/google/play/billing/subscriptions#replacement-recommendations) - 置き換えモード [`CHARGE_PRORATED_PRICE`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode#CHARGE_PRORATED_PRICE())。注意: このメソッドはサブスクリプションのアップグレードにのみ使用できます。ダウングレードはサポートされていません。 - 置き換えモード [`DEFERRED`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode#DEFERRED())。注意: 実際のサブスクリプション変更は、現在のサブスクリプションの請求期間が終了した時点でのみ発生します。 ## iOSでオファーコードを利用する \{#redeem-offer-codes-in-ios\} --- no_index: true --- import Callout from '../../../components/Callout.astro'; <Details> <summary>オファーコードについて</summary> オファーコードを使うと、特定のユーザーに割引や無料トライアルを提供できます。自動的に適用される通常のオファーとは異なり、オファーコードはメールキャンペーン、SNS、印刷物など、アプリの外で配布します。ユーザーはApp Storeでコードを入力するか、引き換えURLを使うか、アプリ内ダイアログから利用できます。 オファーコードを設定するには、App Store Connectでサブスクリプションを開き、**Offer Codes** セクションに移動してください。オファーコードは[3種類](https://developer.apple.com/help/app-store-connect/manage-subscriptions/set-up-subscription-offer-codes)作成できます。 - **Free** — 指定した期間はサブスクリプションが無料になり、次の更新から通常価格になります。 - **Pay as you go** — 指定した期間、各請求サイクルに割引価格が適用され、その後は通常価格で更新されます。 - **Pay up front** — オファー期間全体に対して一括で割引価格を支払い、その後は通常価格で更新されます。 オファーコードをAdaptyに追加する必要はありません。Appleはオファー期間中のすべてのトランザクションにオファーコードカテゴリのタグを付与します。これには最初の引き換えとその後の割引更新がすべて含まれます。Adaptyはこのタグを検出し、各トランザクションをオファーカテゴリ `offer_code` として記録します。オファー期間が終了してサブスクリプションが通常価格で更新されると、タグは付与されなくなります。[Adapty ダッシュボード](controls-filters-grouping-compare-proceeds)のアナリティクスで **Offer Code** オファータイプによるフィルタリングが可能です。 #### 収益の差異が生じた場合のトラブルシューティング \{#revenue-discrepancy-troubleshooting\} オファーコードのトランザクションが、割引価格ではなく通常価格でAdaptyに記録されている場合は、App Store Connectで以下を確認してください。 - オファーコードに、ユーザーが引き換え可能なすべての地域に対して正しい価格が設定されているか。 - ユーザーの特定の国や地域に対してオファー価格が設定されているか。Appleはトランザクションに地域価格を含めて送信します。その地域のオファー価格が設定されていない場合、Appleは通常価格を送信することがあります。 [Adapty ダッシュボード](controls-filters-grouping-compare-proceeds)で、**Offer Code** オファータイプと **Offer Discount Type** フィルターを使ってオファーコードのトランザクションをフィルタリング・確認できます。 #### レガシープロモコード(非推奨) \{#legacy-promo-codes-deprecated\} <Callout type="warning"> Appleは2026年3月にアプリ内課金向けのプロモコードを廃止しました。オファーコードはより多くの機能(適格性の設定、有効期限、四半期あたり最大100万コード)を備えた後継機能です。アプリ内課金にプロモコードを使用していた場合は、App Store Connectでオファーコードに移行してください。 </Callout> レガシープロモコード(アプリのバージョンごとに最大100件)は、サブスクリプションへの無料アクセスを付与していました。オファーコードとは異なり、Appleはプロモコードのトランザクションに割引情報を含めず、レシートには通常価格が記載されていました。そのため、Adaptyはこれらのトランザクションを通常価格で記録し、Adaptyアナリティクスとレポートの間に収益の差異が生じていました。 本来は無料であるべきトランザクションが通常価格で記録されている履歴がある場合、それはレガシープロモコードによるものと考えられます。これらのコードは現在廃止されているため、正確な収益追跡のためにオファーコードに移行してください。 </Details> アプリでコード引き換えシートを表示するには: ```csharp showLineNumbers Adapty.PresentCodeRedemptionSheet((error) => { // handle the error }); ``` :::danger 私たちの観察によると、一部のアプリではオファーコード引き換えシートが正常に動作しないことがあります。ユーザーをApp Storeに直接リダイレクトすることをお勧めします。 そのためには、以下の形式のURLを開く必要があります: `https://apps.apple.com/redeem?ctx=offercodes&id={apple_app_id}&code={code}` ::: ## プリペイドプランを管理する(Android) \{#manage-prepaid-plans-android\} アプリユーザーが[プリペイドプラン](https://developer.android.com/google/play/billing/subscriptions#prepaid-plans)(例: 数か月分の非更新型サブスクリプションを購入する)を利用できる場合、プリペイドプランに対して[保留中のトランザクション](https://developer.android.com/google/play/billing/subscriptions#pending)を有効にできます。 ```csharp showLineNumbers title="Unity" using UnityEngine; using AdaptySDK; var builder = new AdaptyConfiguration.Builder("YOUR_API_KEY") .SetGoogleEnablePendingPrepaidPlans(true); Adapty.Activate(builder.Build(), (error) => { if (error != null) { // handle the error return; } }); ``` --- # File: unity-restore-purchase --- --- title: "Unity SDKで購入を復元する" description: "Adaptyで購入を復元してシームレスなユーザー体験を確保する方法を学びましょう。" --- iOSとAndroidにおける購入の復元は、ユーザーが再度課金されることなく、サブスクリプションやアプリ内課金などのコンテンツへのアクセスを取り戻せる機能です。アプリをアンインストール・再インストールしたり、新しいデバイスに移行したりしたユーザーが、過去に購入したコンテンツに再アクセスしたい場合に特に役立ちます。 :::note [ペイウォールビルダー](adapty-paywall-builder)で作成したペイウォールでは、追加のコードなしで購入が自動的に復元されます。その場合は、この手順をスキップできます。 ::: [ペイウォールビルダー](adapty-paywall-builder)を使用せずにペイウォールをカスタマイズしている場合に購入を復元するには、`.restorePurchases()` メソッドを呼び出してください。 ```csharp showLineNumbers Adapty.RestorePurchases((profile, error) => { if (error != null) { // handle the error return; } var accessLevel = profile.AccessLevels["YOUR_ACCESS_LEVEL"]; if (accessLevel != null && accessLevel.IsActive) { // restore access } }); ``` レスポンスパラメーター: | パラメーター | 説明 | |---------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Profile** | <p>[`AdaptyProfile`](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_profile.html) オブジェクト。このモデルには、アクセスレベル、サブスクリプション、非サブスクリプション購入に関する情報が含まれています。</p><p>**アクセスレベルのステータス**を確認して、ユーザーがアプリにアクセスできるかどうかを判断してください。</p> | :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: --- # File: implement-observer-mode-unity --- --- title: "Unity SDKにオブザーバーモードを実装する" description: "Unity SDKのAdaptyでオブザーバーモードを実装し、ユーザーのサブスクリプションイベントを追跡します。" --- すでに独自の購入インフラを持っており、すぐにAdaptyへ完全移行する準備が整っていない場合は、[オブザーバーモード](observer-vs-full-mode)を検討してみてください。基本的な使い方では、オブザーバーモードは高度なアナリティクスやアトリビューション・アナリティクスシステムとのシームレスな連携を提供します。 この方法で問題なければ、必要な作業は以下の2点だけです: 1. `observerMode` パラメータを `true` に設定して、Adapty SDKの設定時にオブザーバーモードを有効にします。設定手順については[Unity](sdk-installation-unity#activate-adapty-module-of-adapty-sdk)を参照してください。 2. 既存の購入インフラからAdaptyへ[トランザクションを報告する](report-transactions-observer-mode-unity)。 ### オブザーバーモードのセットアップ \{#observer-mode-setup\} 購入とサブスクリプションのステータスを自分で管理し、サブスクリプションイベントやアナリティクスの送信にAdaptyを使用する場合は、オブザーバーモードを有効にしてください。 :::important オブザーバーモードで動作している場合、Adapty SDKはトランザクションをクローズしません。そのため、必ずご自身でトランザクションを処理するようにしてください。 ::: ```csharp showLineNumbers title="C#" using UnityEngine; using AdaptySDK; public class AdaptyListener : MonoBehaviour, AdaptyEventListener { void Start() { DontDestroyOnLoad(this.gameObject); Adapty.SetEventListener(this); var builder = new AdaptyConfiguration.Builder("YOUR_PUBLIC_SDK_KEY") .SetObserverMode(true); // Enable observer mode Adapty.Activate(builder.Build(), (error) => { if (error != null) { // handle the error return; } }); } public void OnLoadLatestProfile(AdaptyProfile profile) { } public void OnInstallationDetailsSuccess(AdaptyInstallationDetails details) { } public void OnInstallationDetailsFail(AdaptyError error) { } } ``` パラメータ: | パラメータ | 説明 | |--------------|------------------------------------------------------------------------------------------------------------| | observerMode | [オブザーバーモード](observer-vs-full-mode)を制御するブール値です。デフォルト値は `false` です。 | ## オブザーバーモードでAdaptyのペイウォールを使用する \{#using-adapty-paywalls-in-observer-mode\} Adaptyのペイウォールやアナリティクス機能も使いたい場合は可能ですが、オブザーバーモードでは追加のセットアップが必要です。上記の手順に加えて、以下の対応が必要になります: 1. [リモートコンフィグのペイウォール](present-remote-config-paywalls-unity)と同様にペイウォールを表示する。 3. 購入トランザクションに[ペイウォールを関連付ける](report-transactions-observer-mode-unity)。 --- # File: report-transactions-observer-mode-unity --- --- title: "Unity SDKのObserverモードでトランザクションを報告する" description: "Unity SDKのAdapty Observerモードで購入トランザクションを報告し、ユーザーインサイトと収益トラッキングを実現します。" --- <Tabs groupId="sdk-version" queryString> <TabItem value="current" label="Adapty SDK v3.4+(現行版)" default> Observerモードでは、Adapty SDKは既存の購入システムを通じて行われた購入を自動的に追跡できません。アプリストアからトランザクションを報告する必要があります。アナリティクスのエラーを防ぐため、アプリのリリース**前**にこの設定を行うことが重要です。 `reportTransaction`を使用して、各トランザクションをAdaptyに明示的に報告してください。 :::warning **トランザクションの報告を省略しないでください!** `ReportTransaction`を呼び出さないと、Adaptyはトランザクションを認識できず、アナリティクスに表示されず、インテグレーションにも送信されません。 ::: Adaptyのペイウォールを使用している場合は、トランザクションを報告する際に`variationId`を含めてください。これにより、購入がトリガーしたペイウォールと関連付けられ、正確なペイウォールアナリティクスが確保されます。 ```csharp showLineNumbers Adapty.ReportTransaction( "YOUR_TRANSACTION_ID", "PAYWALL_VARIATION_ID", // optional (error) => { // handle the error }); ``` パラメーター: | パラメーター | 必須/任意 | 説明 | | ------------- | -------- |------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | transactionId | 必須 | <ul><li> iOS の場合:トランザクションの識別子。</li><li> Android の場合:購入の文字列識別子 `purchase.getOrderId`。ここで purchase は billing library の [Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase) クラスのインスタンスです。</li></ul> | | variationId | 任意 | バリアントの文字列識別子。[AdaptyPaywall](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_paywall.html) オブジェクトの `variationId` プロパティを使用して取得できます。 | </TabItem> <TabItem value="old" label="Adapty SDK 3.3.x(レガシー)" default> Observerモードでは、Adapty SDKは既存の購入システムを通じて行われた購入を自動的に追跡できません。アプリストアからトランザクションを報告するか、リストアする必要があります。アナリティクスのエラーを防ぐため、アプリのリリース**前**にこの設定を行うことが重要です。 両プラットフォームで`reportTransaction`を使用して各トランザクションを明示的に報告し、Androidでは追加のステップとして`restorePurchases`を使用してAdaptyに認識させてください。 :::warning **トランザクションの報告と購入のリストアを省略しないでください!** これらのメソッドを呼び出さないと、Adaptyはトランザクションを認識できず、アナリティクスに表示されず、インテグレーションにも送信されません。 ::: Adaptyのペイウォールを使用している場合は、トランザクションを報告する際に`PAYWALL_VARIATION_ID`を含めてください。これにより、購入がトリガーしたペイウォールと関連付けられ、正確なペイウォールアナリティクスが確保されます。 ```csharp showLineNumbers // every time when calling transasction.finish() #if UNITY_ANDROID && !UNITY_EDITOR Adapty.RestorePurchases((profile, error) => { // handle the error }); #endif Adapty.ReportTransaction( "YOUR_TRANSACTION_ID", "PAYWALL_VARIATION_ID", // optional (error) => { // handle the error }); ``` パラメーター: | パラメーター | 必須/任意 | 説明 | | ------------- | -------- |--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | transactionId | 必須 | <ul><li> iOS、StoreKit 1 の場合:[SKPaymentTransaction](https://developer.apple.com/documentation/storekit/skpaymenttransaction) オブジェクト。</li><li> iOS、StoreKit 2 の場合:[Transaction](https://developer.apple.com/documentation/storekit/transaction) オブジェクト。</li><li> Android の場合:購入の文字列識別子(`purchase.getOrderId`)。ここで purchase は billing library の [Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase) クラスのインスタンスです。</li></ul> | | variationId | 任意 | バリアントの文字列識別子。[AdaptyPaywall](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_paywall.html) オブジェクトの `variationId` プロパティを使用して取得できます。 | </TabItem> <TabItem value="old2" label="Adapty SDK 3.2.x 以前(レガシー)" default> <Tabs groupId="current-os" queryString> <TabItem value="swift" label="iOS" default> **トランザクションの報告** - バージョン 3.1.x 以前は App Store のトランザクションを自動的に監視するため、手動での報告は不要です。 - バージョン 3.2 は Observer モードをサポートしていません。 </TabItem> <TabItem value="kotlin" label="Android および Android ベースのクロスプラットフォーム" default> **トランザクションの報告** Observerモードで Adapty にトランザクションを報告するには、[モバイルコードでの購入リストア](unity-restore-purchase)ページで説明されているように `restorePurchases` を使用してください。 :::warning **トランザクションの報告を省略しないでください!** `restorePurchases` を呼び出さないと、Adapty はトランザクションを認識できず、アナリティクスに表示されず、インテグレーションにも送信されません。 ::: </TabItem> </Tabs> **トランザクションへのペイウォールの関連付け** Adapty SDK は購入の発生元を判断できません。購入の処理はお客様が行っているためです。そのため、Observerモードでペイウォールや A/B テストを使用する場合は、アプリストアから来たトランザクションをモバイルアプリのコード内で対応するペイウォールと関連付ける必要があります。アプリのリリース前に正しく設定することが重要です。設定を誤るとアナリティクスにエラーが発生します。 ```csharp Adapty.SetVariationForTransaction("<variationId>", "<transactionId>", (error) => { if(error != null) { // handle the error return; } // successful binding }); ``` | パラメーター | 必須/任意 | 説明 | | ------------------------------------------------------ | -------- |-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | transactionId | 必須 | <p>iOS、StoreKit 1 の場合:[SKPaymentTransaction](https://developer.apple.com/documentation/storekit/skpaymenttransaction) オブジェクト。</p><p>iOS、StoreKit 2 の場合:[Transaction](https://developer.apple.com/documentation/storekit/transaction) オブジェクト。</p><p>Android の場合:購入の文字列識別子(purchase.getOrderId)。ここで purchase は billing library の [Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase) クラスのインスタンスです。</p> | | variationId | 必須 | バリアントの文字列識別子。[AdaptyPaywall](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_paywall.html) オブジェクトの `variationId` プロパティを使用して取得できます。 | </TabItem> </Tabs> --- # File: unity-troubleshoot-purchases --- --- title: "Unity SDKでの購入に関するトラブルシューティング" description: "Unity SDKでの購入に関するトラブルシューティング" --- このガイドでは、Unity SDKで購入を手動実装する際によく発生する問題の解決方法を説明します。 ## makePurchaseが正常に呼び出されるが、プロファイルが更新されない \{#makepurchase-is-called-successfully-but-the-profile-is-not-being-updated\} **問題**: `makePurchase` メソッドが正常に完了するのに、ユーザーのプロファイルとサブスクリプションのステータスがAdaptyで更新されない。 **原因**: 通常、Google Play Storeのセットアップが不完全か、設定に問題があることを示しています。 **解決策**: [Google Playのセットアップ手順](initial-android)がすべて完了しているか確認してください。 ## makePurchaseが2回呼び出される \{#makepurchase-is-invoked-twice\} **問題**: 同じ購入に対して `makePurchase` メソッドが複数回呼び出されている。 **原因**: UIの状態管理の問題や、ユーザーが素早く操作したことで購入フローが複数回トリガーされる場合に起こります。 **解決策**: [Google Playのセットアップ手順](initial-android)がすべて完了しているか確認してください。 ## オブザーバーモードでのAdaptyError.cantMakePayments \{#adaptyerrorcantmakepayments-in-observer-mode\} **問題**: オブザーバーモードで `makePurchase` を使用すると `AdaptyError.cantMakePayments` が発生する。 **原因**: オブザーバーモードでは、購入はアプリ側で処理する必要があり、Adaptyの `makePurchase` メソッドは使用できません。 **解決策**: 購入に `makePurchase` を使用している場合は、オブザーバーモードをオフにしてください。`makePurchase` を使用するか、オブザーバーモードでアプリ側で購入を処理するか、どちらか一方を選択する必要があります。詳細は[オブザーバーモードの実装](implement-observer-mode-unity)を参照してください。 ## Adaptyエラー: (code: 103, message: Play Market request failed on purchases updated: responseCode=3, debugMessage=Billing Unavailable, detail: null) \{#adapty-error-code-103-message-play-market-request-failed-on-purchases-updated-responsecode3-debugmessagebilling-unavailable-detail-null\} **問題**: Google Play Storeから課金が利用できないというエラーが返ってくる。 **原因**: このエラーはAdaptyとは無関係です。端末で課金が利用できないことを示すGoogle Play Billing Libraryのエラーです。 **解決策**: このエラーはAdaptyとは無関係です。Play Storeのドキュメントで詳細を確認できます: [BillingResultレスポンスコードの処理](https://developer.android.com/google/play/billing/errors#billing_unavailable_error_code_3) | Play Billing | Android Developers。 ## makePurchasesCompletionHandlersが見つからない \{#not-found-makepurchasescompletionhandlers\} **問題**: `makePurchasesCompletionHandlers` が見つからないという問題が発生している。 **原因**: 通常、サンドボックステストに関連する問題です。 **解決策**: 新しいサンドボックスユーザーを作成して再試行してください。サンドボックス環境での購入完了ハンドラーの問題はこれで解決することが多いです。 ## その他の問題 \{#other-issues\} **問題**: 上記に該当しない購入関連の問題が発生している。 **解決策**: 必要に応じて[マイグレーションガイド](unity-sdk-migration-guides)を使用してSDKを最新バージョンに移行してください。多くの問題は新しいSDKバージョンで解決されています。 --- # File: unity-identifying-users --- --- title: "Unity SDKでユーザーを識別する" description: "Adapty SDKを使用してUnityアプリでユーザーを識別する方法をご紹介します。" --- Adaptyはすべてのユーザーに対して内部プロファイルIDを作成します。ただし、独自の認証システムをお持ちの場合は、Customer User IDを設定することをお勧めします。[Profiles](profiles-crm)セクションでCustomer User IDによってユーザーを検索したり、すべてのインテグレーションに送信される[サーバーサイドAPI](getting-started-with-server-side-api)でも使用できます。 ### 設定時にCustomer User IDを設定する \{#setting-customer-user-id-on-configuration\} 設定時にユーザーIDがある場合は、`.activate()`メソッドの`customerUserId`パラメーターとして渡すだけです。 ```csharp showLineNumbers using UnityEngine; using AdaptySDK; var builder = new AdaptyConfiguration.Builder("YOUR_API_KEY") .SetCustomerUserId("YOUR_USER_ID"); Adapty.Activate(builder.Build(), (error) => { if (error != null) { // handle the error return; } }); ``` :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: ### 設定後にCustomer User IDを設定する \{#setting-customer-user-id-after-configuration\} SDK設定時にユーザーIDがない場合は、`.identify()`メソッドを使っていつでも後から設定できます。このメソッドが最もよく使われるのは、登録後や認証後、つまりユーザーが匿名ユーザーから認証済みユーザーに切り替わるタイミングです。 ```csharp showLineNumbers Adapty.Identify("YOUR_USER_ID", (error) => { if(error == null) { // successful identify } }); ``` リクエストパラメーター: - **Customer User ID**(必須):文字列のユーザー識別子。 :::warning 重要なユーザーデータの再送信について ユーザーが再度ログインした場合など、Adaptyのサーバーにすでにそのユーザーの情報が存在していることがあります。このような場合、Adapty SDKは自動的に新しいユーザーとして切り替わります。カスタム属性やサードパーティネットワークからのアトリビューションなど、匿名ユーザーに対して送信したデータがある場合は、識別されたユーザーに対してそのデータを再送信する必要があります。 また、新しいユーザーのデータが異なる場合があるため、ユーザーを識別した後はすべてのペイウォールとプロダクトを再取得する必要があることにも注意してください。 ::: ### ログアウトとログイン \{#logging-out-and-logging-in\} `.logout()`メソッドを呼び出すことで、いつでもユーザーをログアウトできます。 ```csharp showLineNumbers Adapty.Logout((error) => { if(error == null) { // successful logout } }); ``` その後、`.identify()`メソッドを使ってユーザーをログインさせることができます。 ## `appAccountToken`を設定する(iOS) \{#assign-appaccounttoken-ios\} [`appAccountToken`](https://developer.apple.com/documentation/storekit/product/purchaseoption/appaccounttoken(_:))は、App Storeのトランザクションと内部ユーザーIDを紐づけるための**UUID**です。 StoreKitはこのトークンをすべてのトランザクションに関連付けるため、バックエンドでApp Storeのデータを自社ユーザーと照合できます。 ユーザーごとに安定したUUIDを生成し、デバイスをまたいで同じアカウントに再利用してください。 これにより、購入情報やApp Storeの通知が正しく紐づけられます。 トークンの設定方法は2通りあります。SDK有効化時とユーザー識別時です。 :::important `appAccountToken`は必ず`customerUserId`と一緒に渡してください。 トークンだけを渡しても、トランザクションには含まれません。 ::: ```csharp showLineNumbers title="Unity" using UnityEngine; using AdaptySDK; using System; // During configuration: var appAccountToken = new Guid("YOUR_APP_ACCOUNT_TOKEN"); var builder = new AdaptyConfiguration.Builder("YOUR_API_KEY") .SetCustomerUserId("YOUR_USER_ID", appAccountToken); Adapty.Activate(builder.Build(), (error) => { if (error != null) { // handle the error return; } }); // Or when identifying users Adapty.Identify("YOUR_USER_ID", appAccountToken, (error) => { if (error == null) { // successful identify } }); ``` ## 難読化アカウントIDを設定する(Android) \{#set-obfuscated-account-ids-android\} Google Playでは、ユーザーのプライバシーとセキュリティを強化するために、特定のユースケースで難読化アカウントIDが必要です。これらのIDにより、Google Playはユーザー情報を匿名に保ちながら購入を識別できます。これは特に不正防止やアナリティクスにおいて重要です。 アプリが機密性の高いユーザーデータを扱う場合や、特定のプライバシー規制への準拠が求められる場合に、これらのIDを設定する必要が生じることがあります。難読化IDを使用することで、Google Playは実際のユーザー識別子を公開せずに購入を追跡できます。 ```csharp showLineNumbers title="Unity" using UnityEngine; using AdaptySDK; // During configuration: var builder = new AdaptyConfiguration.Builder("YOUR_API_KEY") .SetCustomerUserId("YOUR_USER_ID", null, "YOUR_OBFUSCATED_ACCOUNT_ID"); Adapty.Activate(builder.Build(), (error) => { if (error != null) { // handle the error return; } }); // Or when identifying users Adapty.Identify("YOUR_USER_ID", null, "YOUR_OBFUSCATED_ACCOUNT_ID", (error) => { if (error == null) { // successful identify } }); ``` ## デバイスをまたいでユーザーを検出する \{#detect-users-across-devices\} --- no_index: true --- SDKが有効化されると、StoreKit(iOS)またはGoogle Play Billing(Android)からユーザーの既存のエンタイトルメントを自動的に読み取り、Adaptyバックエンドと同期します。有効なサブスクリプションは、アプリが`restorePurchases`を呼び出すことなく、Adaptyプロファイルに表示されます。 **自動では行われない**のは、新しいデバイスのプロファイルが元のデバイスと同じユーザーのものであることの認識です。AdaptyはCustomer User IDでプロファイルを照合するため、同一性の継続性はCUIDとして何を使用するかによって異なります。 **デバイス間でAdaptyが検出できること** | あなたの設定 | Adaptyが検出すること | 必要な対応 | | --- | --- | --- | | Customer User ID = `device_id`(アプリのログインなし) | 新しいデバイスは異なるCUIDを取得するため、異なるプロファイルが作成されます。サブスクリプションは**Access level updated**イベントを通じて新しいプロファイルに同期されますが、`subscription_started`は発火しません。新しいプロファイルは元の購入の継承者として扱われます。`subscription_started`に基づくアナリティクスは、リターニングユーザーをカウント不足します。 | リターニングユーザーが既存のプロファイルをデバイス間で照合できるよう、安定したアカウントIDをCustomer User IDとして使用してください。 | | Customer User ID = 安定したアカウントID(すべてのデバイスでログイン) | SDKは`activate()`でサブスクリプションを自動同期し、`identify()`がCUIDで既存のプロファイルを照合します。 | 追加の設定は不要です。IDとサブスクリプションの両方が自動的に解決されます。 | | Apple Family Sharing の継承者 | ファミリーメンバーは**Access level updated**イベントのみを通じてサブスクリプションを受け取ります。`subscription_started`は発火しません。 | **Access level updated**をリッスンしてください。完全なイベントマトリクスは[Apple Family Sharing](apple-family-sharing)を参照してください。 | | 同じApple/Googleアカウント、異なるアプリ内ユーザー | 最初に購入を記録したプロファイルが親になります。その後のプロファイルは継承者チェーンを通じてサブスクリプションを確認し、**Access level updated**イベントが1回発生します。 | ログインを必須にし、あなたのモデルに合った[共有モード](sharing-paid-access-between-user-accounts)を選択してください。 | **新しいデバイスでの購入の復元** ペイウォールにユーザーが操作できる「購入を復元」ボタンを設置してください。Apple App Review(ガイドライン3.1.1)で必須とされており、自動同期がエッジケースを見逃した場合のフォールバックとして機能します。このボタンはSDKの`restorePurchases`を呼び出す必要があります。 初回起動時にプログラムで`restorePurchases`を呼び出すことは、通常の使用では必要ありません。SDKはすでに`activate()`で同等の処理を実行しています。プログラムによる呼び出しは、`activate()`完了後にアクセスが欠落している場合のデバッグなど、強制的に新しいレシートチェックを行う場合にのみ使用してください。 --- # File: unity-setting-user-attributes --- --- title: "Unity SDKでユーザー属性を設定する" description: "Adapty SDKを使用してUnityアプリのユーザー属性とプロファイルデータを更新する方法を学びます。" --- メールアドレスや電話番号などの任意の属性をアプリのユーザーに設定できます。設定した属性は、ユーザー[セグメント](segments)の作成やCRMでの確認に活用できます。 ### ユーザー属性の設定 \{#setting-user-attributes\} ユーザー属性を設定するには、`.updateProfile()`メソッドを呼び出します: ```csharp showLineNumbers var builder = new Adapty.ProfileParameters.Builder() .SetFirstName("John") .SetLastName("Appleseed") .SetBirthday(new DateTime(1970, 1, 3)) .SetGender(ProfileGender.Female) .SetEmail("example@adapty.io"); Adapty.UpdateProfile(builder.Build(), (error) => { if(error != nil) { // handle the error } }); ``` `updateProfile`メソッドで以前に設定した属性はリセットされないことに注意してください。 :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: ### 使用可能なキーの一覧 \{#the-allowed-keys-list\} `AdaptyProfileParameters.Builder`で使用できるキー`<Key>`と値`<Value>`は以下のとおりです: | キー | 値 | |---|-----| | <p>email</p><p>phoneNumber</p><p>firstName</p><p>lastName</p> | String | | gender | 列挙型。使用可能な値:`female`、`male`、`other` | | birthday | Date | ### カスタムユーザー属性 \{#custom-user-attributes\} 独自のカスタム属性を設定することができます。これらは通常、アプリの利用状況に関連します。たとえば、フィットネスアプリなら週あたりの運動回数、語学学習アプリならユーザーの習熟度レベルなどが考えられます。カスタム属性はセグメントに活用してターゲットを絞ったペイウォールやオファーを作成したり、収益に最も影響するプロダクト指標を分析したりするのに役立ちます。 ```csharp showLineNumbers try { builder = builder.SetCustomStringAttribute("string_key", "string_value"); builder = builder.SetCustomDoubleAttribute("double_key", 123.0f); } catch (Exception e) { // handle the exception } ``` 既存のキーを削除するには、`.withRemoved(customAttributeForKey:)`メソッドを使用します: ```csharp showLineNumbers try { builder = builder.RemoveCustomAttribute("key_to_remove"); } catch (Exception e) { // handle the exception } ``` 事前にどのようなカスタム属性が設定されているか確認したい場合は、`AdaptyProfile`オブジェクトの`customAttributes`フィールドを使用してください。 :::warning `customAttributes`の値は最新でない場合があります。ユーザー属性は異なるデバイスからいつでも送信される可能性があるため、最後の同期以降にサーバー上の属性が変更されていることがあります。 ::: ### 制限事項 \{#limits\} - ユーザーあたり最大30個のカスタム属性 - キー名は最大30文字。キー名に使用できる文字は英数字および`_`、`-`、`.`です - 値は文字列または浮動小数点数で、50文字以内 --- # File: unity-listen-subscription-changes --- --- title: "Unity SDKでサブスクリプションステータスを確認する" description: "UnityアプリでAdaptyを使ってユーザーのサブスクリプションステータスを追跡・管理し、顧客維持率を向上させましょう。" --- Adaptyを使えば、サブスクリプションステータスの管理が簡単になります。プロダクトIDをコードに直接記述する必要はありません。アクティブな[アクセスレベル](access-level)を確認するだけで、ユーザーのサブスクリプションステータスを簡単に把握できます。 <details> <summary>サブスクリプションステータスの確認を始める前に(クリックして展開)</summary> - iOSの場合は、[App Store Server Notifications](enable-app-store-server-notifications)を設定してください - Androidの場合は、[リアルタイム デベロッパー通知(RTDN)](enable-real-time-developer-notifications-rtdn)を設定してください </details> ## アクセスレベルとAdaptyProfileオブジェクト \{#access-level-and-the-adaptyprofile-object\} アクセスレベルは[AdaptyProfile](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_profile.html)オブジェクトのプロパティです。アプリ起動時(例えば[ユーザーを識別する](unity-identifying-users#setting-customer-user-id-on-configuration)タイミングなど)にプロファイルを取得し、変更があれば都度更新することをおすすめします。こうすることで、毎回リクエストせずにプロファイルオブジェクトを利用できます。 プロファイルの更新通知を受け取るには、下記の[サブスクリプションステータスの更新をリッスンする](#listening-for-subscription-status-updates)セクションに従って、プロファイルの変更を監視してください。 :::tip Adapty SDK がモバイルアプリにどのように統合されているか、実際の例を見てみませんか?ペイウォールの表示、購入処理、その他の基本機能を含む完全なセットアップを実演している[サンプルアプリ](sample-apps)をご覧ください。 ::: ## サーバーからアクセスレベルを取得する \{#retrieving-the-access-level-from-the-server\} サーバーからアクセスレベルを取得するには、`.GetProfile()`メソッドを使用します。 ```csharp showLineNumbers Adapty.GetProfile((profile, error) => { if (error != null) { // handle the error return; } // check the access }); ``` レスポンスのパラメータ: | パラメータ | 説明 | | --------- |--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Profile | <p>[AdaptyProfile](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_profile.html)オブジェクト。通常は、ユーザーがプレミアムアクセスを持っているかどうかを判断するために、プロファイルのアクセスレベルのステータスだけを確認すれば十分です。</p><p></p><p>`.getProfile`メソッドは常にAPIへの問い合わせを試みるため、最新の情報を返します。何らかの理由(例:インターネット接続なし)でAdapty SDKがサーバーから情報を取得できなかった場合は、キャッシュのデータが返されます。また、Adapty SDKは`AdaptyProfile`のキャッシュを定期的に更新し、情報をできる限り最新の状態に保っています。</p> | `.getProfile()`メソッドはユーザープロファイルを返し、そこからアクセスレベルのステータスを取得できます。アプリごとに複数のアクセスレベルを設定することも可能です。たとえば、新聞アプリでさまざまなトピックへのサブスクリプションを独立して販売する場合、「sports」と「science」というアクセスレベルを作成できます。ただし、多くの場合はアクセスレベルは1つで十分であり、その場合はデフォルトの「premium」アクセスレベルを使うだけで問題ありません。 デフォルトの「premium」アクセスレベルを確認する例を示します。 ```csharp showLineNumbers Adapty.GetProfile((profile, error) => { if (error != null) { // handle the error return; } // "premium" is an identifier of default access level var accessLevel = profile.AccessLevels["premium"]; if (accessLevel != null && accessLevel.IsActive) { // grant access to premium features } }); ``` ### サブスクリプションステータスの更新をリッスンする \{#listening-for-subscription-status-updates\} ユーザーのサブスクリプションが変更されるたびに、Adaptyはイベントを発火します。 Adaptyからメッセージを受け取るには、追加の設定が必要です。 ```csharp showLineNumbers // Extend `AdaptyEventListener ` with `OnLoadLatestProfile ` method: public class AdaptyListener : MonoBehaviour, AdaptyEventListener { public void OnLoadLatestProfile(AdaptyProfile profile) { // handle any changes to subscription state } } ``` Adaptyはアプリケーション起動時にもイベントを発火します。この場合、キャッシュされたサブスクリプションステータスが渡されます。 ### サブスクリプションステータスのキャッシュ \{#subscription-status-cache\} Adapty SDKに実装されたキャッシュは、プロファイルのサブスクリプションステータスを保存します。そのため、サーバーにアクセスできない状況でも、キャッシュされたデータを使ってプロファイルのサブスクリプションステータスを確認できます。 ただし、キャッシュからデータを直接取得することはできない点に注意してください。SDKは1分ごとに定期的にサーバーへ問い合わせを行い、プロファイルに関する更新や変更がないかを確認します。新しいトランザクションやその他の更新といった変更があった場合は、サーバーと同期するためにキャッシュデータへ反映されます。 --- # File: unity-deal-with-att --- --- title: "Unity SDKでATTを処理する" description: "UnityでAdaptyを使い始めて、サブスクリプションのセットアップと管理を効率化しましょう。" --- アプリでAppTrackingTransparencyフレームワークを使用しており、ユーザーにアプリトラッキングの認証リクエストを表示する場合は、[認証ステータス](https://developer.apple.com/documentation/apptrackingtransparency/attrackingmanager/authorizationstatus/)をAdaptyに送信する必要があります。 ```csharp showLineNumbers var builder = new Adapty.ProfileParameters.Builder() .SetAppTrackingTransparencyStatus(IOSAppTrackingTransparencyStatus.Authorized); Adapty.UpdateProfile(builder.Build(), (error) => { if(error != null) { // handle the error } }); ``` :::warning この値は変更されたタイミングでできるだけ早く送信することを強く推奨します。そうすることで、設定済みのインテグレーションにタイムリーにデータが送信されます。 ::: --- # File: kids-mode-unity --- --- title: "Unity SDKのキッズモード" description: "キッズモードを簡単に有効化してAppleとGoogleのポリシーに準拠。Unity SDKではIDFA、GAID、広告データは収集されません。" --- Unityアプリが子ども向けである場合、[Apple](https://developer.apple.com/kids/)および[Google](https://support.google.com/googleplay/android-developer/answer/9893335)のポリシーに従う必要があります。Adapty SDKを使用している場合、いくつかの簡単な手順でこれらのポリシーに準拠し、アプリストアの審査を通過できるよう設定できます。 ## 何が必要ですか? \{#whats-required\} 以下の収集を無効にするようAdapty SDKを設定する必要があります。 - [IDFA(広告識別子)](https://en.wikipedia.org/wiki/Identifier_for_Advertisers)(iOS) - [Android広告ID(AAID/GAID)](https://support.google.com/googleplay/android-developer/answer/6048248)(Android) - [IPアドレス](https://www.ftc.gov/system/files/ftc_gov/pdf/p235402_coppa_application.pdf) また、カスタマーユーザーIDの取り扱いには注意が必要です。`<FirstName.LastName>`形式のユーザーIDや、メールアドレスの使用は、個人情報の収集として扱われます。キッズモードでは、ランダム化または匿名化された識別子(ハッシュIDやデバイス生成のUUIDなど)を使用することがコンプライアンス確保のベストプラクティスです。 ## キッズモードの有効化 \{#enabling-kids-mode\} ### Adapty ダッシュボードでの設定 \{#updates-in-the-adapty-dashboard\} Adapty ダッシュボードでIPアドレスの収集を無効にする必要があります。[App settings](https://app.adapty.io/settings/general)に移動し、**Collect users' IP address**の下にある**Disable IP address collection**をクリックしてください。 ### モバイルアプリのコードでの設定 \{#updates-in-your-mobile-app-code\} Unityでのキッズモードサポートはまもなくリリースされます! 現在は、各ネイティブプラットフォームのガイドをご参照ください。 - iOSの設定については[iOS SDKのキッズモード](kids-mode) - Androidの設定については[Android SDKのキッズモード](kids-mode-android) --- # File: unity-get-onboardings --- --- title: "Unity SDKでオンボーディングを取得する" description: "Unity向けAdaptyでオンボーディングを取得する方法を説明します。" --- [Adapty ダッシュボードのビルダーでオンボーディングのビジュアルをデザインした](design-onboarding)後、Unity アプリでそれを表示できます。このプロセスの最初のステップは、以下に説明するように、プレースメントに関連付けられたオンボーディングとそのビュー設定を取得することです。 始める前に、以下を確認してください: 1. [Adapty Unity SDK](sdk-installation-unity) バージョン 3.14.0 以降をインストール済みであること。 2. [オンボーディングを作成済み](create-onboarding)であること。 3. オンボーディングを[プレースメント](placements)に追加済みであること。 ## オンボーディングの取得とビューの作成 \{#fetch-onboarding-and-create-view\} ノーコードビルダーで[オンボーディング](onboardings)を作成すると、アプリが取得して表示する必要のある設定を含むコンテナとして保存されます。このコンテナは、表示されるコンテンツ、表示方法、およびユーザーのインタラクション(クイズの回答やフォームの入力など)の処理方法など、全体のエクスペリエンスを管理します。また、コンテナは自動的にアナリティクスイベントを追跡するため、個別にビュートラッキングを実装する必要はありません。 最高のパフォーマンスを得るために、ユーザーに表示する前に画像のダウンロードが完了するよう、早めにオンボーディング設定を取得してください。 オンボーディングを取得するには、`GetOnboarding` メソッドを使用します: ```csharp showLineNumbers Adapty.GetOnboarding("YOUR_PLACEMENT_ID", (onboarding, error) => { if (error != null) { // handle the error return; } // the requested onboarding }); ``` パラメーター: | パラメーター | 必須 | 説明 | |---------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **placementId** | 必須 | 目的の[プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** | <p>任意</p><p>デフォルト: `en`</p> | <p>オンボーディングのローカライゼーション識別子。このパラメーターは、マイナス(**-**)文字で区切られた1つまたは2つのサブタグで構成される言語コードを指定します。最初のサブタグは言語を表し、2番目は地域を表します。</p><p></p><p>例:`en` は英語、`pt-br` はブラジルのポルトガル語を表します。</p><p>ロケールコードと推奨する使用方法については、[ローカライゼーションとロケールコード](flutter-localizations-and-locale-codes)を参照してください。</p> | | **fetchPolicy** | デフォルト: `.reloadRevalidatingCacheData` | <p>デフォルトでは、SDK はサーバーからデータを読み込もうとし、失敗した場合はキャッシュされたデータを返します。ユーザーが常に最新のデータを取得できるため、このオプションを推奨します。</p><p></p><p>ただし、ユーザーが不安定なインターネット環境にいると思われる場合は、`.returnCacheDataElseLoad` を使用してキャッシュデータ(存在する場合)を返すことを検討してください。この場合、ユーザーは最新のデータを取得できないことがありますが、インターネット接続の状態に関わらず、より速い読み込み時間を体験できます。キャッシュは定期的に更新されるため、セッション中にネットワークリクエストを避けるために使用しても安全です。</p><p></p><p>キャッシュはアプリの再起動後も保持され、アプリのアンインストール時または手動でクリアした場合にのみ消去されます。</p><p></p><p>Adapty SDK はオンボーディングをローカルに2層で保存します:上記の定期的に更新されるキャッシュとフォールバックオンボーディングです。また、オンボーディングをより速く取得するためにCDNを使用し、CDNが到達不能な場合のスタンドアローンのフォールバックサーバーも用意しています。このシステムは、インターネット接続が不安定な場合でも、常に最新バージョンのオンボーディングを取得できるよう設計されています。</p> | | **loadTimeout** | デフォルト: 5秒 | <p>このメソッドのタイムアウト上限を設定します。タイムアウトに達した場合、キャッシュされたデータまたはローカルフォールバックが返されます。</p><p>このメソッドは内部で複数のリクエストで構成される場合があるため、まれに `loadTimeout` で指定した時間より若干遅れてタイムアウトすることがあります。</p> | レスポンスパラメーター: | パラメーター | 説明 | |:----------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Onboarding | オンボーディングの識別子と設定、リモートコンフィグ、その他いくつかのプロパティを含む [`AdaptyOnboarding`](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_onboarding.html) オブジェクト。 | オンボーディングを取得したら、`CreateOnboardingView` メソッドを呼び出します。 :::warning `CreateOnboardingView` メソッドの結果は一度しか使用できません。再度使用する必要がある場合は、`CreateOnboardingView` メソッドを再度呼び出してください。再作成せずに2回呼び出すと、`AdaptyUIError.viewAlreadyPresented` エラーが発生する可能性があります。 ::: ```csharp showLineNumbers AdaptyUI.CreateOnboardingView(onboarding, (view, error) => { // handle the result }); ``` パラメーター: | パラメーター | 必須 | 説明 | |:---------------| :------------- |:-----------------------------------------------------------------------------| | **onboarding** | 必須 | 目的のオンボーディングのビューを取得するための `AdaptyOnboarding` オブジェクト。 | | **externalUrlsPresentation** | <p>任意</p><p>デフォルト: `InAppBrowser`</p> | <p>オンボーディング内のリンクを開く方法を制御します。使用可能なオプション:</p><p>- `AdaptyWebPresentation.InAppBrowser` - リンクをアプリ内ブラウザで開く(デフォルト)</p><p>- `AdaptyWebPresentation.ExternalBrowser` - リンクをデバイスの外部ブラウザで開く</p><p>使用例については、[オンボーディングでのリンクの開き方をカスタマイズする](unity-present-onboardings#customize-how-links-open-in-onboardings)を参照してください。</p> | オンボーディングとそのビュー設定の読み込みに成功したら、[モバイルアプリで表示する](unity-present-onboardings)ことができます。 ## デフォルトオーディエンスのオンボーディングでフェッチを高速化する \{#speed-up-onboarding-fetching-with-default-audience-onboarding\} 通常、オンボーディングはほぼ即座に取得されるため、このプロセスの高速化を心配する必要はありません。ただし、オーディエンスやオンボーディングが多数あり、ユーザーのインターネット接続が弱い場合、オンボーディングの取得に予想以上の時間がかかることがあります。そのような状況では、オンボーディングをまったく表示しないよりも、スムーズなユーザー体験を確保するためにデフォルトのオンボーディングを表示したい場合があります。 これに対処するために、`GetOnboardingForDefaultAudience` メソッドを使用できます。このメソッドは、**All Users** オーディエンス向けの指定されたプレースメントのオンボーディングを取得します。ただし、上記の[オンボーディングの取得とビューの作成](#fetch-onboarding-and-create-view)セクションで説明した `getOnboarding` メソッドでオンボーディングを取得することが推奨されるアプローチであることを理解することが重要です。 :::warning `GetOnboardingForDefaultAudience` の代わりに `GetOnboarding` の使用を検討してください。前者には重要な制限があります: - **互換性の問題**:複数のアプリバージョンをサポートする際に問題が生じる可能性があり、後方互換性のあるデザインを作成するか、古いバージョンで正しく表示されないことを許容する必要があります。 - **パーソナライゼーションなし**:「All Users」オーディエンス向けのコンテンツのみを表示し、国、アトリビューション、またはカスタム属性に基づくターゲティングが行われません。 ユースケースでこれらのデメリットよりも高速な取得が重要な場合は、以下に示すように `GetOnboardingForDefaultAudience` を使用してください。そうでない場合は、[上記](#fetch-onboarding-and-create-view)の説明通り `GetOnboarding` を使用してください。 ::: ```csharp showLineNumbers Adapty.GetOnboardingForDefaultAudience("YOUR_PLACEMENT_ID", (onboarding, error) => { if (error != null) { // handle the error return; } // the requested onboarding }); ``` パラメーター: | パラメーター | 必須 | 説明 | |---------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **placementId** | 必須 | 目的の[プレースメント](placements)の識別子。Adapty ダッシュボードでプレースメントを作成する際に指定した値です。 | | **locale** | <p>任意</p><p>デフォルト: `en`</p> | <p>オンボーディングのローカライゼーション識別子。このパラメーターは、マイナス(**-**)文字で区切られた1つまたは2つのサブタグで構成される言語コードを指定します。最初のサブタグは言語を表し、2番目は地域を表します。</p><p></p><p>例:`en` は英語、`pt-br` はブラジルのポルトガル語を表します。</p> | | **fetchPolicy** | デフォルト: `.reloadRevalidatingCacheData` | <p>デフォルトでは、SDK はサーバーからデータを読み込もうとし、失敗した場合はキャッシュされたデータを返します。ユーザーが常に最新のデータを取得できるため、このオプションを推奨します。</p><p></p><p>ただし、ユーザーが不安定なインターネット環境にいると思われる場合は、`.returnCacheDataElseLoad` を使用してキャッシュデータ(存在する場合)を返すことを検討してください。この場合、ユーザーは最新のデータを取得できないことがありますが、インターネット接続の状態に関わらず、より速い読み込み時間を体験できます。キャッシュは定期的に更新されるため、セッション中にネットワークリクエストを避けるために使用しても安全です。</p><p></p><p>キャッシュはアプリの再起動後も保持され、アプリのアンインストール時または手動でクリアした場合にのみ消去されます。</p><p></p><p>Adapty SDK はオンボーディングをローカルに2層で保存します:上記の定期的に更新されるキャッシュとフォールバックオンボーディングです。また、オンボーディングをより速く取得するためにCDNを使用し、CDNが到達不能な場合のスタンドアローンのフォールバックサーバーも用意しています。このシステムは、インターネット接続が不安定な場合でも、常に最新バージョンのオンボーディングを取得できるよう設計されています。</p> | --- # File: unity-present-onboardings --- --- title: "Unity SDKでオンボーディングを表示する" description: "コンバージョンを高めるためにオンボーディングを効果的に表示する方法を学びましょう。" --- ビルダーでオンボーディングをカスタマイズしている場合、ユーザーに表示するためにUnityアプリのコードでレンダリングを実装する必要はありません。そのようなオンボーディングには、表示する内容と表示方法の両方が含まれています。 始める前に、以下を確認してください。 1. [Adapty Unity SDK](sdk-installation-unity) 3.14.0以降をインストールしていること。 2. [オンボーディングを作成](create-onboarding)していること。 3. オンボーディングを[プレースメント](placements)に追加していること。 オンボーディングを表示するには、`CreateOnboardingView`メソッドで作成した`view`に対して`view.Present()`メソッドを使用します。各`view`は一度しか使用できません。再度ペイウォールを表示する必要がある場合は、`CreateOnboardingView`をもう一度呼び出して新しい`view`インスタンスを作成してください。 :::warning `view`を再作成せずに再利用すると、`AdaptyUIError.viewAlreadyPresented`エラーが発生する可能性があります。 ::: ```csharp showLineNumbers title="Unity" view.Present((presentError) => { if (presentError != null) { // handle the error } }; ``` ## iOS表示スタイルの設定 \{#configure-ios-presentation-style\} `Present()`メソッドに`iosPresentationStyle`パラメーターを渡すことで、iOSでのオンボーディングの表示方法を設定できます。パラメーターには`AdaptyUIIOSPresentationStyle.FullScreen`(デフォルト)または`AdaptyUIIOSPresentationStyle.PageSheet`を指定できます。 ```csharp showLineNumbers title="Unity" view.Present(AdaptyUIIOSPresentationStyle.PageSheet, (error) => { // handle the error }); ``` ## オンボーディングでのリンクの開き方をカスタマイズする \{#customize-how-links-open-in-onboardings\} :::important オンボーディングでのリンクの開き方のカスタマイズは、Adapty SDK v3.15以降でサポートされています。 ::: デフォルトでは、オンボーディング内のリンクはアプリ内ブラウザで開かれ、アプリを切り替えることなくウェブページをアプリ内で表示できるシームレスな体験を提供します。 代わりに外部ブラウザでリンクを開くには、`CreateOnboardingView`メソッドに`AdaptyWebPresentation.ExternalBrowser`を渡してください。 ```csharp showLineNumbers title="Unity" AdaptyUI.CreateOnboardingView( onboarding, AdaptyWebPresentation.ExternalBrowser, // default — InAppBrowser (view, error) => { if (error != null) { // handle the error return; } // present the onboarding view view.Present((presentError) => { if (presentError != null) { // handle the error } }); } ); ``` 利用可能なオプション: - `AdaptyWebPresentation.InAppBrowser` - アプリ内ブラウザでリンクを開く(デフォルト) - `AdaptyWebPresentation.ExternalBrowser` - デバイスの外部ブラウザでリンクを開く --- # File: unity-handling-onboarding-events --- --- title: "Unity SDKでオンボーディングイベントを処理する" description: "Adaptyを使ってUnityでオンボーディング関連のイベントを処理します。" --- 始める前に、以下を確認してください: 1. [Adapty Unity SDK](sdk-installation-unity) 3.14.0以降をインストール済みであること。 2. [オンボーディングを作成済み](create-onboarding)であること。 3. オンボーディングを[プレースメント](placements)に追加済みであること。 ビルダーで設定されたオンボーディングは、アプリが反応できるイベントを生成します。これらのイベントへの対応方法を以下で説明します。 Unityアプリ内のオンボーディング画面で発生するプロセスを制御・監視するには、`AdaptyOnboardingsEventsListener`インターフェースを実装してください。 ## カスタムアクション \{#custom-actions\} ビルダーでは、ボタンに**カスタム**アクションを追加してIDを割り当てることができます。 <img src="/assets/shared/img/ios-events-1.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> このIDをコード内で使用し、カスタムアクションとして処理できます。たとえば、ユーザーが**ログイン**や**通知を許可**などのカスタムボタンをタップすると、`OnboardingViewOnCustomAction`メソッドが呼び出され、`actionId`パラメーターにビルダーで設定した**アクションID**が渡されます。"allowNotifications"のような独自のIDを作成できます。 オンボーディングイベントを処理するには、`AdaptyOnboardingsEventsListener`インターフェースを実装してください: ```csharp showLineNumbers title="Unity" public class OnboardingManager : MonoBehaviour, AdaptyOnboardingsEventsListener { void Start() { Adapty.SetOnboardingsEventsListener(this); } public void OnboardingViewOnCustomAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, string actionId ) { if (actionId == "allowNotifications") { // request notification permissions } } public void OnboardingViewDidFailWithError( AdaptyUIOnboardingView view, AdaptyError error ) { // handle errors } // Implement other required interface methods (see examples below) } ``` <Details> <summary>イベントの例(クリックして展開)</summary> ```json { "actionId": "allowNotifications", "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 0, "screensTotal": 3 } } ``` </Details> ## オンボーディングを閉じる \{#closing-onboarding\} オンボーディングは、ユーザーが**閉じる**アクションが割り当てられたボタンをタップしたときに閉じられたとみなされます。 <img src="/assets/shared/img/ios-events-2.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> :::important ユーザーがオンボーディングを閉じたときの動作を自分で管理する必要があります。たとえば、オンボーディング自体の表示を停止する処理が必要です。 ::: クラスに`OnboardingViewOnCloseAction`メソッドを実装してください: ```csharp showLineNumbers title="Unity" public class OnboardingManager : MonoBehaviour, AdaptyOnboardingsEventsListener { public void OnboardingViewOnCloseAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, string actionId ) { view.Dismiss((error) => { if (error != null) { // handle the error } }); } // ... other interface methods } ``` <Details> <summary>イベントの例(クリックして展開)</summary> ```json { "action_id": "close_button", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "final_screen", "screen_index": 3, "total_screens": 4 } } ``` </Details> ## ペイウォールを開く \{#opening-a-paywall\} :::tip オンボーディング内でペイウォールを開きたい場合は、このイベントを処理してください。オンボーディングが閉じた後にペイウォールを開く場合は、[`OnboardingViewOnCloseAction`](#closing-onboarding)を処理してイベントデータに依存せずにペイウォールを開く方がシンプルです。 ::: オンボーディングでペイウォールを扱う最もシームレスな方法は、アクションIDをペイウォールのプレースメントIDと同じにすることです。こうすることで、`OnboardingViewOnPaywallAction`の後にそのプレースメントIDを使ってすぐにペイウォールを取得して開くことができます。 iOS では、ペイウォールとオンボーディングのどちらか一方しか同時に表示できません。オンボーディングの上にペイウォールを表示した場合、バックグラウンドのオンボーディングをプログラムで制御することはできません。オンボーディングを閉じようとするとペイウォールが閉じられてしまい、オンボーディングがそのまま表示された状態になります。これを避けるため、ペイウォールを表示する前に必ずオンボーディングビューを閉じてください。 ```csharp showLineNumbers title="Unity" public class OnboardingManager : MonoBehaviour, AdaptyOnboardingsEventsListener { public void OnboardingViewOnPaywallAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, string actionId ) { // Dismiss onboarding before presenting paywall view.Dismiss((dismissError) => { if (dismissError != null) { // handle the error return; } Adapty.GetPaywall(actionId, (paywall, error) => { if (error != null) { // handle the error return; } AdaptyUI.CreatePaywallView(paywall, (paywallView, createError) => { if (createError != null) { // handle the error return; } paywallView.Present((presentError) => { if (presentError != null) { // handle the error } }); }); }); }); } // ... other interface methods } ``` <Details> <summary>イベントの例(クリックして展開)</summary> ```json { "action_id": "premium_offer_1", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "pricing_screen", "screen_index": 2, "total_screens": 4 } } ``` </Details> ## オンボーディングの読み込み完了 \{#finishing-loading-onboarding\} オンボーディングの読み込みが完了したら、`OnboardingViewDidFinishLoading`メソッドを実装してください: ```csharp showLineNumbers title="Unity" public class OnboardingManager : MonoBehaviour, AdaptyOnboardingsEventsListener { public void OnboardingViewDidFinishLoading( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta ) { // handle loading completion } // ... other interface methods } ``` <Details> <summary>イベントの例(クリックして展開)</summary> ```json { "meta": { "onboarding_id": "onboarding_123", "screen_cid": "welcome_screen", "screen_index": 0, "total_screens": 4 } } ``` </Details> ## ナビゲーションのトラッキング \{#tracking-navigation\} `OnboardingViewOnAnalyticsEvent`メソッドは、オンボーディングフロー中にさまざまな分析イベントが発生したときに呼び出されます。 `analyticsEvent`オブジェクトは以下のいずれかの型になります: | 型 | 説明 | |------------|-------------| | `AdaptyOnboardingsAnalyticsEventOnboardingStarted` | オンボーディングが読み込まれたとき | | `AdaptyOnboardingsAnalyticsEventScreenPresented` | 任意の画面が表示されたとき | | `AdaptyOnboardingsAnalyticsEventScreenCompleted` | 画面が完了したとき。オプションの`ElementId`(完了した要素の識別子)とオプションの`Reply`(ユーザーからの応答)を含みます。ユーザーが画面を離れるアクションを実行したときに発火します。 | | `AdaptyOnboardingsAnalyticsEventSecondScreenPresented` | 2番目の画面が表示されたとき | | `AdaptyOnboardingsAnalyticsEventUserEmailCollected` | 入力フィールドでユーザーのメールアドレスが収集されたとき | | `AdaptyOnboardingsAnalyticsEventOnboardingCompleted` | ユーザーが`final`IDを持つ画面に到達したときに発火します。このイベントが必要な場合は、[最後の画面に`final`IDを割り当てて](design-onboarding)ください。 | | `AdaptyOnboardingsAnalyticsEventUnknown` | 認識できないイベントタイプの場合。`Name`(不明なイベントの名前)と`meta`(追加のメタデータ)を含みます。 | 各イベントには以下の`meta`情報が含まれます: | フィールド | 説明 | |------------|-------------| | `OnboardingId` | オンボーディングフローの一意識別子 | | `ScreenClientId` | 現在の画面の識別子 | | `ScreenIndex` | フロー内の現在の画面の位置 | | `ScreensTotal` | フロー内の総画面数 | 分析イベントをトラッキングに使用する例を以下に示します: ```csharp showLineNumbers title="Unity" public class OnboardingManager : MonoBehaviour, AdaptyOnboardingsEventsListener { public void OnboardingViewOnAnalyticsEvent( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, AdaptyOnboardingsAnalyticsEvent analyticsEvent ) { switch (analyticsEvent) { case AdaptyOnboardingsAnalyticsEventOnboardingStarted: // track onboarding start TrackEvent("onboarding_started", meta); break; case AdaptyOnboardingsAnalyticsEventScreenPresented: // track screen presentation TrackEvent("screen_presented", meta); break; case AdaptyOnboardingsAnalyticsEventScreenCompleted screenCompleted: // track screen completion with user response TrackEvent("screen_completed", meta, screenCompleted.ElementId, screenCompleted.Reply); break; case AdaptyOnboardingsAnalyticsEventOnboardingCompleted: // track successful onboarding completion TrackEvent("onboarding_completed", meta); break; case AdaptyOnboardingsAnalyticsEventUnknown unknownEvent: // handle unknown events TrackEvent(unknownEvent.Name, meta); break; // handle other cases as needed } } // ... other interface methods } ``` :::note `TrackEvent`メソッドは、お好みの分析サービスに分析データを送信するために自分で実装する必要があるプレースホルダーです。 ::: <Details> <summary>イベントの例(クリックして展開)</summary> ```javascript // onboardingStarted { "name": "onboarding_started", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "welcome_screen", "screen_index": 0, "total_screens": 4 } } // screenPresented { "name": "screen_presented", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "interests_screen", "screen_index": 2, "total_screens": 4 } } // screenCompleted { "name": "screen_completed", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "profile_screen", "screen_index": 1, "total_screens": 4 }, "params": { "element_id": "profile_form", "reply": "success" } } // secondScreenPresented { "name": "second_screen_presented", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "profile_screen", "screen_index": 1, "total_screens": 4 } } // userEmailCollected { "name": "user_email_collected", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "profile_screen", "screen_index": 1, "total_screens": 4 } } // onboardingCompleted { "name": "onboarding_completed", "meta": { "onboarding_id": "onboarding_123", "screen_cid": "final_screen", "screen_index": 3, "total_screens": 4 } } ``` </Details> --- # File: unity-onboarding-input --- --- title: "Unity SDKでオンボーディングのデータを処理する" description: "Adapty SDKを使ってUnityアプリのオンボーディングからデータを保存・活用する方法を解説します。" --- ユーザーがクイズの質問に回答したり、入力フィールドにデータを入力したりすると、`OnboardingViewOnStateUpdatedAction` メソッドが呼び出されます。このフィールドタイプをコード内で保存・処理することができます。 クラスに `OnboardingViewOnStateUpdatedAction` メソッドを実装してください: ```csharp showLineNumbers title="Unity" public class OnboardingManager : MonoBehaviour, AdaptyOnboardingsEventsListener { public void OnboardingViewOnStateUpdatedAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, string elementId, AdaptyOnboardingsStateUpdatedParams @params ) { switch (@params) { case AdaptyOnboardingsSelectParams selectParams: // handle single selection break; case AdaptyOnboardingsMultiSelectParams multiSelectParams: // handle multiple selections break; case AdaptyOnboardingsInputParams inputParams: // handle text input break; case AdaptyOnboardingsDatePickerParams datePickerParams: // handle date selection break; } } // ... other interface methods } ``` パラメーターの説明: | パラメーター | 説明 | |----------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `elementId` | 入力要素の一意の識別子。回答を保存する際に、質問と回答を関連付けるために使用できます。 | | `@params` | ユーザーの入力データオブジェクト。以下のいずれかの型になります。 | | `AdaptyOnboardingsSelectParams` | オプションからの単一選択。`Id`、`Value`、`Label` を含みます。 | | `AdaptyOnboardingsMultiSelectParams` | オプションからの複数選択。`Params` のリスト(各要素に `Id`、`Value`、`Label`)を含みます。<br/>• `input`:`type`、`value` を持つオブジェクト<br/>• `datePicker`:`day`、`month`、`year` を持つオブジェクト | | `AdaptyOnboardingsInputParams` | テキスト入力フィールド。`AdaptyOnboardingsTextInput`、`AdaptyOnboardingsEmailInput`、`AdaptyOnboardingsNumberInput` のいずれかである `Input` を含みます。 | | `AdaptyOnboardingsDatePickerParams` | 日付の選択。null許容の `Day`、`Month`、`Year` を含みます。 | <Details> <summary>保存済みデータの例(実装によって異なる場合があります)</summary> ```javascript // Example of a saved select action { "elementId": "preference_selector", "meta": { "onboardingId": "onboarding_123", "screenClientId": "preferences_screen", "screenIndex": 1, "screensTotal": 3 }, "params": { "type": "select", "value": { "id": "option_1", "value": "premium", "label": "Premium Plan" } } } // Example of a saved multi-select action { "elementId": "interests_selector", "meta": { "onboardingId": "onboarding_123", "screenClientId": "interests_screen", "screenIndex": 2, "screensTotal": 3 }, "params": { "type": "multiSelect", "value": [ { "id": "interest_1", "value": "sports", "label": "Sports" }, { "id": "interest_2", "value": "music", "label": "Music" } ] } } // Example of a saved input action { "elementId": "name_input", "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 0, "screensTotal": 3 }, "params": { "type": "input", "value": { "type": "text", "value": "John Doe" } } } // Example of a saved date picker action { "elementId": "birthday_picker", "meta": { "onboardingId": "onboarding_123", "screenClientId": "profile_screen", "screenIndex": 0, "screensTotal": 3 }, "params": { "type": "datePicker", "value": { "day": 15, "month": 6, "year": 1990 } } } ``` </Details> ## ユースケース \{#use-cases\} ### 入力データでユーザープロファイルを充実させる \{#enrich-user-profiles-with-data\} 入力データをすぐにユーザープロファイルと紐付けて、同じ情報を二度聞かないようにするには、アクションを処理する際に入力データで[ユーザープロファイルを更新](unity-setting-user-attributes)する必要があります。 たとえば、`name` IDを持つテキストフィールドでユーザーに名前を入力してもらい、その値をユーザーのファーストネームとして設定する場合や、`email` フィールドにメールアドレスを入力してもらう場合、アプリのコードは次のようになります: ```csharp showLineNumbers title="Unity" public class OnboardingManager : MonoBehaviour, AdaptyOnboardingsEventsListener { public void OnboardingViewOnStateUpdatedAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, string elementId, AdaptyOnboardingsStateUpdatedParams @params ) { if (@params is AdaptyOnboardingsInputParams inputParams) { var builder = new AdaptyProfileParameters.Builder(); switch (elementId) { case "name": if (inputParams.Input is AdaptyOnboardingsTextInput textInput) { builder.SetFirstName(textInput.Value); } break; case "email": if (inputParams.Input is AdaptyOnboardingsEmailInput emailInput) { builder.SetEmail(emailInput.Value); } break; } Adapty.UpdateProfile(builder.Build(), (error) => { if (error != null) { // handle the error } }); } } // ... other interface methods } ``` ### 回答に基づいてペイウォールをカスタマイズする \{#customize-paywalls-based-on-answers\} オンボーディングのクイズを活用して、ユーザーがオンボーディングを完了した後に表示するペイウォールをカスタマイズすることもできます。 たとえば、スポーツの経験について質問し、ユーザーグループごとに異なるCTAやプロダクトを表示できます。 1. オンボーディングビルダーで[クイズを追加](onboarding-quizzes)し、各オプションにわかりやすいIDを設定します。 2. IDに基づいてクイズの回答を処理し、ユーザーに[カスタム属性を設定](unity-setting-user-attributes)します。 ```csharp showLineNumbers title="Unity" public class OnboardingManager : MonoBehaviour, AdaptyOnboardingsEventsListener { public void OnboardingViewOnStateUpdatedAction( AdaptyUIOnboardingView view, AdaptyUIOnboardingMeta meta, string elementId, AdaptyOnboardingsStateUpdatedParams @params ) { if (@params is AdaptyOnboardingsSelectParams selectParams) { var builder = new AdaptyProfileParameters.Builder(); switch (elementId) { case "experience": // set custom attribute 'experience' with the selected value (beginner, amateur, pro) builder.SetCustomStringAttribute("experience", selectParams.Value); break; } Adapty.UpdateProfile(builder.Build(), (error) => { if (error != null) { // handle the error } }); } } // ... other interface methods } ``` 3. カスタム属性の値ごとに[セグメントを作成](segments)します。 4. [プレースメント](placements)を作成し、作成した各セグメントに対して[オーディエンス](audience)を追加します。 5. アプリのコードでそのプレースメントの[ペイウォールを表示](unity-paywalls)します。オンボーディングにペイウォールを開くボタンがある場合は、[このボタンのアクションへの応答](unity-handling-onboarding-events#opening-a-paywall)としてペイウォールのコードを実装してください。 --- # File: unity-sdk-call-order --- --- title: "Unity SDKの呼び出し順序" description: "Adapty SDKのメソッドを正しい順序で呼び出すことで、プレミアムアクセスの喪失、アトリビューションの欠落、断続的な#2002エラーを回避できます。" --- `Adapty.Activate()` は、他のAdapty SDKメソッドを呼び出す前に完了している必要があります。完了コールバックが発火するまで、SDKには状態がありません。`Activate()` の前または並行して発行された呼び出しは、[`#2002 notActivated`](unity-handle-errors#custom-network-codes) でエラーになります。 アプリがユーザー認証を行い、起動後にカスタマーユーザーIDを取得する場合は、そのタイミングで `Adapty.Identify()` を呼び出してください。`Identify` コールバックが発火するまでユーザーアクションのメソッドを呼び出してはいけません。`Identify` と競合する呼び出しは [`#3006 profileWasChanged`](unity-handle-errors#custom-network-codes) で失敗するか、アクティベーション時に作成された匿名プロファイルに対して実行されてしまいます。これが起きると、アトリビューション、`appsflyer_id` などのMMP ID、インストールの帰属が識別済みプロファイルに引き継がれないことがあります。アプリがユーザー認証を行わない場合は、`Identify` をスキップして匿名プロファイルのまま使い続けてください。 MMP・アナリティクスSDK(AppsFlyer、Adjust、Branch、PostHog)も同じルールに従います。先にそれらを初期化し、UIDコールバックを受け取ってから `Adapty.Activate` を呼び出してください。そうしないと、MMP IDが短命な匿名プロファイルに紐づき、識別済みプロファイルに引き継がれないことがあります。AppsFlyerの詳細については、[AppsFlyer](appsflyer)を参照してください。 ## 正しい呼び出し順序 \{#the-correct-order\} どのパスをたどるかは、カスタマーユーザーIDをいつ取得できるか、そしてMMPまたはアナリティクスSDKを使用するかどうかによって決まります。 - **ステップ2と5**: すべてのアプリで必須です。SDKをアクティベートし、その後SDKメソッドを呼び出します。 - **ステップ1と3**: MMPまたはアナリティクスSDK(AppsFlyer、Adjust、Branch、PostHog)を統合する場合のみ必要です。 - **ステップ4**: アプリがユーザー認証を行い、起動後にカスタマーユーザーIDを取得する場合のみ必要です。 アプリ起動時にカスタマーユーザーIDが判明している場合は、`Activate()` に直接渡してください(ステップ2a)。このパスでは匿名プロファイルが作成されないため、ステップ4は不要です。 | ステップ | 呼び出し | タイミング | 備考 | |------|---------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------| | 1 | MMPまたはアナリティクスSDKの初期化(AppsFlyer、Adjust、PostHog、Branch) | アプリ起動時、最初に | MMPのUIDコールバック(例: `getAppsFlyerId`)を待ってください。 | | 2a | `Adapty.Activate(builder.Build(), ...)` — builderに `SetCustomerUserId` を設定 | アプリ起動時、ステップ1の後、カスタマーユーザーIDが判明している場合 | 推奨。匿名プロファイルは一切作成されません。 | | 2b | `Adapty.Activate(builder.Build(), ...)` — `SetCustomerUserId` なし | アプリ起動時、ステップ1の後、カスタマーユーザーIDが不明な場合(または取得しない場合) | Adaptはが匿名プロファイルを作成します。 | | 3 | 各MMPに対して `Adapty.SetIntegrationIdentifier(key, value, callback)` | ステップ2の後、ユーザーアクション呼び出しの前 | MMP IDを正しいプロファイルに紐づけるために必要です。 | | 4 | `Adapty.Identify("YOUR_USER_ID", callback)` | ステップ3の後(MMPがない場合はステップ2の後)、ステップ5の前 — 認証ありの2bパスのみ | 完了コールバックを待ってください。`Identify` 中の並行呼び出しは `#3006 profileWasChanged` を引き起こします。 | | 5 | `GetPaywall`、`GetPaywallProducts`、`RestorePurchases`、`MakePurchase`、`UpdateAttribution`、`UpdateProfile` | `Identify` を呼び出す場合はステップ4の後、それ以外はステップ3の後(MMPがない場合はステップ2の後) | これらの呼び出しには安定したプロファイルが必要です。 | :::important これらのステップをスキップすると、リターンユーザーのプレミアムアクセスの喪失、プロファイルへの `appsflyer_id` の欠落、誤ったオーディエンスに対するペイウォールの返却といった問題が発生します。 ::: ## Web2appとウェブファネルからのインストール \{#web2app-and-web-funnel-installs\} ユーザーがWebチェックアウト(Stripe、Paddle)で購入してからネイティブアプリをインストールした場合、デバイスの最初の `Activate()` によって新しい匿名プロファイルが作成されます。このプロファイルはWebプロファイルと紐づきません。認証フローやインストールリファラーからアプリ起動前にカスタマーユーザーIDを解決できる場合は、`Activate()` に直接渡してください。そうでない場合、`Identify("YOUR_USER_ID")` を呼び出してから `RestorePurchases` を実行するまで、Web上での購入はデバイス上で確認できません。 各Webチェックアウトで送信するメタデータについては、以下を参照してください: - [Stripe](stripe) - [Paddle](paddle) --- # File: unity-optimize-paywall-fetching --- --- title: "Unity SDKでのペイウォール取得を最適化する" description: "Adaptyのペイウォールを確実に取得する: Unityにおけるタイミングとキャッシュおよびフォールバックのパターン。" --- Unity でペイウォールを確実に取得するには、次の3つが必要です: 高速な表示、オーディエンスにターゲティングされたペイウォールの返却、そしてネットワークが遅い場合のグレースフルなフォールバック。以下のルールでは、そのためのタイミング、キャッシュ、フォールバックのパターンについて説明します。 :::tip これらのルールは、`Adapty.Activate()` と `Adapty.Identify()` がすでに解決済みであることを前提としています。詳細は [Unity SDK のコール順序](unity-sdk-call-order) を参照してください。 ::: ## ルールと注意点 \{#rules-and-pitfalls\} | このようにする | このようにしない | 理由 | |---|---|---| | 表示しようとしているプレースメントを取得する。 | 起動時にすべてのプレースメントを並行してプリフェッチする。 | 一括プリフェッチはメインスレッドをブロックし、バースト中にブラックスクリーンが発生する。 | | アトリビューションが解決する時間を確保した後で `GetPaywall` を取得する(例: `Activate` から 1〜2 秒後、または `OnLoadLatestProfile` が発火した後)。 | `Awake()` で `GetPaywall` を呼び出す。 | アトリビューションがまだ到達していない。ペイウォールはデフォルトのオーディエンスに対して解決され、セグメントや ASA パーソナライゼーションがサイレントにバイパスされる。 | | `loadTimeout` を設定し、すべてのプレースメントに[フォールバックペイウォール](fallback-paywalls)を設定する。 | `GetPaywall` を無期限に待機する。 | タイムアウトを設定しない場合、接続品質の低いユーザーはネットワークが解決するまで空白画面を見続けるか、アプリを閉じてしまう。 | `fetchPolicy` と `loadTimeout` パラメータのリファレンスは [ペイウォールとプロダクトの取得](fetch-paywalls-and-products-unity) を参照してください。また、適切なプレースメントの選び方は [プレースメント](placements) を参照してください。 ## 接続が不安定な環境向けの調整 \{#tune-for-poor-connectivity\} 接続品質が一貫して低い市場(農村部、交通機関内、ルーティングの影響を受ける地域)向け: - 最初のフェッチ以外のすべてのフェッチで `fetchPolicy` を `AdaptyPlacementFetchPolicy.ReturnCacheDataElseLoad` に設定する。 - Adapty ダッシュボードですべてのプレースメントに[フォールバックペイウォール](fallback-paywalls)を設定する。 - `loadTimeout` を 3〜5 秒に設定し、タイムアウト発生時はフォールバックを受け入れる。 - ペイウォールの表示を `GetProfile` に依存させない。`GetPaywall` を独立して呼び出すことで、プロファイルの取得が遅くても UI がブロックされないようにする。 --- # File: unity-test --- --- title: "Unity SDKでのテストとリリース" description: "Adapty SDKを使用したUnityアプリのテストとリリース方法をご紹介します。" --- UnityアプリにAdapty SDKをすでに実装している場合、すべてが正しく設定されていること、そしてiOSとAndroidの両プラットフォームで購入が期待通りに動作することをテストする必要があります。これには、SDKインテグレーションのテストと、Appleのサンドボックス環境およびGoogle Playのテスト環境を使った実際の購入フローのテストが含まれます。 ## アプリのテスト \{#test-your-app\} アプリ内課金の包括的なテストには、プラットフォーム別のテストガイドをご参照ください:[iOSテストガイド](test-purchases-in-sandbox)および[Androidテストガイド](testing-on-android)。 ## リリースの準備 \{#prepare-for-release\} アプリをストアに提出する前に、[リリースチェックリスト](release-checklist)に従って以下を確認してください: - ストア接続とサーバー通知が設定されている - 購入が完了し、Adaptyに報告されている - アクセスが正しくアンロック・リストアされる - プライバシーおよびレビュー要件が満たされている --- # File: InvalidProductIdentifiers-unity --- --- title: "Unity SDKのCode-1000 noProductIDsFoundエラーの修正" description: "Adaptyでサブスクリプションを管理する際に発生する無効なプロダクト識別子エラーを解決します。" --- 1000コードエラー `noProductIDsFound` は、ペイウォールでリクエストしたプロダクトがApp Storeに登録されているにもかかわらず、購入可能な状態にないことを示します。このエラーには `InvalidProductIdentifiers` という警告が伴う場合があります。警告のみでエラーが表示されない場合は、無視して問題ありません。 `noProductIDsFound` エラーが発生している場合は、以下の手順で解決してください。 ## ステップ1. バンドルIDを確認する \{#step-2-check-bundle-id\} --- no_index: true --- 1. [App Store Connect](https://appstoreconnect.apple.com/apps) を開きます。アプリを選択し、**General** → **App Information** セクションに進みます。 2. **General Information** サブセクションで **Bundle ID** をコピーします。 <Zoom> <img src="/docs/img/afd5012-bundle_id_apple.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> </Zoom> 3. Adapty のトップメニューから [**App settings** -> **iOS SDK** タブ](https://app.adapty.io/settings/ios-sdk) を開き、コピーした値を **Bundle ID** フィールドに貼り付けます。 <Zoom> <img src="/docs/img/2d64163-bundle_id.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> </Zoom> 4. App Store Connect の **App information** ページに戻り、**Apple ID** をコピーします。 5. Adapty ダッシュボードの [**App settings** -> **iOS SDK**](https://app.adapty.io/settings/ios-sdk) ページで、**Apple app ID** フィールドにその ID を貼り付けます。 ## ステップ2. プロダクトを確認する \{#step-3-check-products\} 1. **App Store Connect** にアクセスし、左側のメニューから [**Monetization** → **Subscriptions**](https://appstoreconnect.apple.com/apps/6477523342/distribution/subscriptions) に移動します。 <img src="/assets/shared/img/subscription_group_open.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. サブスクリプショングループ名をクリックすると、**Subscriptions** セクションにプロダクトの一覧が表示されます。 3. テストしているプロダクトが **Ready to Submit** としてマークされていることを確認します。 <img src="/assets/shared/img/ready-to-submit.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. 表内のプロダクトIDと、Adapty ダッシュボードの [**Products**](https://app.adapty.io/products) タブに表示されているIDを比較します。IDが一致しない場合は、表からプロダクトIDをコピーし、Adapty ダッシュボードで[プロダクトを作成](create-product)してください。 <img src="/assets/shared/img/product-id-copy.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## ステップ3. プロダクトの提供地域を確認する \{#step-4-check-product-availability\} 1. **App Store Connect** に戻り、同じ **Subscriptions** セクションを開きます。 <img src="/assets/shared/img/subscription_group_open.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. サブスクリプショングループ名をクリックしてプロダクトを表示します。 3. テストしているプロダクトを選択します。 <img src="/assets/shared/img/click-product.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **Availability** セクションまでスクロールし、必要なすべての国・地域が一覧に含まれていることを確認します。 <img src="/assets/shared/img/product-availability.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## ステップ4. プロダクトの価格を確認する \{#step-5-check-product-prices\} 1. **App Store Connect** の **Monetization** → **Subscriptions** セクションに移動します。 <img src="/assets/shared/img/subscription_group_open.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. サブスクリプショングループ名をクリックします。 3. テストしているプロダクトを選択します。 <img src="/assets/shared/img/click-product.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 4. **Subscription Pricing** までスクロールし、**Current Pricing for New Subscribers** セクションを展開します。 <img src="/assets/shared/img/check-prices.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 5. 必要なすべての価格が一覧に表示されていることを確認します。 <img src="/assets/shared/img/product-pricing.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> ## ステップ5. アプリの有料ステータス、銀行口座、税務フォームが有効であることを確認する \{#step-5-check-app-paid-status-bank-account-and-tax-forms-are-active\} 1. [**App Store Connect**](https://appstoreconnect.apple.com/) のホームページで **Business** をクリックします。 <img src="/assets/shared/img/business.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 2. 会社名を選択します。 <img src="/assets/shared/img/business-name.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> 3. 下にスクロールし、**Paid Apps Agreement**、**Bank Account**、**Tax forms** がすべて **Active** になっていることを確認します。 <img src="/assets/shared/img/appstore-connect-status.webp" style={{ border: '1px solid #727272', /* border width and color */ width: '700px', /* image width */ display: 'block', /* for alignment */ margin: '0 auto' /* center alignment */ }} /> これらの手順を実行することで、`InvalidProductIdentifiers` の警告を解消し、プロダクトをストアで有効にできるはずです。 ## ステップ6. 問題が解消しない場合はプロダクトを再作成する \{#step-6-recreate-the-product-if-its-stuck\} ステップ1〜5をすべてパスしている場合(`Approved` ステータス、バンドルIDの一致、有効なAPIキー)でも、SDKが `1000 noProductIDsFound` を返し続けることがあります。この場合、プロダクトがAppleのレジストリでスタックしている可能性があります。App Store ConnectのUIにはプロダクトが存在するものの、StoreKitのルックアップパスに公開されていない状態になることがあります。 App Store Connectでプロダクトを削除し、同じプロダクトIDで再作成してください。再作成後、反映されるまで最大24時間かかる場合があります。 --- # File: cantMakePayments-unity --- --- title: "Unity SDK における Code-1003 cantMakePayment エラーの修正" description: "Adapty でサブスクリプションを管理する際に発生する決済エラーを解決します。" --- 1003エラー(`cantMakePayments`)は、このデバイスでアプリ内課金ができないことを示しています。 `cantMakePayments`エラーが発生している場合、通常は以下のいずれかの原因が考えられます: - デバイスの制限:このエラーはAdaptyとは無関係です。以下の解決方法を参照してください。 - オブザーバーモードの設定:`makePurchase`メソッドとオブザーバーモードは同時に使用できません。以下のセクションを参照してください。 ## 問題:デバイスの制限 \{#issue-device-restrictions\} | 問題 | 解決方法 | |-----------------------------|---------------------------------------------------------| | スクリーンタイムの制限 | [スクリーンタイム](https://support.apple.com/en-us/102470)でアプリ内課金の制限を無効にする | | アカウントの停止 | Appleサポートに連絡してアカウントの問題を解決する | | 地域の制限 | 対応地域のApp Storeアカウントを使用する | ## 問題:オブザーバーモードとmakePurchaseの併用 \{#issue-using-both-observer-mode-and-makepurchase\} 購入処理に`makePurchase`を使用している場合、オブザーバーモードを使用する必要はありません。[オブザーバーモード](observer-vs-full-mode)が必要なのは、購入ロジックを自分で実装する場合のみです。 したがって、`makePurchase`を使用している場合は、SDK有効化コードからオブザーバーモードの有効化を安全に削除できます。 --- # File: migration-to-unity-sdk-314 --- --- title: "Adapty Unity SDK を v3.14 へ移行する" description: "より高いパフォーマンスと新しいマネタイズ機能のために Adapty Unity SDK v3.14 へ移行します。" --- Adapty SDK 3.14.0 はメジャーリリースであり、いくつかの改善が含まれています。ただし、以下の移行手順が必要になる場合があります。 1. ペイウォールイベント用の専用イベントリスナーの分離。 2. `AdaptyUI.CreateView` を `AdaptyUI.CreatePaywallView` およびその関連メソッドにリネーム。 3. `MakePurchase` メソッドで個別パラメーターの代わりに `AdaptyPurchaseParameters` を使用するよう更新。 4. `SetFallbackPaywalls` を `SetFallback` メソッドに置き換え。 5. `AdaptyPlacement` を使用してペイウォールプロパティにアクセスするよう更新。 6. `AdaptyRemoteConfig` オブジェクトを使用してリモートコンフィグにアクセスするよう更新。 7. `AdaptyPaywall` モデルの `VendorProductIds` を `ProductIdentifiers` に置き換え。 8. `GetPaywall` のフェッチポリシーで `AdaptyFetchPolicy` を使用するよう更新。 ## ペイウォールイベント用の専用イベントリスナーの分離 \{#separate-event-listener-for-paywall-events\} [ペイウォールビルダー](adapty-paywall-builder)でデザインしたペイウォールを表示する場合、ペイウォールビューのイベントは専用の `AdaptyPaywallsEventsListener` インターフェースと `SetPaywallsEventsListener` メソッドを使用するようになりました。コアの `AdaptyEventListener` インターフェースは、プロファイル更新とインストール詳細のために引き続き使用されます。 ```diff showLineNumbers using UnityEngine; using AdaptySDK; public class AdaptyListener : MonoBehaviour, - AdaptyEventListener { + AdaptyEventListener, + AdaptyPaywallsEventsListener { void Start() { Adapty.SetEventListener(this); + Adapty.SetPaywallsEventsListener(this); } // AdaptyEventListener methods public void OnLoadLatestProfile(AdaptyProfile profile) { } public void OnInstallationDetailsSuccess(AdaptyInstallationDetails details) { } public void OnInstallationDetailsFail(AdaptyError error) { } + // AdaptyPaywallsEventsListener methods + // Implement paywall event handlers here } ``` [ペイウォールイベントの処理について詳しく見る](unity-handling-events)。 ## ビュー作成・表示メソッドのリネーム \{#rename-view-creation-and-presentation-methods\} ビューの作成と表示に使用するメソッドがリネームされました。 ```diff showLineNumbers using AdaptySDK; - AdaptyUI.CreateView(paywall, parameters, (view, error) => { + AdaptyUI.CreatePaywallView(paywall, parameters, (view, error) => { if (error != null) { // handle the error return; } - AdaptyUI.PresentView(view, (error) => { + AdaptyUI.PresentPaywallView(view, (error) => { // handle the error }); }); } ``` 同様に、閉じるメソッドもリネームされました。 ```diff showLineNumbers - AdaptyUI.DismissView(view, (error) => { + AdaptyUI.DismissPaywallView(view, (error) => { // handle the error }); ``` ## MakePurchase メソッドの更新 \{#update-makepurchase-method\} `MakePurchase` メソッドは、個別の `subscriptionUpdateParams` および `isOfferPersonalized` 引数の代わりに `AdaptyPurchaseParameters` を使用するようになりました。これにより型安全性が向上し、将来的な購入パラメーターの拡張にも対応しやすくなります。 ```diff showLineNumbers using AdaptySDK; void MakePurchase( AdaptyPaywallProduct product, AdaptySubscriptionUpdateParameters subscriptionUpdate, bool? isOfferPersonalized ) { - Adapty.MakePurchase(product, subscriptionUpdate, isOfferPersonalized, (result, error) => { + var parameters = new AdaptyPurchaseParametersBuilder() + .SetSubscriptionUpdateParams(subscriptionUpdate) + .SetIsOfferPersonalized(isOfferPersonalized) + .Build(); + + Adapty.MakePurchase(product, parameters, (result, error) => { switch (result.Type) { case AdaptyPurchaseResultType.Pending: // handle pending purchase break; case AdaptyPurchaseResultType.UserCancelled: // handle purchase cancellation break; case AdaptyPurchaseResultType.Success: var profile = result.Profile; // handle successful purchase break; default: break; } }); } ``` 追加パラメーターが不要な場合は、次のように簡単に記述できます。 ```csharp showLineNumbers using AdaptySDK; void MakePurchase(AdaptyPaywallProduct product) { Adapty.MakePurchase(product, (result, error) => { // handle purchase result }); } ``` ## フォールバックメソッドの更新 \{#update-fallback-method\} :::important Unity SDK 3.14 にアップグレードする際は、Adapty ダッシュボードから新しいフォールバックファイルをダウンロードし、プロジェクト内の既存ファイルと置き換える必要があります。 ::: フォールバックを設定するメソッドが更新されました。`SetFallbackPaywalls` メソッドは `SetFallback` にリネームされました。 ```diff showLineNumbers using AdaptySDK; void SetFallBackPaywalls() { #if UNITY_IOS var assetId = "adapty_fallback_ios.json"; #elif UNITY_ANDROID var assetId = "adapty_fallback_android.json"; #else var assetId = ""; #endif - Adapty.SetFallbackPaywalls(assetId, (error) => { + Adapty.SetFallback(assetId, (error) => { // handle the error }); } ``` 最終的なコード例は [Unity でフォールバックペイウォールを使用する](unity-use-fallback-paywalls) のページをご覧ください。 ## ペイウォールプロパティアクセスの更新 \{#update-paywall-property-access\} 以下のプロパティが `AdaptyPaywall` から `AdaptyPlacement` に移動されました。 ```diff showLineNumbers using AdaptySDK; void ProcessPaywall(AdaptyPaywall paywall) { - var abTestName = paywall.ABTestName; - var audienceName = paywall.AudienceName; - var revision = paywall.Revision; - var placementId = paywall.PlacementId; + var abTestName = paywall.Placement.ABTestName; + var audienceName = paywall.Placement.AudienceName; + var revision = paywall.Placement.Revision; + var placementId = paywall.Placement.Id; } ``` ## リモートコンフィグアクセスの更新 \{#update-remote-config-access\} リモートコンフィグのプロパティが `AdaptyRemoteConfig` オブジェクトに再構成され、より整理された形になりました。 ```diff showLineNumbers using AdaptySDK; void ProcessRemoteConfig(AdaptyPaywall paywall) { - var remoteConfigString = paywall.RemoteConfigString; - var locale = paywall.Locale; - var remoteConfigDict = paywall.RemoteConfig; + var remoteConfigString = paywall.RemoteConfig.Data; + var locale = paywall.RemoteConfig.Locale; + var remoteConfigDict = paywall.RemoteConfig.Dictionary; } ``` ## AdaptyPaywall モデルの使用方法の更新 \{#update-adapty-paywall-model-usage\} `VendorProductIds` プロパティは非推奨となり、`ProductIdentifiers` に置き換えられました。新しいプロパティは単純な文字列ではなく `AdaptyProductIdentifier` オブジェクトを返すため、プロダクト情報がより構造化されています。 ```diff showLineNumbers using AdaptySDK; void ProcessPaywallProducts(AdaptyPaywall paywall) { - var productIds = paywall.VendorProductIds; - foreach (var vendorId in productIds) { - // use vendorId - } + var productIdentifiers = paywall.ProductIdentifiers; + foreach (var productId in productIdentifiers) { + var vendorId = productId.VendorProductId; + // use vendorId + } } ``` `AdaptyProductIdentifier` オブジェクトは `VendorProductId` プロパティを通じてベンダープロダクト ID にアクセスでき、従来と同じ機能を維持しつつ、将来の拡張に向けてより良い構造を提供します。 ## GetPaywall フェッチポリシーの更新 \{#update-getpaywall-fetch-policy\} `GetPaywall` メソッドの `fetchPolicy` パラメーターの型が `AdaptyPaywallFetchPolicy` から `AdaptyPlacementFetchPolicy` に変更されました。この変更により、SDK 全体でフェッチポリシーの使用が統一されます。 ```diff showLineNumbers using AdaptySDK; void GetPaywall(string placementId) { - Adapty.GetPaywall(placementId, AdaptyPaywallFetchPolicy.ReloadRevalidatingCacheData, null, (paywall, error) => { + Adapty.GetPaywall(placementId, AdaptyPlacementFetchPolicy.ReloadRevalidatingCacheData, null, (paywall, error) => { // handle the result }); } ``` --- # File: migration-to-unity-sdk-34 --- --- title: "Adapty Unity SDK を v3.4 へ移行する" description: "Adapty Unity SDK v3.4 に移行して、パフォーマンス向上と新しいマネタイゼーション機能をご活用ください。" --- Adapty SDK 3.4.0 はメジャーリリースであり、お客様側での移行手順が必要な改善が含まれています。 ## フォールバックペイウォールファイルの更新 \{#update-fallback-paywall-files\} 新しい SDK バージョンとの互換性を確保するため、フォールバックペイウォールファイルを更新してください。 1. Adapty ダッシュボードから[更新済みのフォールバックペイウォールファイルをダウンロード](fallback-paywalls)します。 2. モバイルアプリ内の既存のフォールバックペイウォールを[新しいファイルに置き換えます](unity-use-fallback-paywalls)。 ## オブザーバーモードの実装を更新する \{#update-implementation-of-observer-mode\} オブザーバーモードを使用している場合は、その実装を必ず更新してください。 以前は、トランザクションを Adapty に報告するために異なるメソッドが使用されていました。新しいバージョンでは、Android と iOS の両方で `reportTransaction` メソッドを一貫して使用する必要があります。このメソッドは各トランザクションを Adapty に明示的に報告し、認識されることを保証します。ペイウォールを使用した場合は、トランザクションをそのペイウォールに紐付けるためにバリエーション ID を渡してください。 :::warning **トランザクションの報告をスキップしないでください!** `reportTransaction` を呼び出さないと、Adapty はトランザクションを認識できず、アナリティクスに表示されず、インテグレーションにも送信されません。 ::: ```diff showLineNumbers - #if UNITY_ANDROID && !UNITY_EDITOR - Adapty.RestorePurchases((profile, error) => { - // handle the error - }); - #endif Adapty.ReportTransaction( "YOUR_TRANSACTION_ID", "PAYWALL_VARIATION_ID", // optional (error) => { // handle the error }); ``` --- # File: migration-to-unity330 --- --- title: "Adapty Unity SDK を v3.3 へ移行する" description: "パフォーマンス向上と新しいマネタイズ機能のために Adapty Unity SDK v3.3.3 へ移行する方法を説明します。" --- Adapty SDK 3.3.0 はメジャーリリースであり、いくつかの改善が含まれていますが、移行作業が必要な場合があります。 1. Adapty SDK v3.3.x へアップグレードする。 2. Adapty SDK の Adapty モジュールおよび AdaptyUI モジュールで、複数のクラス・プロパティ・メソッドの名前が変更されました。 3. `SetLogLevel` メソッドがコールバックを引数として受け取るようになりました。 4. `PresentCodeRedemptionSheet` メソッドがコールバックを引数として受け取るようになりました。 5. ペイウォールビューの作成方法を変更する。 6. `GetProductsIntroductoryOfferEligibility` メソッドを削除する。 7. フォールバックペイウォールをプラットフォームごとに別々のファイル(各プラットフォーム1ファイル)として `Assets/StreamingAssets/` に保存し、そのファイル名を `SetFallbackPaywalls` メソッドに渡す。 8. 購入処理を更新する。 9. ペイウォールビルダーのイベント処理を更新する。 10. ペイウォールビルダーのペイウォールエラー処理を更新する。 11. Adjust、Amplitude、AppMetrica、Appsflyer、Branch、Firebase および Google Analytics、Mixpanel、OneSignal、Pushwoosh のインテグレーション設定を更新する。 13. Observer モードの実装を更新する。 14. 明示的な `Activate` 呼び出しで Unity プラグインの初期化を更新する。 ## Adapty Unity SDK を 3.3.x へアップグレードする \{#upgrade-adapty-unity-sdk-to-33x\} このバージョンまでは、Adapty SDK がアプリ内で Adapty を正常に動作させるためのコアかつ必須の SDK であり、AdaptyUI SDK はペイウォールビルダーを使用する場合にのみ必要なオプションの SDK でした。 バージョン 3.3.0 以降、AdaptyUI SDK は非推奨となり、AdaptyUI は Adapty SDK のモジュールとして統合されました。この変更により、AdaptyUISDK を削除し、AdaptySDK を再インストールする必要があります。 1. プロジェクトから **AdaptySDK** と **AdaptyUISDK** の両方のパッケージ依存関係を削除する。 2. **AdaptySDK** フォルダーと **AdaptyUISDK** フォルダーを削除する。 3. [Adapty SDK installation & configuration for Unity](sdk-installation-unity) ページの説明に従って、AdaptySDK パッケージを再度インポートする。 ## 名前変更 \{#renamings\} 1. Adapty モジュールでの名前変更: | 旧バージョン | 新バージョン | | ------------------------- | ------------------------ | | Adapty.sdkVersion | Adapty.SDKVersion | | Adapty.LogLevel | AdaptyLogLevel | | Adapty.Paywall | AdaptyPaywall | | Adapty.PaywallFetchPolicy | AdaptyPaywallFetchPolicy | | PaywallProduct | AdaptyPaywallProduct | | Adapty.Profile | AdaptyProfile | | Adapty.ProfileParameters | AdaptyProfileParameters | | ProfileGender | AdaptyProfileGender | | Error | AdaptyError | 2. AdaptyUI モジュールでの名前変更: | 旧バージョン | 新バージョン | | ------------------ | ------------------ | | CreatePaywallView | CreateView | | PresentPaywallView | PresentView | | DismissPaywallView | DismissView | | AdaptyUI.View | AdaptyUIView | | AdaptyUI.Action | AdaptyUIUserAction | ## SetLogLevel メソッドの変更 \{#change-the-setloglevel-method\} `SetLogLevel` メソッドがコールバックを引数として受け取るようになりました。 ```diff showLineNumbers - Adapty.SetLogLevel(Adapty.LogLevel.Verbose); + Adapty.SetLogLevel(Adapty.LogLevel.Verbose, null); // or you can pass the callback to handle the possible error ``` ## PresentCodeRedemptionSheet メソッドの変更 \{#change-the-presentcoderedemptionsheet-method\} `PresentCodeRedemptionSheet` メソッドがコールバックを引数として受け取るようになりました。 ```diff showLineNumbers - Adapty.PresentCodeRedemptionSheet(); + Adapty.PresentCodeRedemptionSheet(null); // or you can pass the callback to handle the possible error ``` ## ペイウォールビューの作成方法を変更する \{#change-how-the-paywall-view-is-created\} 完全なコード例については、[ペイウォールビルダーで作成したペイウォールのビュー設定を取得する](unity-get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder) を参照してください。 ```diff showLineNumbers + var parameters = new AdaptyUICreateViewParameters() + .SetPreloadProducts(true); - AdaptyUI.CreatePaywallView( + AdaptyUI.CreateView( paywall, - preloadProducts: true, + parameters, (view, error) => { // use the view }); ``` ## GetProductsIntroductoryOfferEligibility メソッドの削除 \{#remove-the-getproductsintroductoryoffereligibility-method\} Adapty iOS SDK 3.3.0 より前は、ユーザーが対象かどうかに関わらず、プロダクトオブジェクトには常にオファーが含まれていました。そのため、オファーを使用する前に手動で対象確認を行う必要がありました。 現在は、ユーザーが対象である場合にのみプロダクトオブジェクトにオファーが含まれます。つまり、対象確認は不要になりました — オファーが存在する場合、そのユーザーは対象です。 ## フォールバックペイウォールの提供方法を更新する \{#update-method-for-providing-fallback-paywalls\} このバージョンまでは、フォールバックペイウォールはシリアライズされた JSON として渡されていました。v 3.3.0 以降、仕組みが変更されました。 1. フォールバックペイウォールを `/Assets/StreamingAssets/` 内のファイルに保存する(Android 用に 1 ファイル、iOS 用に 1 ファイル)。 2. ファイル名を `SetFallbackPaywalls` メソッドに渡す。 コードの変更は次のようになります。 ```diff showLineNumbers using AdaptySDK; void SetFallBackPaywalls() { + #if UNITY_IOS + var assetId = "adapty_fallback_ios.json"; + #elif UNITY_ANDROID + var assetId = "adapty_fallback_android.json"; + #else + var assetId = ""; + #endif - Adapty.SetFallbackPaywalls("FALLBACK_PAYWALLS_JSON_STRING", (error) => { + Adapty.SetFallbackPaywalls(assetId, (error) => { // handle the error }); } ``` 最終的なコード例は [Unity でフォールバックペイウォールを使用する](unity-use-fallback-paywalls) ページを参照してください。 ## 購入処理の更新 \{#update-making-purchase\} 以前は、キャンセルされた購入と保留中の購入はエラーとして扱われ、それぞれ `PaymentCancelled` と `PendingPurchase` コードが返されていました。 新しい `AdaptyPurchaseResultType` クラスを使用して、キャンセル済み・成功・保留中の購入を処理します。購入コードを次のように更新してください。 ```diff showLineNumbers using AdaptySDK; void MakePurchase(AdaptyPaywallProduct product) { - Adapty.MakePurchase(product, (profile, error) => { - // handle successfull purchase + Adapty.MakePurchase(product, (result, error) => { + switch (result.Type) { + case AdaptyPurchaseResultType.Pending: + // handle pending purchase + break; + case AdaptyPurchaseResultType.UserCancelled: + // handle purchase cancellation + break; + case AdaptyPurchaseResultType.Success: + var profile = result.Profile; + // handle successful purchase + break; + default: + break; } }); } ``` 最終的なコード例は [モバイルアプリで購入する](unity-making-purchases) ページを参照してください。 ## ペイウォールビルダーのイベント処理を更新する \{#update-handling-of-paywall-builder-events\} キャンセルされた購入と保留中の購入はエラーとして扱われなくなり、これらのケースはすべて `PaywallViewDidFinishPurchase` メソッドで処理されます。 1. キャンセルされた購入イベントの処理を削除する。 2. 購入成功イベントの処理を次のように更新する。 ```diff showLineNumbers - public void OnFinishPurchase( - AdaptyUI.View view, - Adapty.PaywallProduct product, - Adapty.Profile profile - ) { } + public void PaywallViewDidFinishPurchase( + AdaptyUIView view, + AdaptyPaywallProduct product, + AdaptyPurchaseResult purchasedResult + ) { } ``` 3. アクションの処理を更新する。 ```diff showLineNumbers - public void OnPerformAction( - AdaptyUI.View view, - AdaptyUI.Action action - ) { + public void PaywallViewDidPerformAction( + AdaptyUIView view, + AdaptyUIUserAction action + ) { switch (action.Type) { - case AdaptyUI.ActionType.Close: + case AdaptyUIUserActionType.Close: view.Dismiss(null); break; - case AdaptyUI.ActionType.OpenUrl: + case AdaptyUIUserActionType.OpenUrl: var urlString = action.Value; if (urlString != null { Application.OpenURL(urlString); } default: // handle other events break; } } ``` 4. 購入開始の処理を更新する。 ```diff showLineNumbers - public void OnSelectProduct( - AdaptyUI.View view, - Adapty.PaywallProduct product - ) { } + public void PaywallViewDidSelectProduct( + AdaptyUIView view, + string productId + ) { } ``` 5. 購入失敗の処理を更新する。 ```diff showLineNumbers - public void OnFailPurchase( - AdaptyUI.View view, - Adapty.PaywallProduct product, - Adapty.Error error - ) { } + public void PaywallViewDidFailPurchase( + AdaptyUIView view, + AdaptyPaywallProduct product, + AdaptyError error + ) { } ``` 6. リストア成功イベントの処理を更新する。 ```diff showLineNumbers - public void OnFailRestore( - AdaptyUI.View view, - Adapty.Error error - ) { } + public void PaywallViewDidFailRestore( + AdaptyUIView view, + AdaptyError error + ) { } ``` 最終的なコード例は [ペイウォールのイベントを処理する](unity-handling-events) ページを参照してください。 ## ペイウォールビルダーのペイウォールエラー処理を更新する \{#update-handling-of-paywall-builder-paywall-errors\} エラーの処理も変更されました。以下のガイダンスに従ってコードを更新してください。 1. プロダクト読み込みエラーの処理を更新する。 ```diff showLineNumbers - public void OnFailLoadingProducts( - AdaptyUI.View view, - Adapty.Error error - ) { } + public void PaywallViewDidFailLoadingProducts( + AdaptyUIView view, + AdaptyError error + ) { } ``` 2. レンダリングエラーの処理を更新する。 ```diff showLineNumbers - public void OnFailRendering( - AdaptyUI.View view, - Adapty.Error error - ) { } + public void PaywallViewDidFailRendering( + AdaptyUIView view, + AdaptyError error + ) { } ``` ## サードパーティインテグレーション SDK 設定の更新 \{#update-third-party-integration-sdk-configuration\} Adapty Unity SDK 3.3.0 以降、`updateAttribution` メソッドのパブリック API を更新しました。以前は `[AnyHashable: Any]` ディクショナリを受け取り、さまざまなサービスからアトリビューションオブジェクトを直接渡すことができました。現在は `[String: any Sendable]` が必要なため、渡す前にアトリビューションオブジェクトを変換する必要があります。 Adapty Unity SDK 3.3.0 以降でインテグレーションが正しく機能するよう、以下のセクションに記載されているインテグレーションの SDK 設定を更新してください。 ### Adjust 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[Adjust インテグレーションの SDK 設定](adjust#connect-your-app-to-adjust) を参照してください。 ```diff showLineNumbers - using static AdaptySDK.Adapty; using AdaptySDK; Adjust.GetAdid((adid) => { - Adjust.GetAttribution((attribution) => { - Dictionary<String, object> data = new Dictionary<String, object>(); - - data["network"] = attribution.Network; - data["campaign"] = attribution.Campaign; - data["adgroup"] = attribution.Adgroup; - data["creative"] = attribution.Creative; - - String attributionString = JsonUtility.ToJson(data); - Adapty.UpdateAttribution(attributionString, AttributionSource.Adjust, adid, (error) => { - // handle the error - }); + if (adid != null) { + Adapty.SetIntegrationIdentifier( + "adjust_device_id", + adid, + (error) => { + // handle the error + }); } }); Adjust.GetAttribution((attribution) => { Dictionary<String, object> data = new Dictionary<String, object>(); data["network"] = attribution.Network; data["campaign"] = attribution.Campaign; data["adgroup"] = attribution.Adgroup; data["creative"] = attribution.Creative; String attributionString = JsonUtility.ToJson(data); - Adapty.UpdateAttribution(attributionString, AttributionSource.Adjust, adid, (error) => { + Adapty.UpdateAttribution(attributionString, "adjust", (error) => { // handle the error }); }); ``` ### Amplitude 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[Amplitude インテグレーションの SDK 設定](amplitude#sdk-configuration) を参照してください。 ```diff showLineNumbers using AdaptySDK; - var builder = new Adapty.ProfileParameters.Builder(); - builder.SetAmplitudeUserId("YOUR_AMPLITUDE_USER_ID"); - builder.SetAmplitudeDeviceId(amplitude.getDeviceId()); - Adapty.UpdateProfile(builder.Build(), (error) => { - // handle error - }); + Adapty.SetIntegrationIdentifier( + "amplitude_user_id", + "YOUR_AMPLITUDE_USER_ID", + (error) => { + // handle the error + }); + Adapty.SetIntegrationIdentifier( + "amplitude_device_id", + amplitude.getDeviceId(), + (error) => { + // handle the error + }); ``` ### AppMetrica 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[AppMetrica インテグレーションの SDK 設定](appmetrica#sdk-configuration) を参照してください。 ```diff showLineNumbers using AdaptySDK; - var deviceId = AppMetrica.GetDeviceId(); - if (deviceId != null { - var builder = new Adapty.ProfileParameters.Builder(); - builder.SetAppmetricaProfileId("YOUR_ADAPTY_CUSTOMER_USER_ID"); - builder.SetAppmetricaDeviceId(deviceId); - Adapty.UpdateProfile(builder.Build(), (error) => { - // handle error - }); - } + var deviceId = AppMetrica.GetDeviceId(); + if (deviceId != null { + Adapty.SetIntegrationIdentifier( + "appmetrica_device_id", + deviceId, + (error) => { + // handle the error + }); + + Adapty.SetIntegrationIdentifier( + "appmetrica_profile_id", + "YOUR_ADAPTY_CUSTOMER_USER_ID", + (error) => { + // handle the error + }); + } ``` ### AppsFlyer 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[AppsFlyer インテグレーションの SDK 設定](appsflyer#connect-your-app-to-appsflyer) を参照してください。 ```diff showLineNumbers using AppsFlyerSDK; using AdaptySDK; // before SDK initialization AppsFlyer.getConversionData(this.name); // in your IAppsFlyerConversionData void onConversionDataSuccess(string conversionData) { // It's important to include the network user ID - string appsFlyerId = AppsFlyer.getAppsFlyerId(); - Adapty.UpdateAttribution(conversionData, AttributionSource.Appsflyer, appsFlyerId, (error) => { + string appsFlyerId = AppsFlyer.getAppsFlyerId(); + + Adapty.SetIntegrationIdentifier( + "appsflyer_id", + appsFlyerId, + (error) => { // handle the error }); + + Adapty.UpdateAttribution( + conversionData, + "appsflyer", + (error) => { + // handle the error + }); } ``` ### Branch 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[Branch インテグレーションの SDK 設定](branch#connect-your-app-to-branch) を参照してください。 ```diff showLineNumbers using AdaptySDK; - class YourBranchImplementation { - func initializeBranch() { - Branch.getInstance().initSession(launchOptions: launchOptions) { (data, error) in - if let data { - Adapty.updateAttribution(data, source: .branch) - } - } - } - } + Branch.initSession(delegate(Dictionary<string, object> parameters, string error) { + string attributionString = JsonUtility.ToJson(parameters); + + Adapty.UpdateAttribution( + attributionString, + "branch", + (error) => { + // handle the error + }); + }); ``` ### Firebase と Google Analytics \{#firebase-and-google-analytics\} 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[Firebase および Google Analytics インテグレーションの SDK 設定](firebase-and-google-analytics) を参照してください。 ```diff showLineNumbers // We suppose FirebaseAnalytics Unity Plugin is already installed using AdaptySDK; Firebase.Analytics .FirebaseAnalytics .GetAnalyticsInstanceIdAsync() .ContinueWithOnMainThread((task) => { if (!task.IsCompletedSuccessfully) { // handle error return; } var firebaseId = task.Result var builder = new Adapty.ProfileParameters.Builder(); - builder.SetFirebaseAppInstanceId(firebaseId); - - Adapty.UpdateProfile(builder.Build(), (error) => { - // handle error + Adapty.SetIntegrationIdentifier( + "firebase_app_instance_id", + firebaseId, + (error) => { + // handle the error }); }); ``` ### Mixpanel 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[Mixpanel インテグレーションの SDK 設定](mixpanel#sdk-configuration) を参照してください。 ```diff showLineNumbers using AdaptySDK; - var builder = new Adapty.ProfileParameters.Builder(); - builder.SetMixpanelUserId(Mixpanel.DistinctId); - Adapty.UpdateProfile(builder.Build(), (error) => { - // handle error - }); + var distinctId = Mixpanel.DistinctId; + if (distinctId != null) { + Adapty.SetIntegrationIdentifier( + "mixpanel_user_id", + distinctId, + (error) => { + // handle the error + }); + } ``` ### OneSignal 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[OneSignal インテグレーションの SDK 設定](onesignal#sdk-configuration) を参照してください。 ```diff showLineNumbers using AdaptySDK; - using OneSignalSDK; - var pushUserId = OneSignal.Default.PushSubscriptionState.userId; - var builder = new Adapty.ProfileParameters.Builder(); - builder.SetOneSignalPlayerId(pushUserId); - Adapty.UpdateProfile(builder.Build(), (error) => { - // handle error - }); + var distinctId = Mixpanel.DistinctId; + if (distinctId != null) { + Adapty.SetIntegrationIdentifier( + "mixpanel_user_id", + distinctId, + (error) => { + // handle the error + }); + } ``` ### Pushwoosh 以下のようにモバイルアプリのコードを更新してください。完全なコード例については、[Pushwoosh インテグレーションの SDK 設定](pushwoosh#sdk-configuration) を参照してください。 ```diff showLineNumbers using AdaptySDK; - var builder = new Adapty.ProfileParameters.Builder(); - builder.SetPushwooshHWID(Pushwoosh.Instance.HWID); - Adapty.UpdateProfile(builder.Build(), (error) => { - // handle error - }); + Adapty.SetIntegrationIdentifier( + "pushwoosh_hwid", + Pushwoosh.Instance.HWID, + (error) => { + // handle the error + }); ``` ## Observer モードの実装を更新する \{#update-observer-mode-implementation\} ペイウォールとトランザクションの紐付け方法を更新してください。以前は `setVariationId` メソッドを使用して `variationId` を割り当てていました。現在は、新しい `reportTransaction` メソッドを使用してトランザクションを記録する際に `variationId` を直接含めることができます。最終的なコード例は [Observer モードで購入トランザクションにペイウォールを紐付ける](report-transactions-observer-mode-unity) ページを参照してください。 ```diff showLineNumbers // every time when calling transaction.finish() - Adapty.SetVariationForTransaction("<variationId>", "<transactionId>", (error) => { - if(error != null) { - // handle the error - return; - } - - // successful binding - }); + Adapty.ReportTransaction( + "YOUR_TRANSACTION_ID", + "PAYWALL_VARIATION_ID", // optional + (error) => { + // handle the error + }); ``` ## Unity プラグインの初期化を更新する \{#update-the-unity-plugin-initialization\} Adapty Unity SDK 3.3.0 以降、プラグインの初期化時に `Activate` メソッドを明示的に呼び出すことが必須になりました。 ```csharp showLineNumbers Adapty.Activate(builder.Build(), (error) => { if (error != null) { // handle the error return; } }); ``` --- # File: migration-to-unity-sdk-v3 --- --- title: "Adapty Unity SDK を v3.0 に移行する" description: "パフォーマンス向上と新しいマネタイズ機能のために Adapty Unity SDK v3.0 に移行しましょう。" --- Adapty SDK v3.0 では、新しい [Adapty ペイウォールビルダー](adapty-paywall-builder)がサポートされました。これはペイウォールをノーコードで作成できる使いやすいツールの最新バージョンです。高い柔軟性と豊富なデザイン機能により、ペイウォールの効果と収益性をさらに高めることができます。 ## アップグレードの手順 \{#upgrade-process\} Unity のアップグレード手順は他のプラットフォームと同様です。 1. Adapty SDK v3.x にアップグレードする 2. 既存のペイウォールを新しいペイウォールビルダーに移行する Unity 固有の詳細な移行手順については、[Unity SDK インストールガイド](sdk-installation-unity)を参照し、メインの移行ガイドに記載されている一般的な移行手順に従ってください。 --- # File: unity-migration-guide --- --- title: "SDK移行ガイド" description: "Unity Adapty SDKの移行ガイド。" --- ## 移行ガイド \{#migration-guides\} ### [Unity Adapty SDK 3.xへの移行ガイド](unity-sdk-migration-guides) 旧バージョンからUnity Adapty SDK 3.xへの移行方法を説明します。 ## 新機能 \{#whats-new\} ### バージョン 3.x \{#version-3x\} - ペイウォール表示の強化 - エラーハンドリングの改善 - C#サポートの向上 - パフォーマンスの最適化 ### バージョン 2.x \{#version-2x\} - オンボーディング機能の追加 - アナリティクスの強化 - 購入フローの改善 - バグ修正と安定性の向上 ## 破壊的変更 \{#breaking-changes\} ### バージョン 3.x \{#version-3x-1\} - オブザーバーAPIの更新 - ペイウォール表示メソッドの変更 - エラーハンドリング構造の変更 ### バージョン 2.x \{#version-2x-1\} - オンボーディングAPIの更新 - プロファイル構造の変更 - 購入フローの変更 ## 移行チェックリスト \{#migration-checklist\} 新しいバージョンへ移行する際は、以下を確認してください: - [ ] 破壊的変更の確認 - [ ] APIコールの更新 - [ ] 全機能のテスト - [ ] エラーハンドリングの更新 - [ ] アナリティクストラッキングの確認 - [ ] 全プラットフォームでのテスト --- # End of Documentation _Generated on: 2026-06-24T14:36:28.769Z_ _Successfully processed: 41/41 files_