关于 contentsquare-flutter-sdk
供 AI Agent 在客户端应用中集成或升级 Contentsquare Flutter SDK 的技能,涵盖项目健康检查、SDK 配置、分析埋点和迁移指引。
主要功能
- 01项目配置健康检查
- 02Flutter SDK 安装与设置
- 03屏幕和 WebView 跟踪指引
- 04分析与回放 API 指引
- 05SDK 版本迁移指引
适用场景
- 01在 Flutter 应用中集成 Contentsquare
- 02升级现有 Contentsquare SDK
- 03排查项目配置与跟踪问题
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ contentsquare/ agents --skill contentsquare-flutter-sdk安装后在 Claude Code 中输入/contentsquare-flutter-sdk确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/api-reference.mdcommon-patterns.mdios-in-app-features.mdmigration.mdscreen-tracking.mdsession-replay.md详细介绍
Contentsquare Flutter SDK 集成
此技能可帮助 AI Agent 在客户端应用中集成或升级 Contentsquare Flutter SDK。
必须先执行 -- Contentsquare 项目健康检查
在对话中开展任何 Contentsquare 相关工作之前——包括集成、调试、配置问题和代码更改——都要在每次对话中恰好执行一次此健康检查。不得跳过,也不得推迟到任务后续阶段。
-
先告知用户。 告诉用户你即将进行的操作,例如:
“开始之前,我会快速检查一下你的 Contentsquare 项目:我会询问你的数据源 ID(如果没有,则读取应用的包 ID),调用 Contentsquare 健康检查端点,并向你展示当前项目配置。然后我们再继续。”
-
先询问用户的 Contentsquare 数据源 ID。 例如:“你有 Contentsquare 数据源 ID 吗?可能有一个或多个,例如 Android 和 iOS 各一个。如果有,请告诉我每个 ID 对应的平台。” 只能使用用户提供的 ID,绝不能编造 ID。
- 用户提供了一个或多个数据源 ID → 仅按数据源 ID 检查(
v3)。跳过第 3 步。 - 用户只有环境 ID → 仅按包 ID 检查(
v2):环境 ID 不是数据源 ID,在v3流程中永远无法使用。 - 用户没有、不知道或跳过此问题 → 仅按包 ID 检查(
v2)。
- 用户提供了一个或多个数据源 ID → 仅按数据源 ID 检查(
-
解析包 ID(仅在没有数据源 ID 时)——Flutter 应用有两个包 ID,而且它们经常是不同的字符串。 分别解析每个包 ID;绝不要假设它们相同。
平台 读取位置 Android android/app/build.gradle(.kts)中的applicationId(如果没有,则使用namespace,或AndroidManifest.xml中的package)iOS ios/Runner.xcodeproj/project.pbxproj中的PRODUCT_BUNDLE_IDENTIFIER(或ios/Runner/Info.plist中的CFBundleIdentifier),解析其中任何$(...)变量 -
调用端点——只使用一个版本,绝不能同时调用两个版本。 平台段必须是字面值
ios或android。不存在 Flutter 平台值,绝不要传入。使用数据源 ID(
v3)时,每个 ID 调用一次:curl -s "https://mobile-production.content-square.net/healthcheck/android/config/v3/<dataSourceId>.json" curl -s "https://mobile-production.content-square.net/healthcheck/ios/config/v3/<dataSourceId>.json"根据用户提供的平台查询每个 ID。如果平台未知,则在项目中存在的每个平台上查询:某个平台返回非 200,仅表示该数据源未针对该平台设置。
如果某个 ID 在所有查询的平台上都没有获得
200,请告知用户——该 ID 可能是环境 ID,也可能存在拼写错误——并询问是否可以自行在代码中查找数据源 ID:它是传递给StartConfig.withDatasourceId(id: ...)的 ID(如果它来自常量或配置文件,请继续追溯到其字面值)。如果用户同意并且你找到了不同的 ID,则使用该 ID 执行一次v3检查。如果用户拒绝,或者代码中没有该 ID,则不使用它继续操作。没有数据源 ID 时(
v2),每个存在的平台调用一次:curl -s "https://mobile-production.content-square.net/healthcheck/android/config/v2/<androidApplicationId>.json" curl -s "https://mobile-production.content-square.net/healthcheck/ios/config/v2/<iosBundleId>.json"如果项目中只存在一个平台,则只查询该平台。如果无法解析某个平台的包 ID,请询问用户要检查哪个平台,而不要猜测。
-
简要报告每次返回
200的调用所对应的以下值:报告 JSON 路径 项目 ID cs_project_id跟踪已启用 project_configurations.project_config.enabled会话回放 project_configurations.project_config.session_replay--recording_rate,record_via_cellular_network,recording_quality_wifi,srm_enabled,user_identifier已启用的功能标志 project_configurations.project_config.feature_flags-- 仅包含enabled == true的条目,以及其name和min_version对于
v3调用,还要报告环境 ID(environment_id)。Android 和 iOS 可能映射到不同的 Contentsquare 项目。如果响应不同,请明确指出。
-
然后继续处理用户的实际请求。
失败处理。 403 Invalid health-check path 表示 URL 格式错误——请重新检查 ios/android、v2/v3 部分和 ID,不要更改路径结构。上游代理返回非 200 状态码,表示该数据源 ID 或 bundle ID 在此平台上没有 Contentsquare 配置:请说明这一点,然后继续处理——不要尝试另一个版本(唯一允许的重试是步骤 4 中的代码查询)。此健康检查仅供参考,绝不能阻碍用户的任务。
安装
dependencies:
contentsquare: ^4.5.1
然后运行 flutter pub get。
已使用
^4.1.x? 此版本在AnalyticsOptions/ProductAnalyticsOptions中包含破坏性变更(移除了若干字段),并弃用了configureProductAnalytics(...)。升级前请阅读从 4.1.x 迁移到 4.5.1部分。
已使用
^3.x? v4 版本包含破坏性变更,包括 API 重命名、移除ContentsquareRoot以及原生代码清理。升级前请阅读从旧版ContentsquareAPI 迁移到CSQ(v3.x → v4.x)部分。
快速入门
import 'package:contentsquare/csq.dart';
import 'dart:async';
import 'package:flutter/material.dart';
void main() async {
runZonedGuarded(() async {
WidgetsFlutterBinding.ensureInitialized();
FlutterError.onError = (details) {
CSQ().collectFlutterError(details: details);
};
await CSQ().start();
await CSQ().optIn(); // TODO: customer to manage consent — call only after user accepts
runApp(const MyApp());
}, (error, stack) => CSQ().collectError(error: error, stackTrace: stack));
}
仅当应用架构有此需要时才使用
runZonedGuarded。不使用它的替代初始化方式:references/common-patterns.md。
跟踪屏幕非常重要,否则会话回放将无法正常工作。你可以使用 trackScreenview() 手动跟踪屏幕,也可以使用推荐的 CSQNavigatorObserver 自动跟踪。
添加自动屏幕跟踪:
MaterialApp(
navigatorObservers: [CSQNavigatorObserver()],
);
重要:请完成 iOS 应用内功能所需的 iOS 设置。
在封装 MVP 之前,请确保处理应用中存在的 WebView。WebView 不会自动跟踪,必须封装每个 WebView。详情请参阅下方的 WebView 部分。
API 概览
始终使用 package:contentsquare/csq.dart 中的 CSQ。Contentsquare 类已弃用。
生命周期
| 方法 | 用途 |
|---|---|
start({StartConfig, CSQMaskingConfig?}) | 启动 SDK。必须在调用任何其他 API 之前调用。 |
stop() | 完全关闭 SDK。 |
pauseTracking() | 暂停数据收集(用于敏感屏幕)。除非有明确要求,否则请避免使用。 |
resumeTracking() | 在调用 pauseTracking() 后恢复。 |
StartConfig 变体
| 工厂 | 使用场景 | 引导优先级 |
|---|---|---|
StartConfig.withDatasourceId(id:, options:) | 使用数据源 ID 的 CSQ | 新客户端的首选——优先询问此项 |
StartConfig.withEnvironmentId(id:, options:) | 使用环境 ID 的 Product Analytics | 如果没有可用的数据源 ID,则作为第二选择 |
StartConfig.dxa({options}) | 仅 Digital Experience Analytics(默认)。options 为 AnalyticsOptions——4.2.0 中新增 | 仅在没有可用 ID 或明确要求仅使用 DXA 时作为后备选项 |
这三个变体都接受相同的 AnalyticsOptions 对象(请参见下文 AnalyticsOptions 部分)。
推荐的引导流程:
- 询问用户:“您有 Contentsquare 数据源 ID 吗?”(如果用户已在健康检查期间回答过,则跳过此问题)。如果有,请使用
StartConfig.withDatasourceId(id: ...)。 - 如果没有,询问:“您有环境 ID 吗?” 如果有,请使用
StartConfig.withEnvironmentId(id: ...)。 - 只有在两者都不可用(或用户明确希望仅使用 DXA)时,才回退到
StartConfig.dxa()。 - 询问:“您的 Product Analytics / Unified CSQ 环境托管在 EU 吗?” 如果是,请在
AnalyticsOptions中设置baseUrl: Uri.parse('https://mh.ba.contentsquare.net')。默认端点位于 US——如果不进行此覆盖,EU 环境将无法接收数据。
不要编造 ID。不要默认使用 DXA。不要假定托管区域为 US——务必询问。
隐私
| 方法 | 用途 |
|---|---|
optIn() | 允许设备进行跟踪。立即开始。 |
optOut() | 永久停用。直到调用 optIn() 或重新安装应用才会停止。 |
身份
| 方法 | 场景 | 用途 |
|---|---|---|
identify(userIdentifier:) | Product Analytics | 设置用户身份。不同的 ID 会触发新会话。 |
resetIdentity() | Product Analytics | 清除身份。会触发新会话。 |
sendUserIdentifier(userIdentifier:) | DXA | 发送经过哈希处理的用户 ID。最多 100 个字符。 |
屏幕跟踪
| 方法 | 用途 |
|---|---|
trackScreenview(screenName:, customVars:) | 跟踪屏幕浏览,可选择添加自定义变量。 |
CustomVar(index:, name:, value:) —— index(int)、name(String)、value(String)。
交易
await CSQ().trackTransaction(
Transaction(price: 29.99, currency: Currency.USD, id: 'order_123'),
);
Currency 是 ISO 4217 枚举(例如,Currency.USD、Currency.EUR)。
自定义事件和属性
| 方法 | 用途 |
|---|---|
trackEvent(eventName:, properties:) | 跟踪命名事件,可选择添加属性。 |
addDynamicVar(DynamicVar) | 添加会话级动态变量。 |
addUserProperties(properties:) | 设置用户级属性。 |
addEventProperties(properties:) | 为所有后续事件设置属性。 |
removeEventProperty(name:) | 移除一个事件属性。 |
clearEventProperties() | 移除所有事件属性。 |
属性值必须是 String、num 或 bool。其他类型会被静默忽略。
DynamicVar 工厂方法:DynamicVar.fromString(key:, value:) 和 DynamicVar.fromInt(key:, value:)。
会话回放
| 方法 | 用途 |
|---|---|
triggerReplayForCurrentSession(name:) | 标记会话以进行回放采集(用于分组/筛选)。 |
triggerReplayForCurrentScreen(name:) | 标记当前屏幕以进行回放采集。 |
startSessionReplay() (new in 4.2.0) | 按需启动会话回放。若在调用 start() 时传入了 sessionReplayAutoStart: false,请使用此方法。仅限一次——这不是重启 API。 |
stopSessionReplay() (new in 4.2.0) | 按需停止会话回放,但不停止 SDK。终止性操作——在同一 SDK 生命周期内,之后无法重新启动 SR。 |
按需会话回放——在 SDK 启动时禁用自动启动,并手动控制:
await CSQ().start(
startConfig: StartConfig.dxa(
options: const AnalyticsOptions(sessionReplayAutoStart: false),
),
);
// later, when you want SR to start (e.g., entering a checkout flow):
await CSQ().startSessionReplay();
// and to stop it (final -- no restart afterwards):
await CSQ().stopSessionReplay();
startSessionReplay/stopSessionReplay只能启动和停止,不能暂停或恢复。调用stopSessionReplay()后,SR 将保持关闭状态,直到下一个 SDK 生命周期。
会话元数据(获取回放链接)
访问会话信息,包括回放 URL:
// Get current session replay URL (returns Uri?)
final replayUrl = CSQ().metadata.sessionReplayUrl;
// Listen for metadata changes
final subscription = CSQ().metadata.onChange((metadata) {
print('Session Replay URL: ${metadata.sessionReplayUrl}');
});
subscription.cancel(); // Stop listening when done
Metadata 字段:projectId、environmentId、userId、identity、sessionId、sessionReplayUrl(Uri?)。
错误报告
| 方法 | 用途 |
|---|---|
collectFlutterError(details:, presentErrorDetails:) | 报告 Flutter 框架错误。 |
collectError(error:, stackTrace:) | 报告捕获的错误。 |
setURLMaskingPatterns(patterns:) | 在错误跟踪中遮蔽敏感 URL 路径。电子邮件地址会自动遮蔽。 |
如需自动跟踪 HTTP 请求错误,请在应用启动时将 CSQHttpOverrides 安装为全局 HTTP 覆盖设置——请参阅 references/api-reference.md。
Debug and Metadata
| API | Purpose |
|---|---|
debug.setLogLevel(LogLevel) | Set log level (info, verbose, etc.) |
metadata | Access session metadata. metadata.onChange(handler) to listen. |
AnalyticsOptions(由所有 StartConfig 变体共用)
所有字段均可为空(null = 原生默认行为)。
| 字段 | 类型 | 平台 | 用途 |
|---|---|---|---|
enableInteractionsAutocapture | bool? | 两者 | 启用 Flutter 交互自动捕获(PA) |
disablePageviewAutocapture | bool? | 两者 | 禁用原生页面浏览自动捕获 |
enablePushNotificationAutocapture | bool? | 两者 | 捕获推送通知事件 |
enablePushNotificationTitleAutocapture | bool? | 两者 | 捕获推送通知标题 |
enablePushNotificationBodyAutocapture | bool? | 两者 | 捕获推送通知正文 |
baseUrl | Uri? | 两者 | 自定义 API 端点。Product Analytics 欧盟托管环境必填:设置为 Uri.parse('https://mh.ba.contentsquare.net')。也用于本地部署/自定义端点。 |
uploadInterval | Duration? | 两者 | 事件上传频率 |
sessionReplayAutoStart | bool? | 两者 | 如果为 false,SR 不会在 SDK 启动时开始——请使用 startSessionReplay() |
disablePageviewTitleAutocapture | bool? | 仅 iOS | 禁用 iOS 页面标题自动捕获 |
disableInteractionAutocapture | bool? | 仅 iOS | 禁用原生 iOS 交互自动捕获 |
在 4.2.0 中移除(重大变更):
captureVendorId、captureAdvertiserId、clearEventPropertiesOnNewUser、resumePreviousSession、disableScreenviewForwardToDXA、disableScreenviewForwardToPA、messageBatchByteLimit、messageBatchMessageLimit、pruningLookBackWindow、maximumDatabaseSize、maximumBatchCountPerUpload。替代方案请参阅 references/migration.md。
ProductAnalyticsOptions现在是AnalyticsOptions的typedef别名(为保持向后兼容而保留)。新代码中请优先使用AnalyticsOptions。
会话回放遮罩
全局遮罩(启动时)
await CSQ().start(
maskingConfig: const CSQMaskingConfig(
maskTexts: true,
maskTextFields: true,
maskImages: false,
),
);
范围遮罩(针对单个 widget 子树)
CSQMask(
config: const CSQMaskingConfig(maskTexts: true, maskInteractions: true),
child: Text('Sensitive content'),
)
CSQMaskingConfig 字段
| 字段 | 屏蔽内容 |
|---|---|
maskTexts | Text、RichText |
maskTextFields | TextField、TextFormField |
maskImages | Image 组件 |
maskSvgImages | SVG 渲染的图片 |
maskCharts | fl_chart 组件 |
maskCustomPaints | 开发者的 CustomPaint 组件 |
maskInteractions | 用户交互(仅限 Product Analytics) |
便捷方法:CSQMaskingConfig.maskAll() 和 CSQMaskingConfig.unMaskAll()。
Navigator Observer(自动屏幕跟踪)
添加 observer 之前,请检查
pubspec.yaml,确认使用的导航包:
auto_route→ 使用CSQNavigatorAutoRouteObserver(请参阅下文的 AutoRoute 部分)go_router→ 通过GoRouter(observers: [...])使用CSQNavigatorObserver- 两者都未使用 → 通过
MaterialApp(navigatorObservers: [...])使用CSQNavigatorObserver
标准 Flutter Navigator(MaterialApp / CupertinoApp)
import 'package:contentsquare/csq.dart';
MaterialApp(
navigatorObservers: [
CSQNavigatorObserver(
screenNameProvider: (route) {
if (route.settings.name == '/profile') return 'User Profile';
return route.settings.name;
},
customVarsProvider: (route) => [
CustomVar(index: 1, name: 'section', value: 'main'),
],
excludeRouteFromTracking: (route) =>
route.settings.name?.startsWith('/debug') ?? false,
),
],
);
三个回调均为可选项。不设置时,路由名称将用作屏幕名称。
默认情况下,模态路由(
showDialog、showModalBottomSheet等)会作为单独的屏幕进行跟踪。使用excludeRouteFromTracking可跳过这些路由。
GoRouter
无需额外的包。通过 GoRouter 的 observers 参数传入 CSQNavigatorObserver,不要通过 MaterialApp.router 传入。
GoRouter(
observers: [CSQNavigatorObserver()],
routes: [...],
)
在
GoRoute中使用pageBuilder时,必须在MaterialPage上设置name,否则 observer 收到的路由将没有名称。请参阅 references/common-patterns.md。
AutoRoute
AutoRoute 与 CSQNavigatorObserver 不兼容。请使用 csq_navigator_auto_route_observer 包中的 CSQNavigatorAutoRouteObserver。它还会自动处理标签页导航(didInitTabRoute / didChangeTabRoute)。
将 csq_navigator_auto_route_observer: ^1.1.0 添加到 dependencies,然后将其附加到路由器配置:
import 'package:csq_navigator_auto_route_observer/csq_navigator_auto_route_observer.dart';
MaterialApp.router(
routerConfig: _appRouter.config(
navigatorObservers: () => [
CSQNavigatorAutoRouteObserver(),
],
),
);
支持与 CSQNavigatorObserver 相同的三个可选回调(screenNameProvider、customVarsProvider、excludeRouteFromTracking)。完整的回调参考和模态路由排除示例请参阅:references/screen-tracking.md。
兼容性: AutoRoute >=10.1.0+1 <12.0.0、csq_navigator_auto_route_observer ^1.1.0。
PageView 和 TabBar(需要手动跟踪)
PageView 滑动和标准 TabBar 标签切换不会推送路由,因此不会触发 observer。请手动调用 trackScreenview:
- PageView:使用
onPageChanged回调 - TabBar:使用
TabController.addListener
完整代码示例请参阅 references/screen-tracking.md。
WebView 跟踪
WebView 不会自动跟踪。必须使用 CSQWebViewWrapper 包装 WebView,并设置 JavaScript 通道桥接,以便在原生应用和网页内容之间进行会话拼接。
前提条件:
- 必须在 WebView 中启用 JavaScript
- WebView 加载的网页必须使用适用于 WebView 模式的 Contentsquare Web Tracking Tag
使用 webview_flutter(JSChannelWebViewWrapperDelegate)
import 'package:contentsquare/csq.dart';
import 'package:webview_flutter/webview_flutter.dart';
webViewController.setJavaScriptMode(JavaScriptMode.unrestricted);
CSQWebViewWrapper(
delegate: JSChannelWebViewWrapperDelegate(
addJavaScriptChannel: (WebViewJSChannelHandler handler) {
webViewController.addJavaScriptChannel(
handler.channelName,
onMessageReceived: (jsMessage) {
handler.onMessageReceived(jsMessage.message);
},
);
},
builder: (context) {
return WebViewWidget(controller: webViewController);
},
),
);
使用 flutter_inappwebview(UserScriptWebViewWrapperDelegate)
import 'dart:collection';
import 'package:contentsquare/csq.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
CSQWebViewWrapper(
delegate: UserScriptWebViewWrapperDelegate(
builder: (BuildContext context, String userScript) {
return InAppWebView(
initialOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(javaScriptEnabled: true),
),
initialUrlRequest: URLRequest(url: Uri.parse(url)),
initialUserScripts: UnmodifiableListView([
UserScript(
source: userScript,
injectionTime: UserScriptInjectionTime.AT_DOCUMENT_START,
),
]),
);
},
),
);
重要提示:
- 始终使用
handler.channelName作为通道名称(不要硬编码) - 始终在 JavaScript 通道回调中调用
handler.onMessageReceived(...) - 对于
UserScript,始终将injectionTime设为AT_DOCUMENT_START - 底层 WebView 在 Android 上必须使用
android.webkit.WebView,在 iOS 上必须使用WKWebView
常见模式
1. 完整初始化并处理错误
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await CSQ().start(
maskingConfig: const CSQMaskingConfig(maskTexts: true, maskTextFields: true),
);
await CSQ().optIn();
FlutterError.onError = (details) {
CSQ().collectFlutterError(details: details);
};
runZonedGuarded(
() => runApp(const MyApp()),
(error, stack) => CSQ().collectError(error: error, stackTrace: stack),
);
}
2. 按需会话回放(敏感流程)
// 1) Disable SR auto-start globally
await CSQ().start(
startConfig: StartConfig.withEnvironmentId(
id: 'your-env-id',
options: const AnalyticsOptions(sessionReplayAutoStart: false),
),
);
// 2) Start SR once, when entering the flow you want recorded
await CSQ().startSessionReplay();
// 3) Stop SR when the flow is done.
// WARNING: this is terminal for the SDK lifetime -- you cannot
// restart SR after this call. Do NOT wire it to dispose() of
// short-lived widgets if you may want SR again later in the same session.
await CSQ().stopSessionReplay();
更多模式(产品分析设置、事务、同意流程、自定义事件):references/common-patterns.md。
iOS 应用内功能设置
要在 iOS 上使用 Contentsquare 应用内功能(截图捕获、SDK 日志、Zoning Analysis),需要进行原生 iOS 配置:
- 添加 URL scheme 到
ios/Runner/Info.plist:cs-$(PRODUCT_BUNDLE_IDENTIFIER) - 在
AppDelegate.swift中调用CSQ.handle(url: url)处理深层链接
这是少数允许编辑原生文件的情况之一。
查看包含 AppDelegate、SceneDelegate 和 SwiftUI 代码示例的完整实现指南:references/ios-in-app-features.md
迁移
完整的迁移指南位于 references/migration.md。升级前请先加载该文件。
| 客户当前状态 | 要阅读的迁移指南 |
|---|---|
使用 ^3.x,采用 Contentsquare() 单例、ContentsquareRoot、MaskingConfig、ContentsquareNavigatorObserver 等。 | 旧版 Contentsquare API 迁移到 CSQ(v3.x → v4.x) -- API 重命名、移除 ContentsquareRoot、清理原生 AndroidManifest.xml / Info.plist、将 Swift 的 Contentsquare.handle( 替换为 CSQ.handle(。 |
使用 ^4.1.x,可能采用 configureProductAnalytics(...) 和/或已移除的 ProductAnalyticsOptions 字段(captureVendorId、resumePreviousSession、pruningLookBackWindow 等) | 4.1.x 到 4.5.1 -- 有重大变更:移除 11 个 ProductAnalyticsOptions 字段;configureProductAnalytics 弃用(将于 2026 年 8 月移除);新增 startSessionReplay / stopSessionReplay 和 sessionReplayAutoStart 选项。 |
重要限制
- 按以下顺序询问 ID:集成前,询问用户 (1) Contentsquare 数据源 ID(重复使用健康检查中的回答)——这是推荐的新客户端配置。(2) 如果用户没有数据源 ID,再询问环境 ID。(3) 只有在用户两者都没有(或明确只想使用 DXA)时,才回退到
StartConfig.dxa()。将回答映射到:StartConfig.withDatasourceId(id:)→StartConfig.withEnvironmentId(id:)→StartConfig.dxa()。不要编造 ID,也不要默认静默回退到 DXA。 - 绝不修改原生代码或原生配置(例外情况除外):默认仅集成 Dart。除非用户明确允许,否则不要编辑
android/、ios/、macos/、windows/、linux/目录下的文件。允许的例外:- iOS 应用内功能配置:将
cs-$(PRODUCT_BUNDLE_IDENTIFIER)URL scheme 添加到ios/Runner/Info.plist,并将 deeplink 处理程序添加到AppDelegate.swift(参见 iOS 应用内功能配置部分)。 - v3.x → v4.x 迁移清理:从
AndroidManifest.xml中删除旧版com.contentsquare.android.autostartmeta tag,从Info.plist中删除CSDisableAutostartkey,并将 SwiftContentsquare.handle(重命名为CSQ.handle((参见 references/migration.md)。 对于这些范围之外的任何原生代码更改,请停止并询问用户,不要编辑。
- iOS 应用内功能配置:将
- 始终配置 iOS 应用内功能:每次新集成都应用 iOS 配置(URL scheme +
AppDelegate.swift中的CSQ.handle(url:))。完整示例请参见 iOS 应用内功能配置部分和 references/ios-in-app-features.md。 - 检测导航包和组件:扫描
pubspec.yaml和代码。auto_route→ 安装csq_navigator_auto_route_observer,并在_appRouter.config(navigatorObservers: ...)中使用CSQNavigatorAutoRouteObserver;go_router→ 在GoRouter(observers: [...])中使用CSQNavigatorObserver(不要用于MaterialApp.router);两者都没有 → 在MaterialApp(navigatorObservers: [...])中使用CSQNavigatorObserver。此外,PageView和TabBar组件不会推送路由——需要在onPageChanged/TabController.addListener中手动调用trackScreenview。 - 扫描 WebView:集成期间,搜索代码库中是否使用了 WebView(
webview_flutter、flutter_inappwebview、WebViewWidget、InAppWebView)。WebView 不会被自动跟踪——每个 WebView 都必须使用CSQWebViewWrapper和相应的 delegate 进行封装。不要跳过此步骤。 - 先调用
start():其他所有 CSQ 方法都要求先调用start()。 - 使用 CSQ,而不是 Contentsquare:
Contentsquare类已弃用。始终使用CSQ()。 configureProductAnalytics已弃用(将于 2026 年 8 月移除)。改用CSQ().start(startConfig: StartConfig.withEnvironmentId(...))。绝不要同时使用这两者——已弃用的 API 优先级更高,会静默覆盖start(startConfig: ...)。- 优先使用
AnalyticsOptions,而不是ProductAnalyticsOptions:后者是为保持向后兼容而保留的typedef。新代码中使用AnalyticsOptions;它现在也适用于 DXA。 - 平台支持:仅支持 Android 和 iOS。Web / 桌面平台会返回空操作实现。
- Flutter 版本:要求 Flutter >= 3.27.0、Dart >= 3.6.0。
- 属性类型:事件 / 用户属性仅接受
String、num、bool。 - DynamicVar 限制:键最长 49 个字符(断言
< 50),字符串值最长 255 个字符(断言< 256),整数值范围为0..2^32-1。 - userIdentifier:建议
identify()和sendUserIdentifier()的值最长为 100 个字符。 - 隐私:绝不自动选择加入。始终实现同意流程。
- PII:绝不要在屏幕名称、事件名称或属性中传递电子邮件、密码或真实姓名。
- 环境 ID:绝不要硬编码——使用配置或环境变量。
- iOS:集成前请查看 iOS 兼容性文档。
参考资料
- 迁移指南(旧版 v3 → v4 和 4.1.x → 4.5.1):references/migration.md
- 完整的方法签名和参数详情:references/api-reference.md
- Session Replay 深入介绍(遮罩、按需 SR、已知限制):references/session-replay.md
- iOS 应用内功能设置(URL scheme、深度链接处理、调试):references/ios-in-app-features.md
- 屏幕跟踪设置(GoRouter、AutoRoute、PageView、TabBar、排除模态页面、命名指南):references/screen-tracking.md
- 常见模式(替代初始化方式、事务、用户同意、事件、GoRouter pageBuilder):references/common-patterns.md
- Flutter 官方文档