React Native SDKでフローとペイウォールの取得を最適化する

React Nativeで信頼性の高いフローまたはペイウォールの取得を実現するには、次の3つが必要です:高速なレンダリング、オーディエンスに基づくバリアントの返却、そしてネットワークが遅い場合のグレースフルなフォールバック。以下のルールでは、これを達成するためのタイミング、キャッシュ、フォールバックパターンを説明します。

Tip

これらのルールは、adapty.activate() と adapty.identify() がすでに解決済みであることを前提としています。詳しくはReact Native SDKのコール順序をご覧ください。

ルールと注意点

これをするこれをしない理由
表示しようとしているプレースメントをフェッチするか、preloadFlows(SDK 4.3.0+)でキャッシュをウォームアップする。起動時に独自の並列 getFlow 呼び出しをまとめて行う。手作りのプリフェッチバーストは JS スレッドをブロックし、ブラックスクリーンを引き起こす。preloadFlows はこのために設計されており、バッチをネイティブ SDK に一度の呼び出しで送信する。
アトリビューションが解決する機会を得た後に getFlow をフェッチする — 例えば、activate の 1〜2 秒後、または onLatestProfileLoad が発火した後。ルートコンポーネントのマウント時に getFlow を呼び出す。アトリビューションがまだ到達していない。フローはデフォルトのオーディエンスに対して解決され、セグメントや ASA パーソナライゼーションをサイレントにバイパスする。
loadTimeoutMs を設定し、すべてのプレースメントにフォールバックペイウォールを設定する。getFlow を無期限に待つ。タイムアウトがないと、接続が悪いユーザーはネットワークが解決するまで、またはアプリを閉じるまで空白の画面を見続ける。

カスタムペイウォールとプロダクトの取得方法については カスタムペイウォールとプロダクトの取得 を、適切なプレースメントの選び方については プレースメント をご覧ください。

プレースメントの事前読み込み

Info

preloadFlows および preloadFlowsForDefaultAudience は SDK バージョン 4.3.0 以降で利用可能です。

preloadFlows はフローの JSON をあらかじめキャッシュします(プレースメントごとに1リクエスト)。その後は通常通り、フローの取得には getFlow、ビューの作成には createFlowView を使用します。

fetchPolicy は後続の getFlow がどのレイヤーを優先して読み込むかを制御するものであり、キャッシュにアクセスできるかどうかを決めるものではありません:

  • 'return_cache_data_else_load' はプリロード済みのコピーを優先して読み込み、キャッシュに何もない場合のみネットワークにアクセスします。'return_cache_data_if_not_expired_else_load' は同じ動作をしつつ、コピーが maxAgeSeconds より新しい間はキャッシュを使い続けます。
  • デフォルトの 'reload_revalidating_cache_data' はまずネットワークにアクセスし、リクエストが失敗またはタイムアウトした場合にプリロード済みのコピーにフォールバックします。

プリロードはどちらの場合も効果がありますが、動作の仕方が異なります。キャッシュ優先ポリシーではリクエスト自体をなくし、デフォルトポリシーではリクエストを維持しつつフォールバック用のウォームコピーを確保します。

プレースメントが事前に分かっていて、まだ表示したくない場合(例:activate と identify が解決した直後、ユーザーがまだタップしていないボタンの背後にあるフローなど)に使用します。

try {
  await adapty.preloadFlows(['onboarding', 'main_paywall'], {
    loadTimeoutMs: 5000,
  });
} catch (error) {
  // at least one placement failed to preload
}

// Later, when the user reaches the paywall:
const flow = await adapty.getFlow('main_paywall', {
  fetchPolicy: 'return_cache_data_else_load',
});

パラメーター:

  • placementIds (必須): プリロードするプレースメント。
  • loadTimeoutMs (任意): タイムアウトをミリ秒で指定します。デフォルトは5000で、1000未満の値は1000に切り上げられます。iOSではタイムアウトはバッチ全体に適用され、Androidでは各プレースメントに適用されます。

知っておくべき動作:

  • プロミスは全てのプレースメントの試行が完了した後にのみ拒否され、エラーにはプレースメントごとの失敗が集約されます。あるプレースメントの失敗が他のプレースメントの処理を止めることはなく、読み込みに成功したプレースメントはキャッシュに残ります。
  • プレースメントがタイムアウトするかネットワークエラーで失敗した場合、SDK はそのプレースメントのデフォルトオーディエンスのバリアントにフォールバックします。その他の失敗はそのまま報告されます。
  • プリロードはキャッシュをウォームアップするだけです。コンテンツを返すわけではないため、表示するには引き続き getFlow を呼び出す必要があります。

プリロードがカバーする範囲

フローは画面に複数のレイヤーに分けて表示されます。プリロードは getFlow と同様に、最初のレイヤーのみをカバーします。

レイヤー取得元プリロードによるウォームアップ
フロー JSON — 選択されたバリアント、プロダクト ID、リモートコンフィグgetFlowあり
UI レイアウト — 画面の構造、スタイル、テキストcreateFlowViewなし
画像(動画要素の代わりに表示される静止フレームを含む)createFlowView(バックグラウンドで処理)なし
動画ファイルシステムプレーヤー(画面のレンダリング時)SDK によるキャッシュなし

そのため、特定のレイアウトに対して初めて createFlowView を呼び出す際は、プリロード後でもラウンドトリップが発生します。その後、ネイティブ SDK はそのレイアウトをディスクキャッシュに保持するため、アプリの再起動後も維持されます。つまり、コストは毎回ではなく最初のリクエスト時にのみ発生します。

オーディエンスのセグメンテーションをスキップする

オーディエンスのセグメンテーションを一切待たずにキャッシュをウォームアップするには、デフォルトオーディエンスのバリアントを使用します。タイムアウトは不要です:

await adapty.preloadFlowsForDefaultAudience(['main_paywall']);

アプリバンドルから最初の画面のメディアを表示する

フローは画像や動画を Adapty からダウンロードします。最初の画面のメディアを即座に表示するには、アプリバンドルから配信してください。これは、既存のネイティブオンボーディングのビジュアルなど、すでにアプリに同梱しているメディアを再利用する便利な方法です。

  1. フローまたはペイウォールビルダーで、画像や動画にカスタムメディアIDを設定します。そこにアップロードしたファイルはフォールバックとして残ります。
  2. ネイティブプロジェクトにファイルを追加します:iOSのアプリバンドルと、Androidのassetsフォルダです。
  3. フロービューを作成する際、customAssetsでそのIDに対応するバンドル済みファイルを渡します:
// "welcome_video" is the custom media ID set in the Flow & Paywall Builder
const bundledAssets: Record<string, AdaptyCustomAsset> = {
  'welcome_video': {
    type: 'video',
    fileLocation: {
      ios: { fileName: 'welcome.mp4' },
      android: { relativeAssetPath: 'videos/welcome.mp4' },
    },
  },
};

const view = await createFlowView(flow, { customAssets: bundledAssets });

バンドルファイルはアプリのダウンロードサイズを増やすため、ユーザーが最初に目にするメディアのみをバンドルしてください。

バンドルしていないメディアもすぐに表示されます。フローのレイアウトには各画像の低解像度コピー(動画のスチルフレームを含む)が含まれており、フルファイルが読み込まれるまでそれが表示されます。

customAssets の完全なリファレンスについては、アセットのカスタマイズを参照してください。

接続状況が悪い場合のチューニング

接続が常に不安定な市場(農村地域、交通機関内、ルーティングの影響を受ける地域)向けの設定:

  • 最初のフェッチ以外はすべて fetchPolicy: 'return_cache_data_else_load' を設定する。
  • Adapty ダッシュボードのすべてのプレースメントにフォールバックペイウォールを設定する。
  • loadTimeoutMs を 3〜5 秒に設定し、タイムアウト発生時はフォールバックを受け入れる。
  • フローの表示を getProfile() に依存させない。getFlow を独立して呼び出すことで、プロファイルの取得が遅くても UI をブロックしないようにする。