mcpField
C
contentsquare-flutter-sdk

contentsquare-flutter-sdk

github.com/contentsquare开发239 次安装1 周前更新
代码仓库

关于 contentsquare-flutter-sdk

供 AI Agent 在客户端应用中集成或升级 Contentsquare Flutter SDK 的技能,涵盖项目健康检查、SDK 配置、分析埋点和迁移指引。

主要功能

  1. 01项目配置健康检查
  2. 02Flutter SDK 安装与设置
  3. 03屏幕和 WebView 跟踪指引
  4. 04分析与回放 API 指引
  5. 05SDK 版本迁移指引

适用场景

  1. 01在 Flutter 应用中集成 Contentsquare
  2. 02升级现有 Contentsquare SDK
  3. 03排查项目配置与跟踪问题

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/contentsquare/agents --skill contentsquare-flutter-sdk

安装后在 Claude Code 中输入/contentsquare-flutter-sdk确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
api-reference.md
common-patterns.md
ios-in-app-features.md
migration.md
screen-tracking.md
session-replay.md

详细介绍

Contentsquare Flutter SDK 集成

此技能可帮助 AI Agent 在客户端应用中集成或升级 Contentsquare Flutter SDK。

必须先执行 -- Contentsquare 项目健康检查

在对话中开展任何 Contentsquare 相关工作之前——包括集成、调试、配置问题和代码更改——都要在每次对话中恰好执行一次此健康检查。不得跳过,也不得推迟到任务后续阶段。

  1. 先告知用户。 告诉用户你即将进行的操作,例如:

    “开始之前,我会快速检查一下你的 Contentsquare 项目:我会询问你的数据源 ID(如果没有,则读取应用的包 ID),调用 Contentsquare 健康检查端点,并向你展示当前项目配置。然后我们再继续。”

  2. 先询问用户的 Contentsquare 数据源 ID。 例如:“你有 Contentsquare 数据源 ID 吗?可能有一个或多个,例如 Android 和 iOS 各一个。如果有,请告诉我每个 ID 对应的平台。” 只能使用用户提供的 ID,绝不能编造 ID。

    • 用户提供了一个或多个数据源 ID → 仅按数据源 ID 检查(v3)。跳过第 3 步。
    • 用户只有环境 ID → 仅按包 ID 检查(v2):环境 ID 不是数据源 ID,在 v3 流程中永远无法使用。
    • 用户没有、不知道或跳过此问题 → 仅按包 ID 检查(v2)。
  3. 解析包 ID(仅在没有数据源 ID 时)——Flutter 应用有两个包 ID,而且它们经常是不同的字符串。 分别解析每个包 ID;绝不要假设它们相同。

    平台读取位置
    Androidandroid/app/build.gradle(.kts) 中的 applicationId(如果没有,则使用 namespace,或 AndroidManifest.xml 中的 package)
    iOSios/Runner.xcodeproj/project.pbxproj 中的 PRODUCT_BUNDLE_IDENTIFIER(或 ios/Runner/Info.plist 中的 CFBundleIdentifier),解析其中任何 $(...) 变量
  4. 调用端点——只使用一个版本,绝不能同时调用两个版本。 平台段必须是字面值 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,请询问用户要检查哪个平台,而不要猜测。

  5. 简要报告每次返回 200 的调用所对应的以下值:

    报告JSON 路径
    项目 IDcs_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 项目。如果响应不同,请明确指出。

  6. 然后继续处理用户的实际请求。

失败处理。 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 以及原生代码清理。升级前请阅读从旧版 Contentsquare API 迁移到 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 部分)。

推荐的引导流程:

  1. 询问用户:“您有 Contentsquare 数据源 ID 吗?”(如果用户已在健康检查期间回答过,则跳过此问题)。如果有,请使用 StartConfig.withDatasourceId(id: ...)。
  2. 如果没有,询问:“您有环境 ID 吗?” 如果有,请使用 StartConfig.withEnvironmentId(id: ...)。
  3. 只有在两者都不可用(或用户明确希望仅使用 DXA)时,才回退到 StartConfig.dxa()。
  4. 询问:“您的 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
APIPurpose
debug.setLogLevel(LogLevel)Set log level (info, verbose, etc.)
metadataAccess session metadata. metadata.onChange(handler) to listen.
AnalyticsOptions(由所有 StartConfig 变体共用)

所有字段均可为空(null = 原生默认行为)。

字段类型平台用途
enableInteractionsAutocapturebool?两者启用 Flutter 交互自动捕获(PA)
disablePageviewAutocapturebool?两者禁用原生页面浏览自动捕获
enablePushNotificationAutocapturebool?两者捕获推送通知事件
enablePushNotificationTitleAutocapturebool?两者捕获推送通知标题
enablePushNotificationBodyAutocapturebool?两者捕获推送通知正文
baseUrlUri?两者自定义 API 端点。Product Analytics 欧盟托管环境必填:设置为 Uri.parse('https://mh.ba.contentsquare.net')。也用于本地部署/自定义端点。
uploadIntervalDuration?两者事件上传频率
sessionReplayAutoStartbool?两者如果为 false,SR 不会在 SDK 启动时开始——请使用 startSessionReplay()
disablePageviewTitleAutocapturebool?仅 iOS禁用 iOS 页面标题自动捕获
disableInteractionAutocapturebool?仅 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 字段
字段屏蔽内容
maskTextsText、RichText
maskTextFieldsTextField、TextFormField
maskImagesImage 组件
maskSvgImagesSVG 渲染的图片
maskChartsfl_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 通道桥接,以便在原生应用和网页内容之间进行会话拼接。

前提条件:

  1. 必须在 WebView 中启用 JavaScript
  2. 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 配置:

  1. 添加 URL scheme 到 ios/Runner/Info.plist:cs-$(PRODUCT_BUNDLE_IDENTIFIER)
  2. 在 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.autostart meta tag,从 Info.plist 中删除 CSDisableAutostart key,并将 Swift Contentsquare.handle( 重命名为 CSQ.handle((参见 references/migration.md)。 对于这些范围之外的任何原生代码更改,请停止并询问用户,不要编辑。
  • 始终配置 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 兼容性文档。

参考资料

评论

支持 Markdown