ae-migrate-tracking-code
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chineseae-migrate-tracking-code
ae-migrate-tracking-code
Conversation language: This skill document is in English, but all output to the user MUST be in the user's input language. English input → English reply; Chinese input → Chinese reply; Japanese input → Japanese reply. If uncertain, default to English. This applies to all output: section titles, phase names, prompts, code comments, etc. ⚠️ CRITICAL: Many provider adapter docs contain Chinese glossary notes. When reading them to answer an English/Japanese user, translate headings and comments to the user's language. Do NOT copy Chinese text verbatim from this document into English/Japanese replies.
对话语言:本技能文档为英文,但所有输出给用户的回复必须使用用户的输入语言。 英文输入 → 英文回复;中文输入 → 中文回复;日文输入 → 日文回复。 如果不确定,默认使用英文。 这适用于所有输出:章节标题、阶段名称、提示、代码注释等。 ⚠️ 关键:许多提供商适配器文档包含中文术语注释。在阅读这些文档以回答英文/日文用户时,请将标题和注释翻译成用户的语言。 不要将本文档中的中文文本逐字复制到英文/日文回复中。
Terminology Glossary
术语表 Glossary
| 中文 | English | Notes |
|---|---|---|
| 埋点迁移 | Tracking Migration | Convert existing third-party SDK tracking calls to AE SDK |
| 源 SDK | Source SDK / Provider | The third-party SDK already in the project (Firebase, Amplitude, ...) |
| 调用点 | Call Site | A source-SDK invocation ( |
| 归一化中间表示 | IR (Intermediate Representation) | Provider-neutral dump of extracted call sites |
| 映射 | Mapping | Source event/property → AE event/property translation |
| 切换 | Switch | Replace source calls with AE |
| 双写 / 新增 | Add / Dual-write | Keep source SDK and add AE |
| 依赖标识 | Dependency Identifier | Package/module name used to remove the source SDK in switch mode |
| 自动采集事件 | Auto-track Event | Events the source SDK collects automatically (e.g. |
| 公共属性 | Super Property | Property attached to every event automatically. ⚠️ The correct Chinese AE term is "公共属性" or "公共事件属性". Never translate "Super Property" as "超级属性" — that is NOT a valid AE term. |
| 用户属性 | User Property | Property set on the user profile |
| 用户体系 | User Identity System | distinct_id / account_id strategy in AE |
| 中文 | English | 注释 |
|---|---|---|
| 埋点迁移 | Tracking Migration | 将现有第三方SDK埋点调用转换为AE SDK |
| 源 SDK | Source SDK / Provider | 项目中已有的第三方SDK(Firebase、Amplitude等) |
| 调用点 | Call Site | 源SDK调用( |
| 归一化中间表示 | IR (Intermediate Representation) | 提取的调用点的与提供商无关的转储 |
| 映射 | Mapping | 源事件/属性 → AE事件/属性转换 |
| 切换 | Switch | 用AE |
| 双写 / 新增 | Add / Dual-write | 保留源SDK并在旁边添加AE |
| 依赖标识 | Dependency Identifier | 在切换模式下用于移除源SDK的包/模块名称 |
| 自动采集事件 | Auto-track Event | 源SDK自动收集的事件(例如 |
| 公共属性 | Super Property | 自动附加到每个事件的属性。⚠️ AE中正确的中文术语是“公共属性”或“公共事件属性”。切勿将“Super Property”翻译为“超级属性”——这不是有效的AE术语。 |
| 用户属性 | User Property | 在用户档案上设置的属性 |
| 用户体系 | User Identity System | AE中的distinct_id / account_id策略 |
When to Trigger
触发时机 When to Trigger
Trigger when user says: "migrate Firebase tracking to AE / replace Amplitude with ThinkingAI / my project already has Firebase/Amplitude tracking, switch it to AE SDK / add AE tracking alongside existing analytics" etc. — e.g. 把当前工程里的 xx SDK 切换到数数、把已有埋点用数数实现一遍、用数数替换 xx SDK、集成数数并参考已有的 xx SDK 埋点.
The target AE SDK may be referred to by any of: 数数 / 数数 SDK / ThinkingAI / ThinkingAI SDK / Agentic Engine / Agentic Engine SDK / AE / AE SDK — they are one SDK. The trigger signal is "an existing third-party source SDK + 迁移/切换/替换/实现一遍", or "集成/接入数数 并参考已有的 xx SDK 埋点". A bare 接入数数 SDK / 加数数埋点 with no source SDK is greenfield — it belongs to , not this skill.
ae-generate-tracking-codeScope: this skill is codebase-only — it scans existing third-party tracking calls (Phase 0/1). If there is no source code with third-party tracking (only product docs / descriptions), do NOT use this skill; route to + instead. Historical data import into AE is offline data-migration work, out of scope — this skill only switches the live client/server SDK, preserving user IDs and event/property names so new data joins the imported data.
ae-generate-tracking-planae-generate-tracking-codeThis skill orchestrates the migration end-to-end but does not duplicate the two existing skills:
- Plan generation/upload → hand off to (codebase path).
ae-generate-tracking-plan - AE SDK code insertion → hand off to (insert mode), with insertion sites supplied from the migration mapping instead of grep-discovered business triggers.
ae-generate-tracking-code
当用户说以下内容时触发:“把 Firebase 埋点迁移到 AE / 用 ThinkingAI 替换 Amplitude / 我的项目已有 Firebase/Amplitude 埋点,切换到 AE SDK / 在现有分析旁添加 AE 埋点”等——例如:把当前工程里的 xx SDK 切换到数数、把已有埋点用数数实现一遍、用数数替换 xx SDK、集成数数并参考已有的 xx SDK 埋点。
目标 AE SDK 可能被称为:数数 / 数数 SDK / ThinkingAI / ThinkingAI SDK / Agentic Engine / Agentic Engine SDK / AE / AE SDK —— 它们是同一个 SDK。触发信号是“已存在的第三方源 SDK + 迁移/切换/替换/实现一遍”,或“集成/接入数数 并参考已有的 xx SDK 埋点”。如果仅仅是接入数数 SDK / 加数数埋点而没有源 SDK,则属于全新接入(greenfield)——这是 的职责,而非本技能。
ae-generate-tracking-code范围:本技能仅针对代码库——它扫描现有的第三方埋点调用(阶段0/1)。如果不存在带有第三方埋点的源代码(只有产品文档/描述),请勿使用本技能;请改用 + 。将历史数据导入 AE 属于离线数据迁移工作,不在范围内——本技能仅切换线上客户端/服务端 SDK,保留用户ID和事件/属性名称,使新数据能汇入已导入的数据。
ae-generate-tracking-planae-generate-tracking-code本技能端到端编排迁移过程,但不重复现有两个技能的工作:
- 计划生成/上传 → 交给 (代码库路径)。
ae-generate-tracking-plan - AE SDK 代码插入 → 交给 (插入模式),插入位置来自迁移映射,而非通过 grep 发现的业务触发点。
ae-generate-tracking-code
Provider Registry (extensible)
提供商注册表 Provider Registry(可扩展)
The core is provider-agnostic. Each third-party platform is one adapter file. To support a new provider, add one adapter under and one row below — do not modify this SKILL.md.
references/providers/| Provider | Adapter | Platforms covered | Detect pattern (summary) |
|---|---|---|---|
| Firebase Analytics | | Web v8/v9, Android, iOS, Flutter, React Native, Unity, C++ | |
| Amplitude | | Web legacy ( | |
| Sensors Data (神策) | | Web, Android, iOS, Harmony, macOS/tvOS, C++, React Native, Flutter, Unity, Unreal, Cocos2d-x, mini-programs (WeChat/other), QuickApp, APICloud, uni-app, Weex, Egret, LayaAir + server SDKs (Java/Python/Go/Node/PHP/Ruby/C/.NET/Lua) | |
| Mixpanel | | JavaScript, Node, Python, Go, Java, Ruby, PHP, Android, iOS, Swift, React Native, Flutter, Unity | |
| Google Analytics 4 | | Web (gtag.js / dataLayer), Measurement Protocol (server) | |
Adapter contract (required fields per adapter) is defined in .
references/providers/README.mdSupported scope: only the providers/platforms listed above (and the per-platform tables in each adapter's Recognition section) are supported. Anything not listed is out of scope and not supported by this skill — do not fabricate a mapping for unlisted platforms.
核心与提供商无关。每个第三方平台对应一个适配器文件。要支持新的提供商,请在 下添加一个适配器,并在下面添加一行——不要修改本 SKILL.md。
references/providers/| Provider | Adapter | 覆盖平台 | 检测模式(摘要) |
|---|---|---|---|
| Firebase Analytics | | Web v8/v9, Android, iOS, Flutter, React Native, Unity, C++ | |
| Amplitude | | Web legacy ( | |
| Sensors Data (神策) | | Web, Android, iOS, Harmony, macOS/tvOS, C++, React Native, Flutter, Unity, Unreal, Cocos2d-x, mini-programs (WeChat/other), QuickApp, APICloud, uni-app, Weex, Egret, LayaAir + server SDKs (Java/Python/Go/Node/PHP/Ruby/C/.NET/Lua) | |
| Mixpanel | | JavaScript, Node, Python, Go, Java, Ruby, PHP, Android, iOS, Swift, React Native, Flutter, Unity | |
| Google Analytics 4 | | Web (gtag.js / dataLayer), Measurement Protocol (server) | |
适配器合约(每个适配器必填字段)定义于 。
references/providers/README.md支持范围:仅支持上述列出的提供商/平台(以及每个适配器 Recognition 部分中的分平台表格)。未列出的内容不在范围内,本技能不支持——不要为未列出的平台编造映射。
Phase 0 — Detect source SDK and version
阶段 0 — 检测源 SDK 和版本
- Locate the project and its package/dependency manifest (,
package.json,build.gradle,Podfile,pubspec.yaml, ...) plus source imports.*.csproj - Match against the registry above. Read the matching adapter's Recognition section to confirm the provider and pin the version variant:
- Firebase: v8 namespaced vs v9 modular (web), plus Android/iOS/Flutter native forms.
- Amplitude: legacy () vs SDK 2.x (
getInstance().logEvent/amplitude.track).@amplitude/analytics-browser
- If multiple providers are present, list them and ask which to migrate first (one provider per run keeps mapping clean). Exception — GA4 and Firebase Analytics are the same data stream: GA4 is Firebase's web layer (one measurement ID is both a GA4 property and a Firebase project). If and
gtag(...)coexist in one project, they are not two providers — merge them into a single migration run: one scan, onelogEvent(...)/draft.json, one dedup pass over the shared event / property / user-id names. Never produce two drafts for one Google data stream.mapping.json - If no registry match but tracking code exists → show the found calls, ask the user for the provider name, and (per ) collect a minimal adapter from the user-provided docs/snippet before continuing.
references/providers/README.md
- 定位项目及其包/依赖清单(、
package.json、build.gradle、Podfile、pubspec.yaml等)以及源代码导入。*.csproj - 与上述注册表匹配。阅读匹配适配器的 Recognition 部分以确认提供商并确定版本变体:
- Firebase:v8 命名空间风格 vs v9 模块化风格(Web),以及 Android/iOS/Flutter 原生形式。
- Amplitude:旧版()vs SDK 2.x(
getInstance().logEvent/amplitude.track)。@amplitude/analytics-browser
- 如果存在多个提供商,列出它们并询问先迁移哪个(每次运行处理一个提供商可以保持映射清晰)。例外 — GA4 和 Firebase Analytics 是同一数据流:GA4 是 Firebase 的 Web 层(一个测量 ID 既是 GA4 资产也是 Firebase 项目)。如果 和
gtag(...)在同一个项目中共存,它们不是两个提供商——应将它们合并为一次迁移运行:一次扫描、一个logEvent(...)/draft.json、对共享的事件/属性/用户ID名称执行一次去重。切勿为同一条 Google 数据流生成两份草稿。mapping.json - 如果注册表没有匹配但存在埋点代码 → 展示找到的调用,向用户询问提供商名称,并根据 从用户提供的文档/片段中收集一个最小适配器,然后继续。
references/providers/README.md
Phase 1 — Extract call sites into IR
阶段 1 — 将调用点提取到 IR
Scan the project for four call categories, using the adapter's Recognition patterns:
- Event calls: /
logEvent(...)and their params/properties.track(...) - Identity calls: /
setUserId(...)/identify(...).login(...) - User property calls: /
setUserProperty(...)/setUserProperties(...)operations.Identify - Super property calls (common event properties): /
register(...)(Mixpanel, Sensors Data) /registerSuperProperties(...)(Firebase). Record them assetDefaultEventParameters(...)with the fullkind: super_propertymap — do not misread them as user properties (seeprops§6). Amplitude and GA4 have no such API.mapping-framework.md
Record each site as , call kind, event/param values (literals, or variable names to resolve by reading the surrounding code). Write the normalized dump to following .
file:line.ae-cli/migration/scan.jsonreferences/ir.mdWrapper-layer resolution (reverse call-graph tracing) — real projects almost never call the source SDK directly at every business event; they wrap it in an analytics helper ( → ). A naive grep sees only the wrapper's single SDK call (event name = parameter → would be ) and misses every real business event. So when an SDK call's event name is a function parameter (a runtime variable flowing from an enclosing function's argument), do not immediately record :
trackEvent(name, props)mixpanel.track(name, props)resolved:falseresolved:false- Identify the enclosing function — it is an analytics wrapper only when
F's sole role is forwarding that parameter into the SDK call. If the event name comes from local logic/expressions rather than a parameter, it is NOT a wrapper — record the site asFas usual.resolved:false - Grep for every caller of . Resolve each caller with a static event name into a normal call site:
Fis inferred from the SDK callkinddelegates to (event / identity / user_property),Ffrom the caller's literal or constant argument,event_name= the caller's invocation line,source_call= the caller's file, andfile=via_wrapper's name.F - Callers with a dynamic event name stay . If no callers are found (an exported wrapper used externally, or dynamic dispatch), fall back to recording the wrapper's own SDK call as a single
resolved:falsesite.resolved:false - Record itself in scan.json's top-level
Farray (seewrappers) — it is the pivot for tracing, not a migration target.references/ir.md
Auto-track note: source SDK auto-collected events (e.g. Firebase , , ) are not call sites. Handle them per the adapter's Auto-track decision table in Phase 2, not here.
session_startfirst_openscreen_view使用适配器的 Recognition 模式扫描项目中四种调用类别:
- 事件调用:/
logEvent(...)及其参数/属性。track(...) - 身份调用:/
setUserId(...)/identify(...)。login(...) - 用户属性调用:/
setUserProperty(...)/setUserProperties(...)操作。Identify - **公共属性(Super Property)**调用(公共事件属性):/
register(...)(Mixpanel、Sensors Data)/registerSuperProperties(...)(Firebase)。将它们记录为setDefaultEventParameters(...),包含完整的kind: super_property映射——不要误读为用户属性(参见props§6)。Amplitude 和 GA4 没有此类 API。mapping-framework.md
将每个调用点记录为 、调用类型、事件/参数值(字面量,或通过阅读周围代码来解析的变量名)。按照 将归一化转储写入 。
file:linereferences/ir.md.ae-cli/migration/scan.json包装层解析(反向调用图追踪) — 实际项目几乎不会在每个业务事件处直接调用源 SDK;它们通常将其包装在一个分析辅助函数中( → )。简单的 grep 只会看到包装器的单个 SDK 调用(事件名 = 参数 → 会被标记为 ),从而漏掉所有真实的业务事件。因此,当 SDK 调用的事件名是一个函数参数(即从外层函数参数流入的运行时变量)时,不要立即记录 :
trackEvent(name, props)mixpanel.track(name, props)resolved:falseresolved:false- 识别外层函数 —— 仅当
F的职责纯粹是将该参数转发给 SDK 调用时,它才是一个分析包装器。如果事件名来自本地逻辑/表达式而非参数,则它不是包装器——照常记录为F。resolved:false - 搜索 的所有调用者。将每个具有静态事件名的调用者解析为普通调用点:
F从kind委托的 SDK 调用推断(event / identity / user_property),F来自调用者的字面量或常量参数,event_name= 调用者的调用行,source_call= 调用者所在文件,file=via_wrapper的名称。F - 具有动态事件名的调用者保持 。如果找不到调用者(例如用于外部导出的包装器,或动态分发),则回退为将包装器自身的 SDK 调用记录为单个
resolved:false调用点。resolved:false - 在 scan.json 的顶层 数组中记录
wrappers本身(参见F)——它是追踪的枢纽,而不是迁移目标。references/ir.md
自动采集说明:源 SDK 自动采集的事件(例如 Firebase 、、)不是调用点。请按照适配器的 Auto-track decision 表格在阶段 2 中处理,而不是这里。
session_startfirst_openscreen_viewPhase 2 — Map to AE (write draft.json + mapping.json)
阶段 2 — 映射到 AE(写入 draft.json + mapping.json)
- Read (generic algorithm) + the provider adapter (differences).
references/mapping-framework.md - For each extracted event call: map to an AE event (snake_case name, or verbatim when forward compatibility is required — §1;
mapping-framework.mdin the user's language), map each param to an AE property with a type, and apply naming constraints from the adapter (reserved prefixes, special characters, length caps).display_name - Apply dedup + promotion rules: same property on 3+ events → common event property (super property); preset properties never become super properties. Explicit super-property call sites (
#/register) also land insetDefaultEventParameters'sdraft.jsonpool — seecommon_event_properties§6.mapping-framework.md - Map identity → AE (account_id_source
login(accountId)); plus visitor-id continuity (user_account/setDistinctId, init-time) when forward compatibility with imported historical data is in scope — seeidentify§4. User property ops → AEmapping-framework.md/user_set/user_setOnce/user_add/user_appendper the adapter's mapping table. Super property calls → AEuser_unset(static common event property), persetSuperProperties({...})§6.mapping-framework.md - Decide each event's (client / server) from where the call site lives (app code → client; backend → server).
platform - Ask the user to confirm the migration mode (see Modes below) and whether historical source-platform data has been (or will be) imported into AE offline — drives forward-compatible naming per §1 and visitor-id continuity per §4. The import itself is offline data-migration work, out of scope; this skill only switches the live SDK — then:
mapping-framework.md- Write (source site → AE event + mode decision, schema in
.ae-cli/migration/mapping.json).references/ir.md - Write in the AE plan schema (same schema
.ae-cli/draft.jsonproduces) so the plan skill can consume it directly.ae-generate-tracking-plan
- Write
Show the mapping summary table and get user before proceeding.
ok- 阅读 (通用算法)+ 提供商适配器(差异)。
references/mapping-framework.md - 对每个提取的事件调用:映射为 AE 事件(snake_case 名称,或在需要向前兼容时原样保留——§1;
mapping-framework.md使用用户的语言),将每个参数映射为带类型的 AE 属性,并应用适配器中的命名约束(保留前缀、特殊字符、长度上限)。display_name - 应用去重和提升规则:同一属性出现在 3 个及以上事件 → 公共事件属性(公共属性);预置的 属性永远不会变成公共属性。显式的公共属性调用点(
#/register)也归入setDefaultEventParameters的draft.json池——参见common_event_properties§6。mapping-framework.md - 将身份映射为 AE (account_id_source
login(accountId));当需要与已导入的历史数据进行向前兼容时,还要处理访客ID连续性(user_account/setDistinctId,初始化时)——参见identify§4。用户属性操作 → 根据适配器的映射表转换为 AEmapping-framework.md/user_set/user_setOnce/user_add/user_append。公共属性调用 → AEuser_unset(静态公共事件属性),参见setSuperProperties({...})§6。mapping-framework.md - 根据调用点所在位置决定每个事件的 (客户端/服务端)(应用代码 → 客户端;后端 → 服务端)。
platform - 请用户确认迁移模式(见下方 Modes)以及历史源平台数据是否已(或将)离线导入 AE——这决定是否需要遵循 §1 的向前兼容命名和 §4 的访客ID连续性。导入本身是离线数据迁移工作,不在范围内;本技能仅切换线上 SDK——然后:
mapping-framework.md- 写入 (源调用点 → AE 事件 + 模式决策,模式见
.ae-cli/migration/mapping.json)。references/ir.md - 以 AE 计划模式写入 (与
.ae-cli/draft.json生成的模式相同),以便计划技能可直接使用。ae-generate-tracking-plan
- 写入
展示映射汇总表,并在用户确认 后再继续。
okPhase 3 — Generate and upload the tracking plan
阶段 3 — 生成并上传埋点计划
Hand off to using the codebase/draft already produced:
ae-generate-tracking-planae-cli tracking plan draft --in .ae-cli/draft.json --out .ae-cli/draft.xlsxae-cli tracking plan validate --in .ae-cli/draft.json --fix- Resolve AE host/login/projectId per the plan skill, then (ask the user before uploading; append vs replace per that skill's conflict detection).
ae-cli tracking plan upload ...
使用已生成的代码库/draft 移交给 :
ae-generate-tracking-planae-cli tracking plan draft --in .ae-cli/draft.json --out .ae-cli/draft.xlsxae-cli tracking plan validate --in .ae-cli/draft.json --fix- 按照计划技能解析 AE host/login/projectId,然后执行 (上传前询问用户;追加还是替换由该技能的冲突检测决定)。
ae-cli tracking plan upload ...
Phase 4 — Insert AE SDK code (switch or add)
阶段 4 — 插入 AE SDK 代码(切换或新增)
Hand off to (insert mode), but insertion sites come from , not from grep business-trigger discovery:
ae-generate-tracking-code.ae-cli/migration/mapping.json- Client/server platform + language are already in meta; resolve APP_ID / SERVER_URL as that skill does.
draft.json - For each mapped AE event, the insertion point is the original call site recorded in mapping.json.
Mode (replace) — high-risk, confirm before deleting:
switch- Before any deletion, explicitly list what will be removed (the source call sites and the source SDK dependency from the adapter's Dependency identifiers) and get the user's confirmation to delete.
- Replace the source /
logEventcall with the AEtrackcall at the same site; remove now-unused source imports.track(...) - Inline event names that came from a module constant: emit the literal snake_case name in the AE call (it must match the
track(...)marker). Before deleting the constant definition, grep the whole project for its name — a module constant is often imported by multiple files, fed to a server-side report, or asserted in tests. Only remove it when the migrated call sites are its sole references (then it is dead code); otherwise keep it. Do not keep a constant that only feeds the migrated call.// @tracking <event_name> - Remove the source SDK dependency using the adapter's Dependency identifiers (e.g. ,
firebase/analytics).@amplitude/analytics-browser - Remove dead wrappers: when every call site resolved through a wrapper is d, the wrapper function is dead code — delete it (and its now-unused source import). If the wrapper's file holds nothing else, remove the file. (
replacemode keeps the wrapper — it still feeds the source SDK — and adds the AE call at each business call site.)add - Convert identity/user-property calls to / user-property calls similarly; super-property calls →
login(...)in place at the original call site (never hoisted — the source'ssetSuperProperties({...})position encodes when the values become available, e.g. after login; seeregister§6).mapping-framework.md
Mode (dual-write):
add- Keep the source call untouched; add the AE call immediately adjacent (before or after, matching surrounding style).
track(...) - Keep the two SDKs independent — in both directions. Dual-write means two independent writes, for every provider / every SDK (Firebase, Amplitude, Sensors Data, Mixpanel, GA4, …), not a source-guarded AE write:
- The AE /
track()/ user-property /login()call must NOT be nested inside the source SDK's availability guard, early-return, or error path — e.g. aftersetSuperProperties(), behindif (!analytics) return, or inside the source'sisSupported(). If the source call sits behind such a guard, lift the AE call out so it runs unconditionally.try/catch - Give each SDK its own around its write: a source-SDK failure (unavailable,
try/catch, or a thrown error) must never suppress the AE write, and an AE failure must never suppress (or crash) the source write.isSupported() === false - The guard must cover the source SDK's full failure surface, not a single exception type. A pre-existing narrow catch (e.g. Python for 400 validation, Java
except ValueError) is not the independence guard — other failures (unconfigured API key →catch (IllegalArgumentException), network/timeout) still escape and crash before the AE write. Broaden the catch to all exceptions, run the AE write, then re-raise the source exception so the original status/error semantics (400/503) are unchanged.RuntimeError - Give each SDK's init its own too, so that one SDK being unloaded or disabled at load time (init throws / module missing) does not take down the other SDK. Both writes must keep working no matter which SDK is unloaded or disabled.
try/catch - This applies to every /
add/add_afterentry in mixed runs too.add_before
- The AE
- Keep the source SDK dependency; only add the AE SDK dependency.
Async call sites — a source call that is ed (React Native / Flutter , some ) returns a Promise, but the AE client / / user-property / calls are synchronous:
awaitawait analytics().logEvent(...)await mixpanel.track(...)track()login()setSuperProperties()- : drop the
switchon the replaced call — awaiting a synchronous AE call is a lint warning and changes nothing. If the source call sat inside aawaitwhosetry/catchhandled the source SDK's Promise rejection (network retry, offline fallback, error reporting), that rejection branch dies with the source SDK: remove the now-deadcatchlogic; if thecatchblock then holds only the AE call, collapse thetryinto the bare AE call (AE sync failures then follow the code skill's Code Style — loud intry/catch). Never wrap the AE call in a made-upswitch/asyncto keep the shapes matching.await - : keep the source call's
addand itsawaitexactly as-is, and place the AE call outside that block, un-try/catched, in its ownawaitper the independence rule above.try/catch
Both modes follow the code skill's insert rules: SDK init from the wiki main doc (never guess imports), git-status pre-check, batched Edit with language-style check, comment prefix.
// @tracking <event_name>User-property / ( = / ): these two are not in the plan's enum (only / / are), so they do not enter — in the draft their is written (placeholder). At code-insertion time, emit the AE SDK call directly per the mapping's ( → , → ), reading the real method signature from the wiki main doc (never guess).
appendunsetae_calluser_appenduser_unsetupdate_typeuser_setuser_setOnceuser_adddraft.jsonupdate_typeuser_setae_calluser_appenduserAppenduser_unsetuserUnset⚠️ mode overrides the code skill's "Do NOT add try/catch" Code Style. That rule is a single-SDK rule (greenfield insert / after cut-over): with one SDK a loud failure is the point, so init/track failures must surface rather than be swallowed. Dual-write is the opposite — the "each SDK its own " rule above applies to the generated AE code too:
addswitchtry/catch- The AE init must be guarded the same way (its own / availability check), so an AE-SDK load failure never throws at load time and never takes down the source SDK.
try/catch - Never emit a load-time SDK capture that becomes a permanently-reference and throws on every call (e.g.
undefinedin a wrapper) — a missing AE SDK must be a per-call no-op, not a crash of business logic or the source write.var ta = window.TA; - mode does NOT get this override: after cut-over AE is the only SDK, so it follows the code skill's Code Style as-is (failures stay loud).
switch
移交给 (插入模式),但插入位置来自 ,而不是通过 grep 发现业务触发点:
ae-generate-tracking-code.ae-cli/migration/mapping.json- 客户端/服务端平台和语言已在 的元数据中;像该技能那样解析 APP_ID / SERVER_URL。
draft.json - 对于每个映射的 AE 事件,插入点是 mapping.json 中记录的原始调用点。
switch- 在删除任何内容之前,明确列出将被移除的内容(源调用点以及来自适配器 Dependency identifiers 的源 SDK 依赖),并取得用户的删除确认。
- 在同一位置将源 /
logEvent调用替换为 AEtrack调用;移除现在不再使用的源导入。track(...) - 来自模块常量的事件名内联化:在 AE 调用中发出字面量 snake_case 名称(必须与
track(...)标记匹配)。在删除常量定义之前,先在整个项目中搜索其名称——模块常量经常被多个文件导入、用于服务端报表或在测试中断言。仅当迁移后的调用点是其唯一引用时(即死代码)才移除它;否则保留。不要保留仅供被迁移调用使用的常量。// @tracking <event_name> - 使用适配器的 Dependency identifiers 移除源 SDK 依赖(例如 、
firebase/analytics)。@amplitude/analytics-browser - 移除死掉的包装器:当所有通过包装器解析的调用点都已被 后,该包装器函数即为死代码——删除它(以及其不再使用的源导入)。如果包装器所在文件没有其他内容,则删除该文件。(
replace模式保留包装器——它仍然服务于源 SDK——并在每个业务调用点添加 AE 调用。)add - 类似地将身份/用户属性调用转换为 / 用户属性调用;公共属性调用 → 在原始调用点原位使用
login(...)(绝不提升——源的setSuperProperties({...})位置编码了值何时可用,例如登录后;参见register§6)。mapping-framework.md
add- 保持源调用不变;在紧邻位置添加 AE 调用(之前或之后,匹配周围风格)。
track(...) - 保持两个 SDK 独立——双向独立。 双写意味着两次独立写入,对于每个提供商 / 每个 SDK(Firebase、Amplitude、Sensors Data、Mixpanel、GA4 等),而不是受源 SDK 保护的 AE 写入:
- AE 的 /
track()/ 用户属性 /login()调用不得嵌套在源 SDK 的可用性守卫、提前返回或错误路径中——例如在setSuperProperties()之后、if (!analytics) return后面,或源isSupported()内部。如果源调用位于此类守卫之后,请将 AE 调用提升出来,使其无条件执行。try/catch - 为每个 SDK 各自的写入提供各自的 :源 SDK 失败(不可用、
try/catch或抛出错误)绝不能抑制 AE 写入,AE 失败也绝不能抑制(或导致崩溃)源写入。isSupported() === false - 守卫必须覆盖源 SDK 的完整失败面,而不是单一异常类型。预先存在的窄 catch(例如 Python 处理 400 校验、Java
except ValueError)不是独立性守卫——其他失败(未配置 API key →catch (IllegalArgumentException)、网络/超时)仍然会在 AE 写入之前逃逸并导致崩溃。应将 catch 扩大到所有异常,执行 AE 写入,然后重新抛出源异常,以保持原始状态/错误语义(400/503)不变。RuntimeError - 也要为每个 SDK 的初始化提供各自的 ,以便在加载时某个 SDK 被卸载或禁用(初始化抛出/模块缺失)不会拖垮另一个 SDK。无论哪个 SDK 被卸载或禁用,两个写入都必须继续工作。
try/catch - 这同样适用于混合运行中的每个 /
add/add_after条目。add_before
- AE 的
- 保留源 SDK 依赖;仅添加 AE SDK 依赖。
异步调用点 — 被 的源调用(React Native / Flutter 中的 、某些 )返回 Promise,但 AE 客户端的 / / 用户属性 / 调用是同步的:
awaitawait analytics().logEvent(...)await mixpanel.track(...)track()login()setSuperProperties()- :在替换后的调用上移除
switch——await 一个同步的 AE 调用是 lint 警告且没有意义。如果源调用位于await中,且其try/catch处理了源 SDK 的 Promise 拒绝(网络重试、离线回退、错误上报),该拒绝分支会随源 SDK 一起消失:删除现已死掉的catch逻辑;如果catch块随后只包含 AE 调用,则将try简化为裸 AE 调用(AE 同步失败随后遵循代码技能的 Code Style——在try/catch中响亮失败)。切勿为了保持形状匹配而用虚构的switch/async包装 AE 调用。await - :保持源调用的
add及其await完全不变,并将 AE 调用放在该块之外,不try/catch,按照上述独立性规则放在自己的await中。try/catch
两种模式都遵循代码技能的插入规则:SDK 初始化来自 wiki 主文档(绝不猜测导入)、git-status 预先检查、带语言风格检查的批量 Edit、 注释前缀。
// @tracking <event_name>用户属性 / ( = / ):这两个不在计划的 枚举中(只有 / / 在),因此它们不进 —— 在草稿中它们的 写成 (占位符)。在代码插入时,根据映射的 直接发出 AE SDK 调用( → , → ),从 wiki 主文档读取真实方法签名(绝不猜测)。
appendunsetae_calluser_appenduser_unsetupdate_typeuser_setuser_setOnceuser_adddraft.jsonupdate_typeuser_setae_calluser_appenduserAppenduser_unsetuserUnset⚠️ 模式覆盖代码技能的“不要添加 try/catch” Code Style。 该规则是单 SDK 规则(全新接入 / 切换后的 ):只有一个 SDK 时,响亮失败是重点,因此初始化/跟踪失败必须显现而不是被吞掉。双写则相反——上述“每个 SDK 各自 ”规则也适用于生成的 AE 代码:
addswitchtry/catch- AE 初始化必须以同样方式受到保护(其自己的 / 可用性检查),这样 AE-SDK 加载失败绝不会在加载时抛出,也绝不会拖垮源 SDK。
try/catch - 切勿发出加载时的 SDK 捕获,使其成为永久 的引用并在每次调用时抛出(例如在包装器中
undefined)——缺失的 AE SDK 必须在每次调用时成为 no-op,而不是导致业务逻辑或源写入崩溃。var ta = window.TA; - 模式不获得此覆盖:切换完成后 AE 是唯一的 SDK,因此它按原样遵循代码技能的 Code Style(失败保持响亮)。
switch
Phase 5 — Verify
阶段 5 — 验证
Reuse the code skill's validation flow:
- / confirm active host; debug device add/select.
ae-cli auth status - Trigger the migrated events and query .
ae-cli tracking debug-data list - In mode, verify AE data alongside the still-running source SDK; in
addmode, confirm the source SDK is fully removed and AE data flows.switch
复用代码技能的验证流程:
- / 确认活跃主机;添加/选择调试设备。
ae-cli auth status - 触发迁移后的事件并查询 。
ae-cli tracking debug-data list - 在 模式下,验证 AE 数据与仍在运行的源 SDK 并存;在
add模式下,确认源 SDK 已被完全移除且 AE 数据正常流动。switch
Modes
模式 Modes
| Mode | Source SDK kept? | AE call placement | Dependency change |
|---|---|---|---|
| removed | replaces source call | remove source dep, add AE dep |
| kept | added alongside | add AE dep only |
Ask the user once in Phase 2 which mode to use. Default to (dual-write): present as the recommended option in the confirmation prompt. Treat as the non-default, destructive choice — offer it only when the user has explicitly expressed wanting a full cut-over, and never mark it recommended.
addaddswitchStaged / mixed runs: is the run-level default, but each mapping entry carries its own ( vs /), and the per-entry is authoritative. A run may still keep selected entries as for a staged roll-out (e.g. cut over identity + sign-up now, keep dual-writing while its data is validated). In that case: replaced files drop the source SDK, dual-write files keep it, and the source SDK dependency is removed only on a full cut-over (every entry ). See §mapping.json and §8.
modeactionreplaceadd_afteradd_beforeactionswitchadd_afterpurchasereplacereferences/ir.mdmapping-framework.md⚠️is destructive (high-risk): it deletes source tracking calls, their imports, and the source SDK dependency. Never delete old code by default. Before deleting anything, explicitly tell the user what will be removed (call sites + dependencies) and get their confirmation; re-confirm again at Phase 4 immediately before deletion, even ifswitchwas already chosen in Phase 2.switch
| 模式 | 是否保留源 SDK? | AE 调用位置 | 依赖变更 |
|---|---|---|---|
| 移除 | 替换源调用 | 移除源依赖,添加 AE 依赖 |
| 保留 | 在旁边添加 | 仅添加 AE 依赖 |
在阶段 2 向用户询问一次使用哪种模式。默认使用 (双写):在确认提示中将 作为推荐选项。 将 视为非默认、破坏性选择——仅在用户明确表达希望完全切换时才提供,且绝不标记为推荐。
addaddswitch分阶段 / 混合运行: 是运行级默认值,但每个映射条目携带自己的 ( vs /),并且逐条目的 具有权威性。 运行中仍可将部分条目保留为 以进行分阶段发布(例如,先切换身份+注册,在验证 数据的同时保持双写)。在这种情况下:被替换的文件移除源 SDK,双写文件保留它,并且源 SDK 依赖仅在完全切换(每个条目都是 )时移除。参见 §mapping.json 和 §8。
modeactionreplaceadd_afteradd_beforeactionswitchadd_afterpurchasereplacereferences/ir.mdmapping-framework.md⚠️是破坏性(高风险):它会删除源埋点调用、其导入和源 SDK 依赖。切勿默认删除旧代码。在删除任何内容之前,明确告知用户将移除的内容(调用点 + 依赖)并获得其确认;即使已在阶段 2 选择了switch,也要在阶段 4 删除前再次确认。switch
Prohibitions
禁止事项 Prohibitions
- Guessing AE SDK imports/package names — always read the wiki main doc via (
ae-generate-tracking-code).references/sdk-index.md - Modifying event/property names away from the AE plan (, registered names).
snake_case - Migrating source SDK auto-track events as manual calls — map them to AE auto-track switches or drop them per the adapter.
track() - Nesting the AE /
track()/ user-property calls inside the source SDK's availability guard, early-return, orlogin()intry/catchmode, or leaving either SDK's init unguarded, or guarding the source write with a narrow exception-type catch that still lets a source failure crash before the AE write — for every provider, dual-write must stay two independent writes (each SDK its ownadd, init included, covering the full failure surface), so one SDK failing or being unloaded never takes down the other.try/catch - Skipping the mapping summary confirmation in Phase 2.
- Writing /
user_appendintouser_unset'sdraft.json(the plan enum isupdate_type/user_set/user_setOnceonly) — append/unset stay inuser_addmapping.jsonand are emitted directly at Phase 4.ae_call - Translating "Super Property" as "超级属性" in any user-facing output.
- Writing source or AE code before the git-status pre-check (insert mode).
- Editing the provider adapters to add provider-specific logic into the core — new providers are new adapter files only.
- Deleting source tracking code or removing the source SDK dependency (mode) without explicitly warning the user and getting their confirmation immediately before deletion.
switch
- 猜测 AE SDK 导入/包名称——始终通过 (
ae-generate-tracking-code)阅读 wiki 主文档。references/sdk-index.md - 修改偏离 AE 计划的事件/属性名称(、已注册名称)。
snake_case - 将源 SDK 自动追踪事件迁移为手动 调用——应根据适配器将它们映射为 AE 自动追踪开关或丢弃它们。
track() - 在 模式下,将 AE 的
add/track()/ 用户属性调用嵌套在源 SDK 的可用性守卫、提前返回或login()中,或让任一 SDK 的初始化不受保护,或使用狭窄的异常类型 catch 来保护源写入,导致源失败仍可能在 AE 写入前崩溃——对于每个提供商,双写必须保持两次独立写入(每个 SDK 都有自己的try/catch,包括初始化,覆盖完整失败面),这样任一 SDK 失败或被卸载都不会拖垮另一个。try/catch - 跳过阶段 2 的映射摘要确认。
- 将 /
user_append写入user_unset的draft.json(计划枚举只有update_type/user_set/user_setOnce)——append/unset 保留在user_add的mapping.json中,并在阶段 4 直接发出。ae_call - 在任何面向用户的输出中将“Super Property”翻译为“超级属性”。
- 在 git-status 预先检查(插入模式)之前编写源或 AE 代码。
- 编辑提供商适配器以将特定于提供商的逻辑添加到核心——新提供商只能是新的适配器文件。
- 在未明确警告用户并在删除前获得其确认的情况下删除源埋点代码或移除源 SDK 依赖(模式)。
switch
Internal Reference
内部参考 Internal Reference
- — normalized IR schema (
references/ir.md/scan.json).mapping.json - — provider-agnostic mapping algorithm.
references/mapping-framework.md - — authoritative AE
references/ae-preset-properties.mdpreset-property list + system fields (only these#names ingest).# - — adapter contract + how to add a provider.
references/providers/README.md - — Firebase adapter.
references/providers/firebase.md - — Amplitude adapter.
references/providers/amplitude.md - — Sensors Data (神策) adapter.
references/providers/sensors-data.md - — Mixpanel adapter.
references/providers/mixpanel.md - — Google Analytics 4 (gtag.js / Measurement Protocol) adapter.
references/providers/ga4.md
- — 归一化 IR 模式(
references/ir.md/scan.json)。mapping.json - — 与提供商无关的映射算法。
references/mapping-framework.md - — 权威的 AE
references/ae-preset-properties.md预置属性列表 + 系统字段(仅这些#名称可摄取)。# - — 适配器合约 + 如何添加提供商。
references/providers/README.md - — Firebase 适配器。
references/providers/firebase.md - — Amplitude 适配器。
references/providers/amplitude.md - — Sensors Data(神策)适配器。
references/providers/sensors-data.md - — Mixpanel 适配器。
references/providers/mixpanel.md - — Google Analytics 4(gtag.js / Measurement Protocol)适配器。
references/providers/ga4.md