アプリ内収益のトラッキング
アプリ内課金(IAP)、サブスクリプション、カスタム収益ソースからの収益を追跡して、キャンペーンパフォーマンスと広告費用対効果(ROAS)を測定します。
収益データは3つのチャネルを通じて流れます:
- インタラクティブレポート: Singularダッシュボードで収益指標を表示
- ログのエクスポート: カスタム分析のための詳細なETLデータへのアクセス
- リアルタイムポストバック: 収益イベントを外部プラットフォームへ送信
収益イベントを追跡する理由
- 豊富な分析: 詳細なトランザクションデータを取得し、Singularレポートを強化
- 不正防止: トランザクションの領収書(Google PlayやApple App Storeなど)を含めることで、購入を検証し、アプリ内詐欺に対処します。
- キャンペーンの最適化: 収益とマーケティング活動を結びつけてROIを測定します。
ベストプラクティス完全な購入オブジェクトを渡す
Android(Google Play Billing)またはiOS(StoreKit)のアプリ内課金(IAP)プロセスから返される購入オブジェクトを渡すことを強くお勧めします。 これにより、Singularは以下を含む包括的なトランザクションの詳細を受け取ることができます:
- 商品ID
- 価格
- 通貨
- トランザクションID
- 領収書データ(検証用)
完全な購入オブジェクトを渡すことで、リッチなレポーティングが可能になり、Singularの不正検出機能(特にGoogle Playのトランザクション)を活用できます。
アプリ内課金の統合
IAP購入オブジェクトの取得
プラットフォーム固有の IAP ライブラリを使用して、完全なトランザクション詳細を含む購入オブジェクトを取得します。
- iOS: react-native-iapなどを 使用してStoreKitの購入詳細にアクセスする。
- Android: react-native-iap またはGoogle Play Billing Libraryを使用して購入オブジェクトを取得します。
InAppPurchaseメソッド
収益検証と不正防止のために、購入の詳細とともにアプリ内購入イベントを追跡します。
メソッドの署名 :
static inAppPurchase(eventName: string, purchase: SingularIOSPurchase | SingularAndroidPurchase): void
static inAppPurchaseWithArgs(eventName: string, purchase: SingularIOSPurchase | SingularAndroidPurchase, args: Record<string, any>): void
メソッドの完全なリストについては、 inAppPurchaseメソッドリファレンスを 参照してください。
完全なIAP実装例
IAPイベントをキャプチャし、プラットフォーム固有の購入オブジェクトとともにSingularに送信する完全な購入リスナーを実装します。
// TurboModule direct API (React Native 0.76+ New Architecture)
import { Platform } from 'react-native';
import NativeSingular from 'singular-react-native/jsNativeSingular';
import {
SingularIOSPurchase,
SingularAndroidPurchase
} from 'singular-react-native';
import {
initConnection,
getProducts,
setPurchaseListener,
finishTransaction,
IAPResponseCode
} from 'react-native-iap';
// Helper function to convert price to a double
const getPriceAsDouble = (product) => {
if (Platform.OS === 'android' && product.priceAmountMicros) {
// Android: Convert priceAmountMicros to double
return product.priceAmountMicros / 1000000.0;
} else if (Platform.OS === 'ios') {
// iOS: Parse price string (e.g., "$4.99" -> 4.99)
const priceString = product.price.replace(/[^0-9.]/g, '');
return parseFloat(priceString) || 0.0;
}
return 0.0; // Fallback
};
// Set up purchase listener
const handlePurchases = async () => {
try {
// Initialize connection
await initConnection();
// Set purchase listener
setPurchaseListener(async ({ responseCode, results }) => {
if (responseCode === IAPResponseCode.OK) {
for (const purchase of results) {
if (!purchase.acknowledged) {
// Fetch product details
const products = await getProducts({ skus: [purchase.productId] });
const product = products.length > 0 ? products[0] : null;
if (!product) return;
// Create purchase object
let singularPurchase = null;
if (Platform.OS === 'ios') {
singularPurchase = new SingularIOSPurchase(
getPriceAsDouble(product),
product.currency ?? 'USD',
purchase.productId,
purchase.transactionId ?? '',
purchase.transactionReceipt
);
} else if (Platform.OS === 'android') {
const jsonData = JSON.parse(purchase.transactionReceipt || '{}');
const receipt = jsonData.purchaseToken || '';
singularPurchase = new SingularAndroidPurchase(
getPriceAsDouble(product),
product.currency ?? 'USD',
purchase.transactionReceipt,
purchase.signatureAndroid
);
} else {
return;
}
// Track in-app purchase
NativeSingular.inAppPurchase('iap_purchase', singularPurchase);
// Complete the purchase
await finishTransaction(purchase, Platform.OS === 'ios');
}
}
}
});
} catch (error) {
console.error('Error handling purchases:', error);
}
};
// Call handlePurchases when your app starts
handlePurchases();
import { Platform } from 'react-native';
import {
Singular,
SingularIOSPurchase,
SingularAndroidPurchase
} from 'singular-react-native';
import {
initConnection,
getProducts,
setPurchaseListener,
finishTransaction,
IAPResponseCode
} from 'react-native-iap';
// Helper function to convert price to a double
const getPriceAsDouble = (product) => {
if (Platform.OS === 'android' && product.priceAmountMicros) {
// Android: Convert priceAmountMicros to double
return product.priceAmountMicros / 1000000.0;
} else if (Platform.OS === 'ios') {
// iOS: Parse price string (e.g., "$4.99" -> 4.99)
const priceString = product.price.replace(/[^0-9.]/g, '');
return parseFloat(priceString) || 0.0;
}
return 0.0; // Fallback
};
// Set up purchase listener
const handlePurchases = async () => {
try {
// Initialize connection
await initConnection();
// Set purchase listener
setPurchaseListener(async ({ responseCode, results }) => {
if (responseCode === IAPResponseCode.OK) {
for (const purchase of results) {
if (!purchase.acknowledged) {
// Fetch product details
const products = await getProducts({ skus: [purchase.productId] });
const product = products.length > 0 ? products[0] : null;
if (!product) return;
// Create purchase object
let singularPurchase = null;
if (Platform.OS === 'ios') {
singularPurchase = new SingularIOSPurchase(
getPriceAsDouble(product), // Price as double, e.g., 4.99
product.currency ?? 'USD', // Currency code, e.g., "USD"
purchase.productId, // e.g., "com.example.premium_subscription"
purchase.transactionId ?? '', // e.g., "1000000823456789"
purchase.transactionReceipt // JWS receipt from StoreKit
);
} else if (Platform.OS === 'android') {
// Parse transactionReceipt to extract purchaseToken
const jsonData = JSON.parse(purchase.transactionReceipt || '{}');
const receipt = jsonData.purchaseToken || '';
singularPurchase = new SingularAndroidPurchase(
getPriceAsDouble(product), // Price as double, e.g., 4.99
product.currency ?? 'USD', // Currency code, e.g., "USD"
purchase.transactionReceipt, // Full JSON receipt from Google Play
purchase.signatureAndroid // Signature from Google Play
);
} else {
return; // Unsupported platform
}
// Track in-app purchase
Singular.inAppPurchase('iap_purchase', singularPurchase);
// Complete the purchase
await finishTransaction(purchase, Platform.OS === 'ios');
}
}
}
});
} catch (error) {
console.error('Error handling purchases:', error);
}
};
// Call handlePurchases when your app starts
handlePurchases();
手動の収益トラッキング
購入検証なしの収益
通貨、金額、オプションの商品詳細を Purchase オブジェクトなしで渡して収益をトラッキングします。このメソッドは検証用のトランザクションレシートを提供しないことに注意してください。
重要:
有効なPurchaseオブジェクトなしで収益イベントを送信する場合、Singularはトランザクションを検証しません。 可能な限り、上記の
inAppPurchase()
メソッドを使用することを強くお勧めします。
注:
通貨は3文字のISO 4217通貨コードで渡します。例えば、
USD
,
EUR
,
INR
。
収益メソッド
指定された通貨と金額の単純な収益イベントを追跡する。
// TurboModule direct API (React Native 0.76+ New Architecture)
import NativeSingular from 'singular-react-native/jsNativeSingular';
// Track revenue without product details
NativeSingular.revenue('USD', 4.99);
import { Singular } from 'singular-react-native';
// Track revenue without product details
Singular.revenue('USD', 4.99);
メソッドの署名 :
static revenue(currency: string, amount: number): void
メソッドの完全なリストについては、 Revenue メソッド・リファレンスを 参照してください。
RevenueWithArgs メソッド
指定した通貨、金額、および追加のカスタム属性を持つ収益イベントを追跡します。
// TurboModule direct API (React Native 0.76+ New Architecture)
import NativeSingular from 'singular-react-native/jsNativeSingular';
// Track revenue with attributes
NativeSingular.revenueWithArgs('USD', 9.98, {
productSKU: 'coin_package_abc123',
productName: 'Coin Pack 10',
productCategory: 'Bundles',
productQuantity: 2,
productPrice: 4.99,
transaction_id: 'T12345'
});
import { Singular } from 'singular-react-native';
// Track revenue with attributes
Singular.revenueWithArgs('USD', 9.98, {
productSKU: 'coin_package_abc123',
productName: 'Coin Pack 10',
productCategory: 'Bundles',
productQuantity: 2,
productPrice: 4.99,
transaction_id: 'T12345'
});
メソッドのシグネチャ :
static revenueWithArgs(currency: string, amount: number, args: Record<string, any>): void
メソッドの完全なリストについては、 revenueWithArgs メソッド・リファレンスを 参照してください。
CustomRevenue メソッド
指定したイベント名、通貨、および金額を持つカスタム収益イベントを追跡します。
// TurboModule direct API (React Native 0.76+ New Architecture)
import NativeSingular from 'singular-react-native/jsNativeSingular';
// Track custom revenue event
NativeSingular.customRevenue('PremiumUpgrade', 'USD', 9.99);
import { Singular } from 'singular-react-native';
// Track custom revenue event
Singular.customRevenue('PremiumUpgrade', 'USD', 9.99);
メソッド・シグネチャ :
static customRevenue(eventName: string, currency: string, amount: number): void
メソッドの完全なリストについては、 customRevenue メソッドのリファレンスを 参照してください。
CustomRevenueWithArgs メソッド
指定したイベント名、通貨、金額、および追加のカスタム属性を持つカスタム収益イベントを追跡します。
// TurboModule direct API (React Native 0.76+ New Architecture)
import NativeSingular from 'singular-react-native/jsNativeSingular';
// Track custom revenue event with attributes
NativeSingular.customRevenueWithArgs('PremiumBundlePurchase', 'USD', 99.99, {
productSKU: 'premium_bundle_xyz',
productName: 'Premium Bundle',
productCategory: 'Bundles',
productQuantity: 1,
productPrice: 99.99,
discount_applied: true
});
import { Singular } from 'singular-react-native';
// Track custom revenue event with attributes
Singular.customRevenueWithArgs('PremiumBundlePurchase', 'USD', 99.99, {
productSKU: 'premium_bundle_xyz',
productName: 'Premium Bundle',
productCategory: 'Bundles',
productQuantity: 1,
productPrice: 99.99,
discount_applied: true
});
メソッドのシグネチャ :
static customRevenueWithArgs(eventName: string, currency: string, amount: number, args: Record<string, any>): void
メソッドの完全なリストについては、 customRevenueWithArgs メソッド・リファレンスを 参照してください。
サブスクリプション収益
サブスクリプションのトラッキング
Singularは、Singular SDKを使ったサブスクリプションイベントの実装に関する包括的なガイドを提供しています。このガイドでは、様々なプラットフォームにおけるアプリ内サブスクリプションイベントのトラッキングをカバーしています。
- サブスクリプション収益をトラッキングしたい場合は、 サブスクリプションイベント技術実装ガイドを お読みください。
ハイブリッドイベント追跡(上級者向け)
Singularでは、最適なアトリビューションのために、アプリに統合されたSingular SDKを通してすべてのイベントと収益を送信することを推奨しています。ただし、Singularは必要に応じて他のソースからイベントを収集することができます。
Singular SDK以外で送信されるイベントは、Singularの サーバー間イベントドキュメンテーション要件に 準拠し、正しいアトリビューションのために一致するデバイス識別子を提供する必要があります。
重要です:
Server-to-Server イベントリクエストで使用されるデバイス識別子がSingularで一致しない場合、不一致が発生します。以下の可能性に注意してください:
- 初期イベント: Singular SDKがアプリセッションからデバイス識別子を記録する 前に イベントリクエストを受信した場合、そのイベントリクエストは未知のデバイスの「最初のセッション」とみなされ、Singularはそのデバイスを オーガニックアトリビューションとして アトリビュートします。
- 識別子の不一致: Singular SDKがデバイス識別子を記録したが、それがServer-to-Server Eventリクエストで指定されたデバイス識別子と異なる場合、イベントは 正しく帰属されません 。
ハイブリッドイベント追跡ガイド
内部サーバーからのイベントの送信
内部サーバーから収益データを収集し、キャンペーンのパフォーマンスとROIを分析します。
要件
- デバイス識別子を取得する: アプリ内登録またはログインイベントから、デバイス識別子をキャプチャして渡し、このデータをユーザーIDと共にサーバーに保存します。デバイス識別子はユーザーによって変更される可能性があるため、ユーザーがアプリセッションを生成したときに識別子を更新します。これにより、サーバー側のイベントが正しいデバイスに帰属することが保証されます。
- プラットフォーム固有の識別子: サーバー側イベントはプラットフォーム固有であり、デバイス・プラットフォームに一致するデバイス識別子(例えば、iOSデバイスの場合はIDFAまたはIDFV、Androidデバイスの場合はGAID)を使用して送信する必要があります。
- リアルタイム更新: Singular Internal BIのポストバックメカニズムを使用して、内部エンドポイントにリアルタイムでイベントをプッシュし、サーバー側でデータセットを更新できるようにします。 内部BIポストバックのFAQを 参照してください。
- 実装の詳細: 詳細については、『サーバー間統合』ガイドの「 収益の追跡 」セクションを参照してください。
収益プロバイダからのイベントの送信
RevenueCatやadaptyのようなサードパーティの収益プロバイダーを統合して、購入や購読の収益をSingularに送信します。
サポートしているプロバイダー
- RevenueCat: 詳細は RevenueCatのドキュメントを ご覧ください。
- adapty 詳細は adaptyのドキュメントを ご覧ください。
- Superwall 詳細は Superwallのドキュメントを ご覧ください。
- Xsolla 詳細は Xsollaのドキュメントを ご覧ください。
セグメントからのイベント送信
Segmentに "Cloud-Mode "送信先を追加することで、Singular SDKと並行してSegmentからSingularへイベントを送信できるようになります。
詳細な設定方法については、実装ガイドの Singular-Segment Integrationに従って ください。