siluzan-tso-cli 1.1.19-beta.8 → 1.1.19-beta.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -51,7 +51,7 @@ siluzan-tso init -d /path/to/skills # 写入自定义目录
|
|
|
51
51
|
siluzan-tso init --force # 强制覆盖已存在文件
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
-
> **注意**:当前为测试版(1.1.19-beta.
|
|
54
|
+
> **注意**:当前为测试版(1.1.19-beta.9),供内部测试使用。正式发布后安装命令将改为 `npm install -g siluzan-tso-cli`。
|
|
55
55
|
|
|
56
56
|
| 助手 | 建议 `--ai` |
|
|
57
57
|
| ----------------------- | ------------------------------------ |
|
package/dist/index.js
CHANGED
|
@@ -4526,6 +4526,16 @@ import * as path11 from "path";
|
|
|
4526
4526
|
function googleAnalysisManifestFile(accountId) {
|
|
4527
4527
|
return `${applyIdSuffix("manifest", accountId)}.json`;
|
|
4528
4528
|
}
|
|
4529
|
+
function buildOutlineHints(section) {
|
|
4530
|
+
const hints = [];
|
|
4531
|
+
if (RATE_BEARING_SECTIONS.has(section)) {
|
|
4532
|
+
hints.push(...GOOGLE_ANALYSIS_RATE_NORMALIZED_OUTLINE_HINTS);
|
|
4533
|
+
}
|
|
4534
|
+
if (section === "campaigns") {
|
|
4535
|
+
hints.push(...GOOGLE_ANALYSIS_CAMPAIGNS_OUTLINE_BUDGET_HINTS);
|
|
4536
|
+
}
|
|
4537
|
+
return hints.length > 0 ? hints : void 0;
|
|
4538
|
+
}
|
|
4529
4539
|
function sectionToFilename(section, accountId) {
|
|
4530
4540
|
if (!/^[a-z0-9-]+$/.test(section)) {
|
|
4531
4541
|
throw new Error(`\u975E\u6CD5\u5B50\u547D\u4EE4\u540D\uFF0C\u65E0\u6CD5\u751F\u6210\u6587\u4EF6\u540D\uFF1A${section}`);
|
|
@@ -4585,7 +4595,7 @@ async function writeGoogleAnalysisSnapshot(params) {
|
|
|
4585
4595
|
await fs7.writeFile(path11.join(absDir, fileName), `${body}
|
|
4586
4596
|
`, "utf8");
|
|
4587
4597
|
const outlineFileName = snapshotOutlineFileName(fileName);
|
|
4588
|
-
const outlineExtra = params.section
|
|
4598
|
+
const outlineExtra = buildOutlineHints(params.section);
|
|
4589
4599
|
const outlineBody = formatOutlineFileBody(fileName, params.payload, outlineExtra);
|
|
4590
4600
|
await fs7.writeFile(path11.join(absDir, outlineFileName), `${outlineBody}
|
|
4591
4601
|
`, "utf8");
|
|
@@ -4620,7 +4630,7 @@ async function writeGoogleAnalysisSnapshot(params) {
|
|
|
4620
4630
|
agentHint: OUTLINE_AGENT_HINT
|
|
4621
4631
|
};
|
|
4622
4632
|
}
|
|
4623
|
-
var LEGACY_MANIFEST_FILE, CLI_PACKAGE2, SCHEMA_VERSION2, DEFAULT_FIELD_GUIDE2, GOOGLE_ANALYSIS_CAMPAIGNS_OUTLINE_BUDGET_HINTS;
|
|
4633
|
+
var LEGACY_MANIFEST_FILE, CLI_PACKAGE2, SCHEMA_VERSION2, DEFAULT_FIELD_GUIDE2, GOOGLE_ANALYSIS_CAMPAIGNS_OUTLINE_BUDGET_HINTS, RATE_BEARING_SECTIONS, GOOGLE_ANALYSIS_RATE_NORMALIZED_OUTLINE_HINTS;
|
|
4624
4634
|
var init_google_analysis = __esm({
|
|
4625
4635
|
"src/utils/snapshot/google-analysis.ts"() {
|
|
4626
4636
|
"use strict";
|
|
@@ -4628,7 +4638,7 @@ var init_google_analysis = __esm({
|
|
|
4628
4638
|
init_dir();
|
|
4629
4639
|
LEGACY_MANIFEST_FILE = "manifest.json";
|
|
4630
4640
|
CLI_PACKAGE2 = "siluzan-tso-cli";
|
|
4631
|
-
SCHEMA_VERSION2 =
|
|
4641
|
+
SCHEMA_VERSION2 = 2;
|
|
4632
4642
|
DEFAULT_FIELD_GUIDE2 = {
|
|
4633
4643
|
markdownRefs: ["references/account-analytics.md"],
|
|
4634
4644
|
tsTypesModule: "tso-cli/src/types/google-analysis-api.ts"
|
|
@@ -4637,6 +4647,29 @@ var init_google_analysis = __esm({
|
|
|
4637
4647
|
"// \u91D1\u989D\uFF1A`campaigns[].budgetAmount`\uFF1D\u7F51\u5173\u300C\u5206\u300D\uFF08\u4E3B\u5E01\u79CD\xD7100 \u7684\u6574\u6570\uFF09\uFF0C**\u5143\uFF1D\xF7100**\uFF1B**\u7981\u6B62**\u6309\u5FAE\u5143 **\xF71_000_000**\uFF08\u4F1A\u7EA6\u5C0F\u4E00\u4E07\u500D\uFF09\u3002",
|
|
4638
4648
|
"// \u540C\u6587\u4EF6 `spend`\u3001`averageCpc`\u3001`costPerConversion` \u7B49\u5DF2\u4E3A\u300C\u5143\u300D\u5C0F\u6570\u3002\u8BE6 `references/account-analytics.md`\u300CCampaignSectionData\u300D\u3002"
|
|
4639
4649
|
];
|
|
4650
|
+
RATE_BEARING_SECTIONS = /* @__PURE__ */ new Set([
|
|
4651
|
+
"overview",
|
|
4652
|
+
"keywords",
|
|
4653
|
+
"search-terms",
|
|
4654
|
+
"campaigns",
|
|
4655
|
+
"ads",
|
|
4656
|
+
"extensions",
|
|
4657
|
+
"devices",
|
|
4658
|
+
"geographic",
|
|
4659
|
+
"campaign-geo",
|
|
4660
|
+
"campaign-device",
|
|
4661
|
+
"audience",
|
|
4662
|
+
"asset-images",
|
|
4663
|
+
"videos",
|
|
4664
|
+
"materials",
|
|
4665
|
+
"daily-metrics",
|
|
4666
|
+
"dimension-summary",
|
|
4667
|
+
"ads-index"
|
|
4668
|
+
]);
|
|
4669
|
+
GOOGLE_ANALYSIS_RATE_NORMALIZED_OUTLINE_HINTS = [
|
|
4670
|
+
"// \u6982\u7387\u5B57\u6BB5\uFF1A`ctr` / `conversionRate` \u81EA manifest schemaVersion 2\uFF082026-05\uFF09\u8D77\u5DF2\u7531 CLI \u7EDF\u4E00\u5F52\u4E00\u4E3A **0~1 \u5C0F\u6570**\uFF08\u5982 `0.0964` = 9.64%\uFF09\u3002",
|
|
4671
|
+
"// \u5199 Excel 0~1 \u5C0F\u6570\u5217\uFF1A\u76F4\u63A5\u5199\u5165\uFF1B\u5199\u300Cx%\u300D\u6587\u6848\uFF1A`(v * 100).toFixed(2) + '%'`\uFF1B**\u7981\u6B62**\u518D \xF7100\u3002`interactionRate` \u4ECD\u662F\u5B57\u7B26\u4E32 0~1 \u5C0F\u6570\uFF0C`parseFloat` \u540E\u4F7F\u7528\u3002"
|
|
4672
|
+
];
|
|
4640
4673
|
}
|
|
4641
4674
|
});
|
|
4642
4675
|
|
|
@@ -4833,6 +4866,50 @@ var init_sections = __esm({
|
|
|
4833
4866
|
}
|
|
4834
4867
|
});
|
|
4835
4868
|
|
|
4869
|
+
// src/commands/google-analysis/normalize-rates.ts
|
|
4870
|
+
function divIfFiniteNumber(v) {
|
|
4871
|
+
return typeof v === "number" && Number.isFinite(v) ? v / 100 : v;
|
|
4872
|
+
}
|
|
4873
|
+
function divideRatesInPlace(value, seen) {
|
|
4874
|
+
if (value === null || typeof value !== "object") return;
|
|
4875
|
+
if (seen.has(value)) return;
|
|
4876
|
+
seen.add(value);
|
|
4877
|
+
if (Array.isArray(value)) {
|
|
4878
|
+
for (const item of value) divideRatesInPlace(item, seen);
|
|
4879
|
+
return;
|
|
4880
|
+
}
|
|
4881
|
+
const obj = value;
|
|
4882
|
+
for (const k of Object.keys(obj)) {
|
|
4883
|
+
if (RATE_FIELD_NAMES.has(k)) {
|
|
4884
|
+
obj[k] = divIfFiniteNumber(obj[k]);
|
|
4885
|
+
} else {
|
|
4886
|
+
divideRatesInPlace(obj[k], seen);
|
|
4887
|
+
}
|
|
4888
|
+
}
|
|
4889
|
+
}
|
|
4890
|
+
function normalizeRateScales(payload, section) {
|
|
4891
|
+
if (!PERCENT_SCALE_SECTIONS.has(section)) return payload;
|
|
4892
|
+
divideRatesInPlace(payload, /* @__PURE__ */ new WeakSet());
|
|
4893
|
+
return payload;
|
|
4894
|
+
}
|
|
4895
|
+
var PERCENT_SCALE_SECTIONS, RATE_FIELD_NAMES;
|
|
4896
|
+
var init_normalize_rates = __esm({
|
|
4897
|
+
"src/commands/google-analysis/normalize-rates.ts"() {
|
|
4898
|
+
"use strict";
|
|
4899
|
+
PERCENT_SCALE_SECTIONS = /* @__PURE__ */ new Set([
|
|
4900
|
+
"overview",
|
|
4901
|
+
"keywords",
|
|
4902
|
+
"search-terms",
|
|
4903
|
+
"campaigns",
|
|
4904
|
+
"ads",
|
|
4905
|
+
"extensions",
|
|
4906
|
+
"devices",
|
|
4907
|
+
"ads-index"
|
|
4908
|
+
]);
|
|
4909
|
+
RATE_FIELD_NAMES = /* @__PURE__ */ new Set(["ctr", "conversionRate"]);
|
|
4910
|
+
}
|
|
4911
|
+
});
|
|
4912
|
+
|
|
4836
4913
|
// src/commands/google-analysis/fetch.ts
|
|
4837
4914
|
function defaultDateRange3() {
|
|
4838
4915
|
const end = /* @__PURE__ */ new Date();
|
|
@@ -4968,7 +5045,7 @@ async function fetchSectionPayload(def, opts, config, id) {
|
|
|
4968
5045
|
fetchJson(config, videoPath, !!opts.verbose)
|
|
4969
5046
|
]);
|
|
4970
5047
|
const merged = { images, videos };
|
|
4971
|
-
return stripLegacyGoogleFieldsIfV2Present(merged);
|
|
5048
|
+
return normalizeRateScales(stripLegacyGoogleFieldsIfV2Present(merged), "materials");
|
|
4972
5049
|
}
|
|
4973
5050
|
if (def.name === "daily-metrics") {
|
|
4974
5051
|
const { startDate, endDate } = resolveDateRange2(opts.start, opts.end);
|
|
@@ -4980,7 +5057,7 @@ async function fetchSectionPayload(def, opts, config, id) {
|
|
|
4980
5057
|
const url = `${config.apiBaseUrl}/report/media-account/google/account-daily-reports?${params.toString()}`;
|
|
4981
5058
|
const raw = await apiFetch2(url, config, {}, !!opts.verbose);
|
|
4982
5059
|
const rows = rowsFromAccountDailyReportsEnvelope(raw, id);
|
|
4983
|
-
return stripLegacyGoogleFieldsIfV2Present(rows);
|
|
5060
|
+
return normalizeRateScales(stripLegacyGoogleFieldsIfV2Present(rows), "daily-metrics");
|
|
4984
5061
|
}
|
|
4985
5062
|
const sectionPath = def.path(id);
|
|
4986
5063
|
const query = buildSearchParams(def, opts.start, opts.end, extras);
|
|
@@ -4990,7 +5067,7 @@ async function fetchSectionPayload(def, opts, config, id) {
|
|
|
4990
5067
|
!!opts.verbose,
|
|
4991
5068
|
def.name
|
|
4992
5069
|
);
|
|
4993
|
-
return stripLegacyGoogleFieldsIfV2Present(data);
|
|
5070
|
+
return normalizeRateScales(stripLegacyGoogleFieldsIfV2Present(data), def.name);
|
|
4994
5071
|
}
|
|
4995
5072
|
function endpointHintForSection(def) {
|
|
4996
5073
|
if (def.name === "materials") return "CampaignAssetView+Videos";
|
|
@@ -5030,6 +5107,7 @@ var init_fetch = __esm({
|
|
|
5030
5107
|
init_auth();
|
|
5031
5108
|
init_strip_legacy_google_fields();
|
|
5032
5109
|
init_sections();
|
|
5110
|
+
init_normalize_rates();
|
|
5033
5111
|
}
|
|
5034
5112
|
});
|
|
5035
5113
|
|
|
@@ -6664,6 +6742,7 @@ var init_google_analysis2 = __esm({
|
|
|
6664
6742
|
"use strict";
|
|
6665
6743
|
init_sections();
|
|
6666
6744
|
init_fetch();
|
|
6745
|
+
init_normalize_rates();
|
|
6667
6746
|
init_register_cli();
|
|
6668
6747
|
}
|
|
6669
6748
|
});
|
package/dist/skill/_meta.json
CHANGED
|
@@ -59,14 +59,18 @@ siluzan-tso google-analysis -a <mediaCustomerId> --start <S> --end <E> --json-ou
|
|
|
59
59
|
|
|
60
60
|
以下按 **工作簿 → Sheet 名(须完全一致)→ 版式** 约定,便于 WorkBuddy / 人工用样表对照验收。**不**再单独建名为「广告系列」的 Sheet(系列表在 **`账户报告`** 内)。**金额等展示列**:脚本与运营约定保留小数位数(常见两位),须与样表一致。
|
|
61
61
|
|
|
62
|
-
### 脚本写表:点击率 / 转化率 /
|
|
62
|
+
### 脚本写表:点击率 / 转化率 / 互动率
|
|
63
63
|
|
|
64
|
-
|
|
64
|
+
> **2026-05 起 CLI 已统一归一**(manifest `schemaVersion: 2`):所有 `<section>-*.json` 中的 `ctr` / `conversionRate` 一律为 **0~1 小数**(如 `0.0964` = 9.64%)。无需再按维度做 ÷100 分支;下表与脚本片段仅作快速参考。详见 `references/account-analytics.md`「指标字段对照」。
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
66
|
+
| 场景 | 处理 |
|
|
67
|
+
| --------------------------------------------------- | ------------------------------------------------------------------------------------------ |
|
|
68
|
+
| **写入 Excel 0~1 小数列**(点击率/转化率/互动率) | 直接写入 JSON 数值(**禁止**再 ÷100) |
|
|
69
|
+
| **写客户话术 / 文案的 `x%`** | `(v * 100).toFixed(2) + "%"`(**禁止**直接打印数值得到 "0.09%") |
|
|
70
|
+
| **`interactionRate`(字符串)** | `parseFloat(row.interactionRate)` 后按数值字段使用(同样 0~1 小数) |
|
|
71
|
+
| **`interactions === 0` / `null`** | **平均费用**(`spend / interactions`)与 **互动率** 列填 **`—`**,禁止除零 |
|
|
72
|
+
|
|
73
|
+
> **历史快照兼容(`schemaVersion: 1` 旧目录)**:2026-04 及更早落盘 JSON **未归一**——`overview` / `campaigns` / `keywords` / `search-terms` / `ads` / `extensions` / `devices`(账户级)/ `ads-index` 这 8 个维度仍是百分数刻度(如 `ctr: 9.636` = 9.636%),写入前须 ÷100;其余维度原样为 0~1 小数。先看 `manifest-<id>.json` 顶部 `schemaVersion` 判别,**不要**用「值 > 1 才 ÷100」启发式(搜索词旧行 `ctr: 100` 会被误判)。
|
|
70
74
|
|
|
71
75
|
### 工作簿级
|
|
72
76
|
|
|
@@ -99,7 +103,7 @@ siluzan-tso google-analysis -a <mediaCustomerId> --start <S> --end <E> --json-ou
|
|
|
99
103
|
| R1 标题 | `广告系列报告`(与样表一致;若运营统一改名,可改文案但须保持 Sheet 名仍为 `账户报告`) |
|
|
100
104
|
| R2 | 统计区间(中文日期,见上) |
|
|
101
105
|
| R3 表头(A→K,共 11 列) | `广告系列` \| `预算` \| `费用` \| `展示次数` \| `点击次数` \| `点击率` \| `平均每次点击费用` \| `所有转化次数` \| `转化次数` \| `每次转化费用` \| `转化率` |
|
|
102
|
-
| R4… | 每行一条广告系列:来自 `campaigns-*.json` 的 `campaignName`、`budgetAmount`(÷100 为元)、`spend`、`impressions`、`clicks`、**`ctr
|
|
106
|
+
| R4… | 每行一条广告系列:来自 `campaigns-*.json` 的 `campaignName`、`budgetAmount`(÷100 为元)、`spend`、`impressions`、`clicks`、**`ctr` 直接写入「点击率」(已归一为 0~1 小数)**、`averageCpc`、**`allConversions ` →「所有转化次数」**、**`conversions` →「转化次数」**、`costPerConversion`、**`conversionRate` 直接写入「转化率」(已归一为 0~1 小数)**;若缺 `allConversions ` 仅 `conversions`,「所有转化次数」可与「转化次数」同值或填 `0` / `—` 并在脚注说明(以 outline 为准) |
|
|
103
107
|
| 末行「合计」 | **广告系列**列填 `总计`;**预算**列填 `--`;**展示 / 点击 / 所有转化次数 / 转化次数 / 费用**等做列求和;**点击率** = 合计点击÷合计展示;**转化率** = 合计转化÷合计点击(**禁止**用合计转化÷合计展示冒充);**每次转化费用** = 合计费用÷合计转化(转化为 0 时填 `—`);禁止对各行比率取算术平均 |
|
|
104
108
|
|
|
105
109
|
表下**留白若干行**后写 **「数据复盘」**(与样表一致):
|
|
@@ -122,7 +126,7 @@ siluzan-tso google-analysis -a <mediaCustomerId> --start <S> --end <E> --json-ou
|
|
|
122
126
|
| R1 标题 | `搜索关键字报告` |
|
|
123
127
|
| R2 | 统计区间(同 `账户报告`) |
|
|
124
128
|
| R3 表头(A→L,共 12 列) | `关键字` \| `匹配类型` \| `广告系列` \| `广告组` \| `费用` \| `展示次数` \| `点击次数` \| `点击率` \| `平均每次点击费用` \| `转化次数` \| `每次转化费用` \| `转化率` |
|
|
125
|
-
| R4… | `keywords-*.json` 行映射;`keywordMatchType` → 匹配类型;`campaignName` / `adGroupName` 等按 outline |
|
|
129
|
+
| R4… | `keywords-*.json` 行映射;`keywordMatchType` → 匹配类型;`campaignName` / `adGroupName` 等按 outline;**`ctr` / `conversionRate` 直接写入「点击率」「转化率」(CLI 已统一归一为 0~1 小数)** |
|
|
126
130
|
|
|
127
131
|
---
|
|
128
132
|
|
|
@@ -133,7 +137,7 @@ siluzan-tso google-analysis -a <mediaCustomerId> --start <S> --end <E> --json-ou
|
|
|
133
137
|
| R1 标题 | `搜索字词报告` |
|
|
134
138
|
| R2 | 统计区间 |
|
|
135
139
|
| R3 表头(A→N,共 14 列) | `搜索字词` \| `匹配类型` \| `已添加/已排除` \| `广告系列` \| `广告组` \| `关键字` \| `展示次数` \| `点击次数` \| `点击率` \| `平均每次点击费用` \| `费用` \| `转化次数` \| `每次转化费用` \| `转化率` |
|
|
136
|
-
| R4… | `search-terms-*.json`;`已添加/已排除` 若 JSON
|
|
140
|
+
| R4… | `search-terms-*.json`;`已添加/已排除` 若 JSON 无此枚举则留空或填「—」,禁止臆造状态;**`ctr` / `conversionRate` 直接写入「点击率」「转化率」(CLI 已统一归一为 0~1 小数)** |
|
|
137
141
|
|
|
138
142
|
---
|
|
139
143
|
|
|
@@ -144,7 +148,7 @@ siluzan-tso google-analysis -a <mediaCustomerId> --start <S> --end <E> --json-ou
|
|
|
144
148
|
| R1 标题 | `设备报告` |
|
|
145
149
|
| R2 | 统计区间 |
|
|
146
150
|
| R3 表头(A→M,共 13 列) | `设备` \| `级别` \| `广告系列` \| `出价调整` \| `展示次数` \| `点击次数` \| `点击率` \| `平均每次点击费用` \| `费用` \| `所有转化次数` \| `转化次数` \| `每次转化费用` \| `转化率` |
|
|
147
|
-
| R4… | **`campaign-device-*.json`**(`devices[]`):`deviceType` → 设备;`campaignName` / `adGroupName` →「广告系列」等;**`allConversions `(或 outline 中的等价字段)→「所有转化次数」**;`conversions` →「转化次数」;**`ctr` / `conversionRate`
|
|
151
|
+
| R4… | **`campaign-device-*.json`**(`devices[]`):`deviceType` → 设备;`campaignName` / `adGroupName` →「广告系列」等;**`allConversions `(或 outline 中的等价字段)→「所有转化次数」**;`conversions` →「转化次数」;**`ctr` / `conversionRate` 直接写入(已归一为 0~1 小数)**;**出价调整** 无字段则「—」;**级别**列按运营约定(如填 `广告系列` 或 `账户`,全文一致) |
|
|
148
152
|
|
|
149
153
|
---
|
|
150
154
|
|
|
@@ -155,7 +159,7 @@ siluzan-tso google-analysis -a <mediaCustomerId> --start <S> --end <E> --json-ou
|
|
|
155
159
|
| R1 标题 | `地理位置报告` |
|
|
156
160
|
| R2 | 统计区间 |
|
|
157
161
|
| R3 表头(A→M,共 13 列) | `地理位置` \| `广告系列` \| `展示次数` \| `互动次数` \| `互动率` \| `费用` \| `平均费用` \| `点击次数` \| `点击率` \| `所有转化次数` \| `转化次数` \| `每次转化费用` \| `转化率` |
|
|
158
|
-
| R4… | **`campaign-geo-*.json`**(`countries[]`):`countryOrRegion` → 地理位置;`campaignName` →「广告系列」;**`allConversions `(或等价)→「所有转化次数」**;`conversions` →「转化次数」;**互动次数** → `interactions`;**互动率** → `interactionRate`(字符串须解析)或 `interactions/impressions`(`interactions` 为 0 时互动率填 **`—`**);**平均费用** **必须**为 **`spend / interactions`**,`interactions` 为 0 / null / undefined 时填 **`—`**;**`ctr` / `conversionRate`
|
|
162
|
+
| R4… | **`campaign-geo-*.json`**(`countries[]`):`countryOrRegion` → 地理位置;`campaignName` →「广告系列」;**`allConversions `(或等价)→「所有转化次数」**;`conversions` →「转化次数」;**互动次数** → `interactions`;**互动率** → `interactionRate`(字符串须解析)或 `interactions/impressions`(`interactions` 为 0 时互动率填 **`—`**);**平均费用** **必须**为 **`spend / interactions`**,`interactions` 为 0 / null / undefined 时填 **`—`**;**`ctr` / `conversionRate` 直接写入(已归一为 0~1 小数)**;其余列按 outline 映射。 |
|
|
159
163
|
|
|
160
164
|
---
|
|
161
165
|
|
|
@@ -186,7 +190,7 @@ siluzan-tso google-analysis -a <mediaCustomerId> --start <S> --end <E> --json-ou
|
|
|
186
190
|
8. 账户余额:<金额+币种>(截至查询时点)
|
|
187
191
|
```
|
|
188
192
|
|
|
189
|
-
**第 3 条**:若 CLI 返回的是**账户整体 CTR**,话术写「整体点击率」而非「搜索点击率」,避免与搜索广告狭义口径冲突;若数据中可区分搜索广告 CTR
|
|
193
|
+
**第 3 条**:若 CLI 返回的是**账户整体 CTR**,话术写「整体点击率」而非「搜索点击率」,避免与搜索广告狭义口径冲突;若数据中可区分搜索广告 CTR,再写「搜索点击率」。**百分比数字**:`overview-*.json`(`schemaVersion: 2` 起)的 `ctr` 已是 **0~1 小数**(如 `0.1026`),话术 `x%` 用 `(ctr * 100).toFixed(2) + "%"`,**禁止**直接打印数值得到 "0.1%"。
|
|
190
194
|
|
|
191
195
|
**第 1 条「平均每天」**:`区间总消耗 / 区间日历天数`(含起止日),在脚本中计算,禁止手填。
|
|
192
196
|
|