支持 SKAdNetwork
SKAdNetwork 是苹果公司针对 iOS 应用程序安装活动推出的注重隐私的归因框架。Singular Flutter SDK 默认在托管模式下启用 SKAdNetwork,Singular 会根据您在仪表板中配置的转换模型自动更新转换值。
无需额外配置:如果您使用的是最新的 Flutter SDK,SKAdNetwork 开箱即用。基本功能无需更改代码或进行额外设置。
了解 SKAN 模式
托管模式(默认)
在托管模式下,Singular 会根据您在仪表板中配置的转换模型自动处理转换值更新。这是大多数应用程序的推荐方法,因为它只需最少的代码,并提供最佳的转换跟踪。
- 自动更新:Singular 根据用户事件和配置的模型管理所有转换值更新。
- 仪表板配置:在 Singular 面板中设计转换模型,无需修改代码。
- 优化:受益于 Singular 在苹果限制条件下最大化转换值更新的专业知识。
- 24 小时窗口管理:Singular 可智能处理 SKAdNetwork 的 24 小时更新窗口,最大限度地收集数据。
手动模式(高级)
手动模式可让您完全控制转换值更新,允许您实施自定义逻辑,以确定何时以及如何更新 SKAN 转换值。只有当您有管理模式无法满足的特殊要求时,才可使用此模式。
高级功能:手动模式需要仔细实施并了解 Apple 的 SKAdNetwork 限制,包括转换值更新窗口和限制。大多数应用程序应使用托管模式。
禁用 SKAdNetwork 支持
SKAdNetwork 跟踪功能默认已启用。要禁用它,请在构建 SingularConfig 对象时将skAdNetworkEnabled 配置属性设置为 false。
import 'package:singular_flutter_sdk/singular_config.dart';
SingularConfig config = SingularConfig('API_KEY', 'SECRET');
config.skAdNetworkEnabled = false; // Disable SKAdNetwork
配置手动模式
要实现自定义转换值逻辑,请启用手动模式,并使用提供的 SDK 方法在应用程序的整个生命周期内更新和监控转换值。
启用手动模式
在构建 SingularConfig 对象时,将manualSkanConversionManagement 配置属性设为 true,以便控制转换值更新。
import 'package:singular_flutter_sdk/singular_config.dart';
SingularConfig config = SingularConfig('API_KEY', 'SECRET');
config.manualSkanConversionManagement = true; // Enable manual mode
重要:手动更新方法只有在manualSkanConversionManagement 启用时才会起作用。如果启用了托管模式,手动更新将被忽略。
更新转换值(SKAN 2.0-3.0)
使用skanUpdateConversionValue 方法,根据自定义逻辑手动更新 SKAdNetwork 转换值。转换值必须是 0 到 63 之间的整数。
方法签名
static void skanUpdateConversionValue(int conversionValue)
使用示例
import 'package:singular_flutter_sdk/singular.dart';
import 'dart:io';
// User completed signup - update conversion value to 7
void onUserSignUp() {
if (Platform.isIOS) {
// Track the sign-up event
Singular.event('SignUp');
// Update SKAN conversion value
Singular.skanUpdateConversionValue(7);
print('Conversion value updated to 7');
}
}
// User completed purchase - update based on purchase amount
void onPurchaseComplete(double purchaseAmount) {
if (Platform.isIOS) {
// Track revenue event
Singular.customRevenue('Purchase', 'USD', purchaseAmount);
// Calculate conversion value based on purchase tier
int conversionValue = calculateConversionValue(purchaseAmount);
Singular.skanUpdateConversionValue(conversionValue);
print('Conversion value updated to $conversionValue');
}
}
int calculateConversionValue(double 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 void skanUpdateConversionValues(
int conversionValue, // Fine value (0-63)
int coarse, // Coarse value (0=low, 1=medium, 2=high)
bool lock // Lock status
)
使用示例
import 'package:singular_flutter_sdk/singular.dart';
import 'dart:io';
void updateSKAN4ConversionValue(
int fineValue,
String coarseValue,
bool shouldLock
) {
if (Platform.isIOS) {
// Map coarse value string to number
Map<String, int> coarseMap = {
'low': 0,
'medium': 1,
'high': 2
};
// Update SKAdNetwork 4.0 conversion values
Singular.skanUpdateConversionValues(
fineValue,
coarseMap[coarseValue] ?? 0,
shouldLock
);
print('SKAN 4.0 updated: fine=$fineValue, coarse=$coarseValue, lock=$shouldLock');
}
}
// Example: High-value user completes tutorial
void onTutorialComplete() {
updateSKAN4ConversionValue(15, 'medium', false);
}
// Example: Premium purchase - lock the value
void onPremiumPurchase() {
updateSKAN4ConversionValue(63, 'high', true);
}
获取当前转换值
读取由 Singular SDK 跟踪的当前转换值。这对于根据当前状态实施条件逻辑非常有用,在托管和手动模式下均可使用。
方法签名
static Future<int> skanGetConversionValue()
使用示例
import 'package:singular_flutter_sdk/singular.dart';
import 'dart:io';
Future<void> checkAndUpdateConversionValue() async {
if (Platform.isIOS) {
int currentValue = await Singular.skanGetConversionValue();
print('Current conversion value: $currentValue');
// Only update if current value is below threshold
if (currentValue < 30) {
Singular.skanUpdateConversionValue(30);
print('Updated conversion value to 30');
}
}
}
监控转换值更新
设置一个处理程序,以便在转换值发生变化时接收实时通知。这样,您就可以对转换值更新做出反应,并记录分析结果或触发其他应用程序行为。
配置
在初始化 SDK 时使用conversionValueUpdatedCallback 属性配置转换值更新处理程序。
import 'package:singular_flutter_sdk/singular.dart';
import 'package:singular_flutter_sdk/singular_config.dart';
void initializeSingularSDK() {
SingularConfig config = SingularConfig('API_KEY', 'SECRET');
// Set up conversion value update handler
config.conversionValueUpdatedCallback = (int conversionValue) {
print('Conversion value updated to: $conversionValue');
// Log the update to your analytics
logConversionValueUpdate(conversionValue);
// Trigger app-specific behavior
if (conversionValue >= 50) {
unlockPremiumFeature();
}
};
Singular.start(config);
}
void logConversionValueUpdate(int value) {
// Your analytics logging logic
print('Analytics: SKAN CV = $value');
}
void unlockPremiumFeature() {
// Your custom logic
print('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 框架。
-
打开 Info.plist:导航至 Flutter 项目的 iOS Info.plist 文件(位于
ios/Runner/Info.plist)。 -
添加使用说明:添加
NSUserTrackingUsageDescription关键字,并清楚解释为什么您的应用程序需要跟踪权限。
<key>NSUserTrackingUsageDescription</key>
<string>This app uses tracking to provide personalized ads and improve your experience.</string>
重要:使用说明将在 ATT 提示中显示给用户。请清晰、简洁、诚实地说明跟踪如何使用户受益。
第 2 步:安装 ATT 支持软件包
安装 Flutter ATT 支持包,在您的应用程序中启用 ATT 功能。我们推荐使用app_tracking_transparency 插件。
添加依赖项
dependencies:
flutter:
sdk: flutter
singular_flutter_sdk: ^1.8.0
app_tracking_transparency: ^2.0.4
添加依赖后,运行flutter pub get 安装软件包。
flutter pub get
替代软件包:虽然我们推荐使用app_tracking_transparency,但您也可以使用任何提供类似功能的 Flutter ATT 插件。 确保插件支持 iOS 14.5 以上版本。
第 3 步:配置 SDK 等待超时
通过设置waitForTrackingAuthorizationWithTimeoutInterval 属性,配置 Singular SDK 在初始化前等待用户的 ATT 响应。此延迟可确保在用户授予权限时捕获 IDFA。
关键: 在Singular SDK 发送第一个会话之前,一定要请求 ATT 同意并检索 IDFA。否则将永久丢失该设备属性数据的 IDFA。
import 'package:singular_flutter_sdk/singular_config.dart';
SingularConfig config = SingularConfig('API_KEY', 'SECRET');
config.waitForTrackingAuthorizationWithTimeoutInterval = 300; // Wait up to 5 minutes
建议值:如果您的应用程序显示 ATT 提示,请将超时设置为 300 秒(5 分钟)。这将为用户提供足够的时间查看和回复提示,而不会因提示延迟或未显示而造成不良的用户体验。
步骤 4:请求 ATT 同意
在应用程序中实施 ATT 请求流程,在用户体验的适当时间提示用户获得跟踪权限。
import 'package:flutter/material.dart';
import 'dart:io';
import 'package:singular_flutter_sdk/singular.dart';
import 'package:singular_flutter_sdk/singular_config.dart';
import 'package:app_tracking_transparency/app_tracking_transparency.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
void initState() {
super.initState();
initializeApp();
}
Future<void> initializeApp() async {
if (Platform.isIOS) {
// Request ATT authorization
final trackingStatus = await AppTrackingTransparency.requestTrackingAuthorization();
// Log the user's response
print('ATT Status: $trackingStatus');
// Possible values: TrackingStatus.authorized, .denied, .restricted, .notDetermined
}
// Initialize Singular SDK (configured with wait timeout)
SingularConfig config = SingularConfig('API_KEY', 'SECRET');
config.waitForTrackingAuthorizationWithTimeoutInterval = 300;
config.enableLogging = true;
Singular.start(config);
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: MyHomePage(),
);
}
}
了解 ATT 流程
当您使用waitForTrackingAuthorizationWithTimeoutInterval 设置初始化延迟时,应用流程的工作原理如下:
- 当应用程序打开时,Singular SDK 会开始记录会话和用户事件,但不会将它们发送到 Singular 服务器。
- 当授予/拒绝应用程序跟踪透明度同意或设定时间过去后,SDK 会将会话和任何排队事件发送到 Singular 服务器(无论是否有 IDFA)。
- 然后,Singular 会利用 IDFA(如果有的话)启动归属过程。
ATT 场景
下表总结了使用该集成的可能场景:
| 方案 | IDFA 可用性 |
| 用户看到 "同意 "对话框,并在设定时间结束前表示同意。 | IDFA 可用 |
| 用户看到同意对话框,并在设定时间结束前拒绝同意。 | IDFA 不可用 |
| 设定时间结束后,用户看到同意对话框并同意。 | IDFA 仅对同意后报告的用户事件有效 |
| 设置的时间已过,然后用户将看到同意对话框并拒绝同意。 | IDFA 不可用 |
| 用户看到同意对话框,未采取任何操作就退出了应用程序,然后在设定时间到期后打开应用程序并同意。 | 重新打开应用程序时,任何排队的事件都会发送到 Singular 服务器。在同意后跟踪的任何事件都有与之相关的 IDFA。 |
| 用户看到同意对话框后,未采取任何行动即退出应用程序,随后打开应用程序并拒绝同意。 | 重新打开应用程序时,任何排队的事件都会发送到 Singular 服务器。IDFA 不能用于这些事件或之后跟踪的任何事件。 |
ATT 最佳实践
- 预先提示消息:向用户显示 ATT 前屏幕,解释为什么需要跟踪许可,以及跟踪许可对用户有什么好处(更好的广告、更好的体验)。这可以大大提高选择加入率。
- 时机很重要:在应用程序流程中的自然时刻显示 ATT 提示,而不是在首次启动时立即显示。让用户先体验您的应用,以建立信任。
-
超时配置:将
waitForTrackingAuthorizationWithTimeoutInterval设置为 30-300 秒。超时后,Singular 将继续使用 SKAN 4.0 归属(无 IDFA)。 - 全面测试:测试授权和拒绝两种情况,以确保无论用户如何选择,您的应用程序都能正常运行。
- 尊重用户的选择:切勿反复提示已拒绝跟踪的用户,或向其展示咄咄逼人的信息,迫使其选择加入。
-
错误处理:检查
restricted(如家长控制)或notDetermined状态的跟踪状态,并记录分析日志。 - SKAN 4.0 集成:确保转换值更新与 ATT 同意保持一致,以优化 SKAN 回传(例如,使用 Singular 的仪表板将事件映射到 0-63 值)。
应用程序商店审查:未正确实施 ATT 或试图规避框架的应用程序可能会在 App Store 审核期间被拒绝。请确保您的实施遵循 Apple 的指导原则并尊重用户的隐私选择。