React Native SDK - 支持 SKAdNetwork

文件

支持 SKAdNetwork

SKAdNetwork 是苹果公司针对 iOS 应用程序安装活动推出的注重隐私的归因框架。Singular React Native SDK 默认在托管模式下启用 SKAdNetwork,Singular 会根据仪表板中配置的转换模型自动更新转换值。

无需额外配置:如果您使用的是最新的 React Native SDK,SKAdNetwork 开箱即用。基本功能无需更改代码或进行额外设置。

了解 SKAN 模式

托管模式(默认)

在托管模式下,Singular 会根据您在仪表板中配置的转换模型自动处理转换值更新。这是大多数应用程序的推荐方法,因为它只需最少的代码,并提供最佳的转换跟踪。

  • 自动更新:Singular 根据用户事件和配置的模型管理所有转换值更新。
  • 仪表板配置:在 Singular 面板中设计转换模型,无需修改代码。
  • 优化:受益于 Singular 在苹果限制条件下最大化转换值更新的专业知识。
  • 24 小时窗口管理:Singular 可智能处理 SKAdNetwork 的 24 小时更新窗口,最大限度地收集数据。

手动模式(高级)

手动模式可让您完全控制转换值更新,允许您实施自定义逻辑,以确定何时以及如何更新 SKAN 转换值。只有当您有管理模式无法满足的特殊要求时,才可使用此模式。

高级功能:手动模式需要仔细实施并了解 Apple 的 SKAdNetwork 限制,包括转换值更新窗口和限制。大多数应用程序应使用托管模式。

禁用 SKAdNetwork 支持

SKAdNetwork 跟踪功能默认已启用。要禁用它,请在构建 SingularConfig 对象时将skAdNetworkEnabled 配置属性设置为 false。

New ArchitectureOld Architecture
// 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
};

配置手动模式

要实现自定义转换值逻辑,请启用手动模式,并使用提供的 SDK 方法在应用程序的整个生命周期内更新和监控转换值。

启用手动模式

在构建 SingularConfig 对象时,将manualSkanConversionManagement 配置属性设为 true,以便控制转换值更新。

New ArchitectureOld Architecture
// 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
};

重要:手动更新方法只有在manualSkanConversionManagement 启用时才会起作用。如果启用了托管模式,手动更新将被忽略。

更新转换值(SKAN 2.0-3.0)

使用skanUpdateConversionValue 方法,根据自定义逻辑手动更新 SKAdNetwork 转换值。转换值必须是 0 到 63 之间的整数。

方法签名

static skanUpdateConversionValue(conversionValue)

使用示例

New ArchitectureOld Architecture
// 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
}

更新转换值(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
)

使用示例

New ArchitectureOld Architecture
// 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);
}

获取当前转换值

读取由 Singular SDK 跟踪的当前转换值。这对于根据当前状态执行条件逻辑非常有用,在托管和手动模式下均可使用。

签名

static skanGetConversionValue()

使用示例

New ArchitectureOld Architecture
// 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');
    }
  }
}

监控转换值更新

设置一个处理程序,以便在转换值发生变化时接收实时通知。这样,您就能对转换值更新做出反应,并记录分析结果或触发其他应用程序行为。

配置

在初始化 SDK 时使用withConversionValueUpdatedHandler 方法配置转换值更新处理程序。

New ArchitectureOld Architecture
// 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');
}

最佳实践:使用转换值处理程序可保持整个应用程序当前转换状态的同步视图。 这对于调试和确保自定义逻辑正确运行特别有用。


支持应用程序跟踪透明度 (ATT)

App Tracking Transparency (ATT) 是 Apple 的隐私框架,要求在访问设备的 IDFA(广告商识别码)和共享用户数据前征得用户同意。正确实施 ATT 对于 iOS 归因和最大限度地提高用户获取活动的准确性至关重要。

ATT 为何对归因至关重要

从 iOS 14.5 开始,应用程序在访问 IDFA 之前必须通过 ATT 框架请求用户许可。虽然在没有 IDFA 的情况下仍可使用指纹识别和概率方法进行归因,但有了 IDFA,归因的准确性会大大提高,并提供确定性匹配。

  • 确定性归属:IDFA 可实现精确的设备级归因,将广告印象与安装直接联系起来。
  • 广告网络优化:通过访问 IDFA,广告网络可以更好地优化广告活动并提供更准确的报告。
  • 用户级洞察:访问 IDFA 可以进行更精细的用户行为分析和群组跟踪。

建议:Singular 强烈建议实施 ATT 提示并征求用户同意。向用户解释这样做的好处(个性化广告、更好的应用体验),以最大限度地提高选择加入率。

实施要求

对于 iOS 14.5 以上版本(包括 iOS 18),在访问 IDFA 进行跟踪之前,使用 ATTrackingManager 框架请求用户同意。Singular SDK 支持 ATT,允许在用户同意之前进行初始化,并延迟事件直到用户同意或出现超时。

步骤 1:添加 ATT 框架配置

用面向用户的使用说明更新 Info.plist 文件,配置 iOS 应用程序以支持 ATT 框架。

  1. 打开 Info.plist:导航至 iOS 项目的 Info.plist 文件(位于ios/[YourAppName]/Info.plist )。
  2. 添加使用说明:添加NSUserTrackingUsageDescription 密钥,并清楚地解释应用程序需要跟踪权限的原因。
Info.plist
<key>NSUserTrackingUsageDescription</key>
<string>This app uses tracking to provide personalized ads and improve your experience.</string>

重要:使用说明将在 ATT 提示中显示给用户。请清晰、简洁、诚实地说明跟踪如何使用户受益。

第 2 步:安装 ATT 支持包

安装 React Native ATT 支持包,在应用程序中启用 ATT 功能。

bash
npm install react-native-tracking-transparency --save

安装完成后,从 iOS 目录运行pod install ,链接原生依赖项。

bash
cd ios && pod install && cd ..

第 3 步:配置 SDK 等待超时

通过设置waitForTrackingAuthorizationWithTimeoutInterval 属性,配置 Singular SDK 在初始化前等待用户的 ATT 响应。该延迟可确保在用户授予权限时捕获 IDFA。

关键: Singular SDK 发送第一个会话之前,一定要请求 ATT 同意并检索 IDFA。否则将永久丢失该设备属性数据的 IDFA。

New ArchitectureOld Architecture
// 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
};

建议值:如果您的应用程序显示 ATT 提示,请将超时设置为 300 秒(5 分钟)。这将为用户提供足够的时间查看和回复提示,而不会因提示延迟或未显示而造成不良的用户体验。

步骤 4:请求 ATT 同意

在应用程序中实施 ATT 请求流程,在用户体验的适当时间提示用户获得跟踪权限。

New ArchitectureOld Architecture
// 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
  );
}

ATT 最佳实践

  • 预提示信息:向用户显示 ATT 前屏幕,解释为什么需要跟踪许可,以及跟踪许可对用户有什么好处(更好的广告、更好的体验)。这可以大大提高选择加入率。
  • 时机很重要:在应用程序流程中的自然时刻显示 ATT 提示,而不是在首次启动时立即显示。让用户先体验您的应用,以建立信任。
  • 超时配置:waitForTrackingAuthorizationWithTimeoutInterval 设置为 30-300 秒。超时后,Singular 将继续使用 SKAN 4.0 归属(无 IDFA)。
  • 全面测试:测试授权和拒绝两种情况,以确保无论用户如何选择,您的应用程序都能正常运行。
  • 尊重用户的选择:切勿反复提示已拒绝跟踪的用户,或向其展示咄咄逼人的信息,迫使其选择加入。
  • 错误处理:检查restricted (如家长控制)或unavailable 状态的跟踪状态,并记录分析日志。

应用程序商店审查:未正确实施 ATT 或试图规避框架的应用程序可能会在 App Store 审核期间被拒绝。确保您的实施遵循 Apple 的指导原则并尊重用户的隐私选择。

其他资源