SKAdNetworkのサポート
SKAdNetworkは、iOSアプリインストールキャンペーン用のAppleのプライバシー重視のアトリビューションフレームワークです。Singular React Native SDKは、ダッシュボードで設定したコンバージョンモデルに基づいてSingularが自動的にコンバージョン値を更新するマネージドモードで、デフォルトでSKAdNetworkを有効にします。
追加の設定は必要ありません:最新のReact Native SDKを使用している場合、SKAdNetworkはすぐに動作します。基本的な機能にはコードの変更や追加設定は必要ありません。
SKANモードについて
マネージドモード(デフォルト)
マネージドモードでは、ダッシュボードで設定したコンバージョンモデルに基づいて、Singularが自動的にコンバージョン値の更新を処理します。これは最小限のコードで最適なコンバージョントラッキングを提供するため、ほとんどのアプリに推奨されるアプローチです。
- 自動更新:Singularはユーザーイベントと設定されたモデルに基づいてすべてのコンバージョン値の更新を管理します。
- ダッシュボードの設定:コードを変更することなく、Singularダッシュボードでコンバージョンモデルをデザインします。
- 最適化:Appleの制約の中でコンバージョン値の更新を最大化するSingularの専門知識をご利用ください。
- 24時間ウィンドウ管理:SingularはSKAdNetworkの24時間更新ウィンドウをインテリジェントに処理し、データ収集を最大化します。
マニュアルモード(上級者向け)
マニュアルモードでは、変換値の更新を完全にコントロールすることができ、SKANの変換値をいつ、どのように更新するかを決定するカスタムロジックを実装することができます。このモードは、マネージドモードでは対応できない特定の要件がある場合にのみ使用します。
高度な機能です:マニュアルモードでは、変換値の更新ウィンドウや制限など、AppleのSKAdNetworkの制約を理解し、慎重に実装する必要があります。ほとんどのアプリはマネージドモードを使用してください。
SKAdNetworkサポートを無効にする
SKAdNetwork トラッキングはデフォルトで有効になっています。無効にするには、SingularConfigオブジェクトをビルドする際に、skAdNetworkEnabled コンフィギュレーションプロパティをfalseに設定してください。
// TurboModule direct API (React Native 0.76+ New Architecture)
import NativeSingular from 'singular-react-native/jsNativeSingular';
const config: SingularConfig = {
apikey: 'API_KEY',
secret: 'SECRET',
skAdNetworkEnabled: false // Disable SKAdNetwork
};
import { SingularConfig } from 'singular-react-native';
const config = new SingularConfig('API_KEY', 'SECRET')
.withSkAdNetworkEnabled(false); // Disable SKAdNetwork
マニュアルモードの設定
カスタム変換値ロジックを実装するには、Manual Modeを有効にし、提供されるSDKメソッドを使用して、アプリのライフサイクル全体を通して変換値を更新および監視します。
マニュアルモードを有効にする
SingularConfigオブジェクトをビルドする際に、manualSkanConversionManagement コンフィギュレーションプロパティをtrueに設定し、変換値の更新を制御できるようにします。
// TurboModule direct API (React Native 0.76+ New Architecture)
import NativeSingular from 'singular-react-native/jsNativeSingular';
const config: SingularConfig = {
apikey: 'API_KEY',
secret: 'SECRET',
manualSkanConversionManagement: true // Enable manual SKAN conversion mode
};
import { SingularConfig } from 'singular-react-native';
const config = new SingularConfig('API_KEY', 'SECRET')
.withManualSkanConversionManagement(); // Enable manual mode
重要:手動更新メソッドは、manualSkanConversionManagement が有効な場合にのみ機能します。マネージドモードが有効な場合、手動更新は無視されます。
変換値の更新(SKAN 2.0-3.0)
skanUpdateConversionValue メソッドを使用して、カスタムロジックに基づいてSKAdNetworkの変換値を手動で更新します。変換値は0~63の整数である必要があります。
メソッドの署名
static skanUpdateConversionValue(conversionValue)
使用例
// TurboModule direct API (React Native 0.76+ New Architecture)
import NativeSingular from 'singular-react-native/jsNativeSingular';
import { Platform } from 'react-native';
// User completed signup - update conversion value to 7
async function onUserSignUp() {
if (Platform.OS === 'ios') {
// Track the sign-up event
NativeSingular.event('SignUp');
// Update SKAN conversion value
const success = await NativeSingular.skanUpdateConversionValue(7);
if (success) {
console.log('Conversion value updated successfully');
} else {
console.warn('Failed to update conversion value');
}
}
}
// User completed purchase - update based on purchase amount
async function onPurchaseComplete(purchaseAmount) {
if (Platform.OS === 'ios') {
// Track revenue event
NativeSingular.revenue('USD', purchaseAmount);
// Calculate conversion value based on purchase tier
const conversionValue = calculateConversionValue(purchaseAmount);
await NativeSingular.skanUpdateConversionValue(conversionValue);
}
}
function calculateConversionValue(amount) {
// Your custom logic to determine conversion value
if (amount >= 100) return 63; // High value
if (amount >= 50) return 40; // Medium value
if (amount >= 10) return 20; // Low value
return 10; // Minimal value
}
import { Singular } from 'singular-react-native';
import { Platform } from 'react-native';
// User completed signup - update conversion value to 7
async function onUserSignUp() {
if (Platform.OS === 'ios') {
// Track the sign-up event
Singular.event('SignUp');
// Update SKAN conversion value
const success = await Singular.skanUpdateConversionValue(7);
if (success) {
console.log('Conversion value updated successfully');
} else {
console.warn('Failed to update conversion value');
}
}
}
// User completed purchase - update based on purchase amount
async function onPurchaseComplete(purchaseAmount) {
if (Platform.OS === 'ios') {
// Track revenue event
Singular.revenue('USD', purchaseAmount);
// Calculate conversion value based on purchase tier
const conversionValue = calculateConversionValue(purchaseAmount);
await Singular.skanUpdateConversionValue(conversionValue);
}
}
function calculateConversionValue(amount) {
// Your custom logic to determine conversion value
if (amount >= 100) return 63; // High value
if (amount >= 50) return 40; // Medium value
if (amount >= 10) return 20; // Low value
return 10; // Minimal value
}
変換値の更新(SKAN 4.0)
iOS 16.1+では、skanUpdateConversionValues メソッドを使用して、SKAdNetwork 4.0の変換値を細かい値、粗い値、およびロックパラメータで更新します。これにより、変換値の更新をより細かく制御できます。
シグネチャ
static skanUpdateConversionValues(
conversionValue, // Fine value (0-63)
coarse, // Coarse value (0=low, 1=medium, 2=high)
lock // Lock status
)
使用例
// TurboModule direct API (React Native 0.76+ New Architecture)
import NativeSingular from 'singular-react-native/jsNativeSingular';
import { Platform } from 'react-native';
async function updateSKAN4ConversionValue(fineValue, coarseValue, shouldLock) {
if (Platform.OS === 'ios') {
// Map coarse value string to number
const coarseMap = { low: 0, medium: 1, high: 2 };
// Update SKAdNetwork 4.0 conversion values
await NativeSingular.skanUpdateConversionValues(
fineValue,
coarseMap[coarseValue],
shouldLock
);
console.log(`SKAN 4.0 updated: fine=${fineValue}, coarse=${coarseValue}, lock=${shouldLock}`);
}
}
// Example: High-value user completes tutorial
async function onTutorialComplete() {
await updateSKAN4ConversionValue(15, 'medium', false);
}
// Example: Premium purchase - lock the value
async function onPremiumPurchase() {
await updateSKAN4ConversionValue(63, 'high', true);
}
import { Singular } from 'singular-react-native';
import { Platform } from 'react-native';
async function updateSKAN4ConversionValue(fineValue, coarseValue, shouldLock) {
if (Platform.OS === 'ios') {
// Map coarse value string to number
const coarseMap = { low: 0, medium: 1, high: 2 };
// Update SKAdNetwork 4.0 conversion values
Singular.skanUpdateConversionValues(
fineValue,
coarseMap[coarseValue],
shouldLock
);
console.log(`SKAN 4.0 updated: fine=${fineValue}, coarse=${coarseValue}, lock=${shouldLock}`);
}
}
// Example: High-value user completes tutorial
async function onTutorialComplete() {
await updateSKAN4ConversionValue(15, 'medium', false);
}
// Example: Premium purchase - lock the value
async function onPremiumPurchase() {
await updateSKAN4ConversionValue(63, 'high', true);
}
現在の変換値を取得
Singular SDKが追跡している現在の変換値を取得する。これは現在の状態に基づいた条件ロジックを実装するのに便利で、マネージドモードでもマニュアルモードでも動作します。
シグネチャ
static skanGetConversionValue()
使用例
// TurboModule direct API (React Native 0.76+ New Architecture)
import NativeSingular from 'singular-react-native/jsNativeSingular';
import { Platform } from 'react-native';
async function checkAndUpdateConversionValue() {
if (Platform.OS === 'ios') {
const currentValue = await NativeSingular.skanGetConversionValue();
if (currentValue !== null) {
console.log(`Current conversion value: ${currentValue}`);
// Only update if current value is below threshold
if (currentValue < 30) {
await NativeSingular.skanUpdateConversionValue(30);
console.log('Updated conversion value to 30');
}
} else {
console.warn('Conversion value not available');
}
}
}
import { Singular } from 'singular-react-native';
import { Platform } from 'react-native';
async function checkAndUpdateConversionValue() {
if (Platform.OS === 'ios') {
const currentValue = await Singular.skanGetConversionValue();
if (currentValue !== null) {
console.log(`Current conversion value: ${currentValue}`);
// Only update if current value is below threshold
if (currentValue < 30) {
await Singular.skanUpdateConversionValue(30);
console.log('Updated conversion value to 30');
}
} else {
console.warn('Conversion value not available');
}
}
}
コンバージョン値の更新を監視する
コンバージョン値が変更されるたびにリアルタイムの通知を受け取るハンドラを設定します。これにより、コンバージョン値の更新に反応し、アナリティクスを記録したり、他のアプリの動作をトリガーしたりすることができます。
設定方法
SDKを初期化する際に、withConversionValueUpdatedHandler メソッドを使用してコンバージョン値更新ハンドラを設定します。
// TurboModule direct API (React Native 0.76+ New Architecture)
import NativeSingular from 'singular-react-native/jsNativeSingular';
import { NativeEventEmitter } from 'react-native';
const config: SingularConfig = {
apikey: 'API_KEY',
secret: 'SECRET'
};
NativeSingular.init(config);
const emitter = new NativeEventEmitter(NativeSingular);
// Listen for conversion value updates
emitter.addListener('ConversionValueUpdatedHandler', (conversionValue) => {
console.log(`Conversion value updated to: ${conversionValue}`);
// Log the update to your analytics
logConversionValueUpdate(conversionValue);
// Trigger app-specific behavior
if (conversionValue >= 50) {
unlockPremiumFeature();
}
});
function logConversionValueUpdate(value) {
// Your analytics logging logic
console.log(`Analytics: SKAN CV = ${value}`);
}
function unlockPremiumFeature() {
// Your custom logic
console.log('Premium feature unlocked based on high conversion value');
}
import { Singular, SingularConfig } from 'singular-react-native';
const config = new SingularConfig('API_KEY', 'SECRET')
.withConversionValueUpdatedHandler((conversionValue) => {
console.log(`Conversion value updated to: ${conversionValue}`);
// Log the update to your analytics
logConversionValueUpdate(conversionValue);
// Trigger app-specific behavior
if (conversionValue >= 50) {
unlockPremiumFeature();
}
});
Singular.init(config);
function logConversionValueUpdate(value) {
// Your analytics logging logic
console.log(`Analytics: SKAN CV = ${value}`);
}
function unlockPremiumFeature() {
// Your custom logic
console.log('Premium feature unlocked based on high conversion value');
}
ベストプラクティスコンバージョン値ハンドラを使用して、アプリ全体の現在のコンバージョン状態の同期ビューを維持します。 これは、デバッグとカスタムロジックが正しく動作することを確認するために特に便利です。
App Tracking Transparency(ATT)のサポート
App Tracking Transparency (ATT)は、デバイスのIDFA (Identifier for Advertisers)にアクセスしてユーザーデータを共有する前に、ユーザーの同意を必要とするAppleのプライバシーフレームワークです。ATTを正しく実装することは、iOSのアトリビューションとユーザー獲得キャンペーンの精度を最大化するために非常に重要です。
ATTがアトリビューションに重要な理由
iOS 14.5以降、アプリはIDFAにアクセスする前に、ATTフレームワークを通じてユーザーの許可を要求する必要があります。IDFAがなくてもフィンガープリンティングや確率的な方法でアトリビューションは可能ですが、IDFAがあることでアトリビューションの精度が大幅に向上し、決定論的なマッチングが可能になります。
- 決定論的アトリビューション:IDFAは、広告インプレッションとインストールを直接結びつける正確なデバイスレベルのアトリビューションを可能にします。
- 広告ネットワークの最適化:広告ネットワークは、IDFAにアクセスすることで、キャンペーンをより最適化し、より正確なレポートを提供できます。
- ユーザーレベルのインサイト:IDFAにアクセスすることで、より詳細なユーザー行動分析とコホート追跡が可能になります。
推奨ATTプロンプトを実装し、ユーザーの同意を求めることを強くお勧めします。ユーザーにメリット(パーソナライズされた広告、より良いアプリ体験)を説明し、オプトイン率を最大化する。
実装要件
iOS 14.5+(iOS 18を含む)では、トラッキングのためにIDFAにアクセスする前に、ATTrackingManagerフレームワークを使用してユーザーの同意を求めます。Singular SDKはATTをサポートしており、同意の前に初期化を行い、同意が得られるかタイムアウトが発生するまでイベントを遅延させることができます。
ステップ1:ATTフレームワーク設定を追加する
Info.plistファイルをユーザー向けの使用説明で更新することで、ATTフレームワークをサポートするようにiOSアプリを設定します。
-
Info.plistを開きます:iOSプロジェクトのInfo.plistファイルに移動します(
ios/[YourAppName]/Info.plistにあります)。 -
使い方の説明を追加します:あなたのアプリがトラッキング許可を必要とする理由を明確に説明した
NSUserTrackingUsageDescriptionキーを追加します。
<key>NSUserTrackingUsageDescription</key>
<string>This app uses tracking to provide personalized ads and improve your experience.</string>
重要:使用方法の説明は、ATTプロンプトでユーザーに表示されます。トラッキングがユーザーにどのような利益をもたらすかについて、明確かつ簡潔に、そして正直に記述してください。
ステップ2: ATTサポートパッケージのインストール
アプリでATT機能を有効にするために、React Native ATTサポートパッケージをインストールします。
npm install react-native-tracking-transparency --save
インストール後、iOSディレクトリからpod install 、ネイティブ依存関係をリンクします。
cd ios && pod install && cd ..
ステップ3:SDK待ちタイムアウトの設定
waitForTrackingAuthorizationWithTimeoutInterval プロパティを設定して、初期化する前にユーザーのATT応答を待つようにSingular SDKを設定します。 この遅延により、ユーザーが許可を与えた場合にIDFAがキャプチャされるようになります。
重要です:Singular SDKが最初のセッションを送信する前に、必ずATTの同意を要求し、IDFAを取得してください。これを怠ると、そのデバイスのアトリビューションデータのIDFAが永久に失われます。
// TurboModule direct API (React Native 0.76+ New Architecture)
import NativeSingular from 'singular-react-native/jsNativeSingular';
const config: SingularConfig = {
apikey: 'API_KEY',
secret: 'SECRET',
waitForTrackingAuthorizationWithTimeoutInterval: 300 // Wait up to 5 minutes
};
import { SingularConfig } from 'singular-react-native';
const config = new SingularConfig('API_KEY', 'SECRET')
.withWaitForTrackingAuthorizationWithTimeoutInterval(300); // Wait up to 5 minutes
推奨値アプリがATTプロンプトを表示する場合は、タイムアウトを300秒(5分)に設定してください。これにより、プロンプトの表示が遅れたり表示されなかったりしても、ユーザーエクスペリエンスが低下することなく、ユーザーがプロンプトを見て応答するのに十分な時間が確保されます。
ステップ4:ATT同意を要求する
アプリにATTリクエストフローを実装し、ユーザーエクスペリエンスの適切なタイミングでトラッキング許可をユーザーに促します。
// TurboModule direct API (React Native 0.76+ New Architecture)
import React, { useEffect } from 'react';
import { Platform } from 'react-native';
import NativeSingular from 'singular-react-native/jsNativeSingular';
import { requestTrackingPermission } from 'react-native-tracking-transparency';
export default function App() {
useEffect(() => {
initializeApp();
}, []);
async function initializeApp() {
if (Platform.OS === 'ios') {
// Request ATT authorization
const trackingStatus = await requestTrackingPermission();
// Log the user's response
console.log('ATT Status:', trackingStatus);
// Possible values: 'authorized', 'denied', 'restricted', 'unavailable'
}
// Initialize Singular SDK (configured with wait timeout)
const config: SingularConfig = {
apikey: 'API_KEY',
secret: 'SECRET',
waitForTrackingAuthorizationWithTimeoutInterval: 300,
loggingEnabled: true,
};
NativeSingular.init(config);
}
return (
// Your app components go here
null
);
}
import React, { useEffect } from 'react';
import { Platform } from 'react-native';
import { Singular, SingularConfig } from 'singular-react-native';
import { requestTrackingPermission, getTrackingStatus } from 'react-native-tracking-transparency';
export default function App() {
useEffect(() => {
initializeApp();
}, []);
async function initializeApp() {
if (Platform.OS === 'ios') {
// Request ATT authorization
const trackingStatus = await requestTrackingPermission();
// Log the user's response
console.log('ATT Status:', trackingStatus);
// Possible values: 'authorized', 'denied', 'restricted', 'unavailable'
}
// Initialize Singular SDK (configured with wait timeout)
const config = new SingularConfig('API_KEY', 'SECRET')
.withWaitForTrackingAuthorizationWithTimeoutInterval(300)
.withLoggingEnabled();
Singular.init(config);
}
return (
// Your app components
);
}
ATTベストプラクティス
- プロンプト前のメッセージング:トラッキング許可が必要な理由と、それがユーザーにどのようなメリット(より良い広告、より良い体験)をもたらすかを説明するATT前の画面をユーザーに見せましょう。これにより、オプトイン率が大幅に向上します。
- タイミングが重要:初回起動直後ではなく、アプリフローの自然なタイミングでATTプロンプトを表示しましょう。まずはユーザーにアプリを体験してもらい、信頼を築きましょう。
-
タイムアウトの設定:
waitForTrackingAuthorizationWithTimeoutIntervalを30~300秒に設定します。タイムアウト後、SingularはSKAN 4.0のアトリビューションで処理を進めます(IDFAなし)。 - 徹底的にテストする:許可されたシナリオと拒否されたシナリオの両方をテストし、ユーザーの選択に関係なくアプリが正しく機能することを確認します。
- ユーザーの選択を尊重してください:トラッキングを拒否したユーザーに対して何度もプロンプトを表示したり、オプトインを迫るような攻撃的なメッセージを表示したりしないでください。
-
エラー処理:
restricted(例:ペアレンタルコントロール)またはunavailableのトラッキングステータスをチェックし、分析のためにログを記録する。
App Storeのレビュー:ATTを適切に実装していないアプリや、フレームワークを回避しようとするアプリは、App Storeの審査で却下される可能性があります。Appleのガイドラインに従って実装し、ユーザーのプライバシーに関する選択を尊重するようにしてください。