siluzan-tso-cli 1.1.15-beta.4 → 1.1.15-beta.6
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 +1 -1
- package/assets/siluzan-ads/references/hosted-automation-user-catalog.md +4 -4
- package/dist/index.js +73 -112
- package/dist/skill/SKILL.md +122 -268
- package/dist/skill/_meta.json +2 -2
- package/dist/skill/references/account-analytics.md +161 -228
- package/dist/skill/references/google-ads-rules/google-ads-account-audit.md +64 -65
- package/dist/skill/references/google-ads-rules/google-ads-audience-strategy.md +14 -14
- package/dist/skill/references/google-ads-rules/google-ads-campaign-optimization.md +9 -9
- package/dist/skill/references/google-ads-rules/google-ads-conversion-architecture.md +12 -12
- package/dist/skill/references/google-ads-rules/google-ads-creative-optimization.md +1 -1
- package/dist/skill/references/google-ads-rules/google-ads-keyword-optimization.md +15 -15
- package/dist/skill/references/google-ads-rules/google-ads-pmax-guide.md +24 -24
- package/dist/skill/references/google-ads.md +2 -2
- package/dist/skill/references/hosted-automation-monitoring-json.md +5 -5
- package/dist/skill/references/hosted-automation-optimize-ab-winner.md +1 -1
- package/dist/skill/references/hosted-automation-optimize-index.md +1 -1
- package/dist/skill/references/hosted-automation-optimize-scale.md +4 -4
- package/dist/skill/references/hosted-automation-optimize-weak-downbid.md +2 -2
- package/dist/skill/references/hosted-automation-scenarios.md +2 -2
- package/dist/skill/references/hosted-automation-user-catalog.md +4 -4
- package/dist/skill/references/tips.md +21 -0
- package/dist/skill/report-templates/REPORT-WORKFLOW.md +1 -1
- package/dist/skill/report-templates/google-account-diagnosis-report.md +11 -11
- package/dist/skill/report-templates/google-period-report.md +28 -27
- package/dist/skill/report-templates/meta-period-report.md +1 -1
- package/eval/cases/google-analysis-keywords-route.scenario.json +2 -2
- package/eval/cases/uj-analytics-30d-pdf-campaign-device-geo.scenario.json +1 -1
- package/eval/cases/uj-analytics-google-weekly-trends-campaigns-keywords.scenario.json +1 -1
- package/eval/cases/uj-roi-keywords-high-cpa-low-cvr-triage.scenario.json +1 -1
- package/eval/cases/uj-roi-search-terms-add-negative-keywords.scenario.json +2 -2
- package/eval/stub-fixtures/google-analysis.json +32 -5
- package/package.json +1 -1
- package/eval/stub-fixtures/google-analysis-search-terms.json +0 -10
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.15-beta.
|
|
54
|
+
> **注意**:当前为测试版(1.1.15-beta.6),供内部测试使用。正式发布后安装命令将改为 `npm install -g siluzan-tso-cli`。
|
|
55
55
|
|
|
56
56
|
| 助手 | 建议 `--ai` |
|
|
57
57
|
| ----------------------- | ------------------------------------ |
|
|
@@ -21,10 +21,10 @@
|
|
|
21
21
|
| 功能名称 | 监控层级 / 说明 | CLI 检查入口(`--json`) |
|
|
22
22
|
| ----------------- | --------------- | ------------------------ |
|
|
23
23
|
| 1. 账户被封禁 | 账户级;与 Google `CustomerStatus` 及 `list-accounts` 的字段映射**暂不写进本 skill**,由宿主约定。 | `list-accounts`、`balance` 等见 [`accounts.md`](accounts.md) |
|
|
24
|
-
| 2. 落地页死链强停 | URL 不可用或跳错页时暂停关联创意,避免无效消耗。 | **`google-analysis final-urls`**;或 **`ad list`** / **`google-analysis ads`** 取落地页字段后由宿主 HTTP 校验 |
|
|
25
|
-
| 3. 广告素材拒审 | 创意政策状态异常时告警或配合工单。 | **`ad list`** / **`google-analysis ads`**:`policyApprovalStatusV2`、`approvalStatusDetails` 等(见 **[`google-ads.md`](google-ads.md)**) |
|
|
26
|
-
| 4. 花费异动监控 | 系列或账户维度花费相对历史异常波动。 | **`google-analysis campaign-hour`**:按 `campaignId` + `date` + `hour` 看 **`spend`** |
|
|
27
|
-
| 5. 余额枯竭预警 | 余额过低或按日均推算续航不足。 | **`balance-scan`**(`balance`、`remainingDays`、`hitReason`、`meta`)或 **`balance`** / **`google-analysis overview`**(`remainingAccountBudget`、`averageDailyCost` 等) |
|
|
24
|
+
| 2. 落地页死链强停 | URL 不可用或跳错页时暂停关联创意,避免无效消耗。 | **`google-analysis --sections final-urls`**;或 **`ad list`** / **`google-analysis --sections ads`** 取落地页字段后由宿主 HTTP 校验 |
|
|
25
|
+
| 3. 广告素材拒审 | 创意政策状态异常时告警或配合工单。 | **`ad list`** / **`google-analysis --sections ads`**:`policyApprovalStatusV2`、`approvalStatusDetails` 等(见 **[`google-ads.md`](google-ads.md)**) |
|
|
26
|
+
| 4. 花费异动监控 | 系列或账户维度花费相对历史异常波动。 | **`google-analysis --sections campaign-hour`**:按 `campaignId` + `date` + `hour` 看 **`spend`** |
|
|
27
|
+
| 5. 余额枯竭预警 | 余额过低或按日均推算续航不足。 | **`balance-scan`**(`balance`、`remainingDays`、`hitReason`、`meta`)或 **`balance`** / **`google-analysis --sections overview`**(`remainingAccountBudget`、`averageDailyCost` 等) |
|
|
28
28
|
|
|
29
29
|
## 自动优化
|
|
30
30
|
|
package/dist/index.js
CHANGED
|
@@ -3538,6 +3538,10 @@ async function writeGoogleAnalysisSnapshot(params) {
|
|
|
3538
3538
|
const writtenAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
3539
3539
|
const body = JSON.stringify(params.payload, null, 2);
|
|
3540
3540
|
await fs4.writeFile(path6.join(absDir, fileName), `${body}
|
|
3541
|
+
`, "utf8");
|
|
3542
|
+
const outlineFileName = snapshotOutlineFileName(fileName);
|
|
3543
|
+
const outlineBody = formatOutlineFileBody(fileName, params.payload);
|
|
3544
|
+
await fs4.writeFile(path6.join(absDir, outlineFileName), `${outlineBody}
|
|
3541
3545
|
`, "utf8");
|
|
3542
3546
|
const existing = await readManifestIfExists(absDir, accountSlug || void 0);
|
|
3543
3547
|
const newArtifact = {
|
|
@@ -3564,8 +3568,10 @@ async function writeGoogleAnalysisSnapshot(params) {
|
|
|
3564
3568
|
schemaVersion: SCHEMA_VERSION,
|
|
3565
3569
|
absoluteSnapshotDir: absDir,
|
|
3566
3570
|
manifestFile,
|
|
3567
|
-
writtenFiles: [fileName],
|
|
3568
|
-
section: params.section
|
|
3571
|
+
writtenFiles: [fileName, outlineFileName],
|
|
3572
|
+
section: params.section,
|
|
3573
|
+
outlineFile: outlineFileName,
|
|
3574
|
+
agentHint: OUTLINE_AGENT_HINT
|
|
3569
3575
|
};
|
|
3570
3576
|
}
|
|
3571
3577
|
|
|
@@ -3573,6 +3579,7 @@ async function writeGoogleAnalysisSnapshot(params) {
|
|
|
3573
3579
|
var CLI_SNAPSHOT_MANIFEST_FILE = "cli-manifest.json";
|
|
3574
3580
|
var CLI_PACKAGE2 = "siluzan-tso-cli";
|
|
3575
3581
|
var SCHEMA_VERSION2 = 1;
|
|
3582
|
+
var OUTLINE_AGENT_HINT = "\u5904\u7406\u987A\u5E8F\uFF1A\u5148\u8BFB outlineFile\uFF08schema \u63CF\u8FF0\uFF0C\u975E\u6570\u636E\uFF09\u4E86\u89E3\u5B57\u6BB5\u7C7B\u578B\uFF0C\u518D\u7528\u811A\u672C\u8BFB writtenFiles[0]\uFF08\u771F\u5B9E JSON \u6570\u636E\uFF09\u505A\u7B5B\u9009/\u805A\u5408\uFF1B\u4E0D\u8981\u628A outline \u5F53\u6210\u6570\u636E\uFF0C\u4E5F\u4E0D\u8981\u628A JSON \u5F53\u6210 schema\u3002";
|
|
3576
3583
|
var DEFAULT_FIELD_GUIDE2 = {
|
|
3577
3584
|
markdownRefs: ["references/tips.md", "references/accounts.md"]
|
|
3578
3585
|
};
|
|
@@ -3706,9 +3713,18 @@ function snapshotOutlineFileName(jsonBasename) {
|
|
|
3706
3713
|
}
|
|
3707
3714
|
return `${jsonBasename.slice(0, -".json".length)}.outline.txt`;
|
|
3708
3715
|
}
|
|
3716
|
+
function formatOutlineFileBody(jsonBasename, payload) {
|
|
3717
|
+
const typeText = describePayloadTsLike(payload);
|
|
3718
|
+
const lines = [
|
|
3719
|
+
`// outline of \`${jsonBasename}\` \u2014 schema-only, NOT the data.`,
|
|
3720
|
+
`// \u7528\u6CD5\uFF1A\u5904\u7406\u540C\u76EE\u5F55 \`${jsonBasename}\` \u7684\u6570\u636E\u524D\uFF0C\u5148\u8BFB\u672C\u6587\u4EF6\u4E86\u89E3\u5B57\u6BB5\u7C7B\u578B\uFF0C\u518D\u7528\u811A\u672C\uFF08fs.readFileSync / require\uFF09\u8BFB\u53D6\u8BE5 JSON \u505A\u7B5B\u9009\u4E0E\u805A\u5408\u3002`,
|
|
3721
|
+
`// \u7C7B\u578B\u7531 JSON \u63A8\u65AD\uFF1A\u6570\u7EC4\u53D6\u524D 8 \u9879\u53BB\u91CD\u5E76\u96C6\uFF1B\u73AF\u6216\u91CD\u590D\u5BF9\u8C61\u5F15\u7528\u8BB0\u4E3A any\u3002`,
|
|
3722
|
+
typeText
|
|
3723
|
+
];
|
|
3724
|
+
return lines.join("\n");
|
|
3725
|
+
}
|
|
3709
3726
|
async function writeCliJsonSnapshot(params) {
|
|
3710
3727
|
const trimmed = params.snapshotDir.trim();
|
|
3711
|
-
const outlineText = describePayloadTsLike(params.payload);
|
|
3712
3728
|
const idSlug = slugifyIdSuffix(params.idSuffix);
|
|
3713
3729
|
const manifestFile = cliManifestFileName(idSlug || void 0);
|
|
3714
3730
|
let absDir;
|
|
@@ -3744,7 +3760,8 @@ async function writeCliJsonSnapshot(params) {
|
|
|
3744
3760
|
if (outlineFileName.toLowerCase() === manifestFile.toLowerCase()) {
|
|
3745
3761
|
throw new Error(`\u975E\u6CD5\u8F93\u51FA\uFF1A${outlineFileName} \u4E0E\u6E05\u5355\u6587\u4EF6\u540D\u51B2\u7A81`);
|
|
3746
3762
|
}
|
|
3747
|
-
|
|
3763
|
+
const outlineBody = formatOutlineFileBody(fileName, params.payload);
|
|
3764
|
+
await fs5.writeFile(path7.join(absDir, outlineFileName), `${outlineBody}
|
|
3748
3765
|
`, "utf8");
|
|
3749
3766
|
const existing = await readCliManifestIfExists(absDir, idSlug || void 0);
|
|
3750
3767
|
const newArtifact = {
|
|
@@ -3770,7 +3787,8 @@ async function writeCliJsonSnapshot(params) {
|
|
|
3770
3787
|
manifestFile,
|
|
3771
3788
|
writtenFiles: [fileName, outlineFileName],
|
|
3772
3789
|
section,
|
|
3773
|
-
outlineFile: outlineFileName
|
|
3790
|
+
outlineFile: outlineFileName,
|
|
3791
|
+
agentHint: OUTLINE_AGENT_HINT
|
|
3774
3792
|
};
|
|
3775
3793
|
}
|
|
3776
3794
|
async function emitCliJsonOrSnapshot(opts, params) {
|
|
@@ -6429,7 +6447,7 @@ async function writeReportAnalysisSnapshot(params) {
|
|
|
6429
6447
|
);
|
|
6430
6448
|
await fs8.writeFile(
|
|
6431
6449
|
path11.join(absDir, outlineFileName),
|
|
6432
|
-
`${
|
|
6450
|
+
`${formatOutlineFileBody(fileName, params.payload)}
|
|
6433
6451
|
`,
|
|
6434
6452
|
"utf8"
|
|
6435
6453
|
);
|
|
@@ -6459,7 +6477,8 @@ async function writeReportAnalysisSnapshot(params) {
|
|
|
6459
6477
|
manifestFile,
|
|
6460
6478
|
writtenFiles: [fileName, outlineFileName],
|
|
6461
6479
|
section: params.section,
|
|
6462
|
-
outlineFile: outlineFileName
|
|
6480
|
+
outlineFile: outlineFileName,
|
|
6481
|
+
agentHint: OUTLINE_AGENT_HINT
|
|
6463
6482
|
};
|
|
6464
6483
|
}
|
|
6465
6484
|
|
|
@@ -7305,22 +7324,6 @@ function manifestDateRange(def, start, end) {
|
|
|
7305
7324
|
const { startDate, endDate } = resolveDateRange(start, end);
|
|
7306
7325
|
return { mode: "range", start: startDate, end: endDate };
|
|
7307
7326
|
}
|
|
7308
|
-
function summarizeHuman(section, data) {
|
|
7309
|
-
if (data === null || data === void 0) return "\u65E0\u6570\u636E";
|
|
7310
|
-
if (Array.isArray(data)) return `\u6570\u7EC4\uFF0C\u5171 ${data.length} \u6761`;
|
|
7311
|
-
if (typeof data === "object") {
|
|
7312
|
-
const o = data;
|
|
7313
|
-
if (Array.isArray(o.keywords)) return `keywords\uFF1A${o.keywords.length} \u6761`;
|
|
7314
|
-
if (Array.isArray(o.campaigns)) return `campaigns\uFF1A${o.campaigns.length} \u6761`;
|
|
7315
|
-
if (Array.isArray(o.devices)) return `devices\uFF1A${o.devices.length} \u6761`;
|
|
7316
|
-
if (Array.isArray(o.countries)) return `countries\uFF1A${o.countries.length} \u6761`;
|
|
7317
|
-
if (Array.isArray(o.audience)) return `audience\uFF1A${o.audience.length} \u6761`;
|
|
7318
|
-
if (Array.isArray(o.data)) return `data\uFF1A${o.data.length} \u6761`;
|
|
7319
|
-
const keys = Object.keys(o);
|
|
7320
|
-
return `\u5BF9\u8C61\uFF0C\u9876\u5C42\u5B57\u6BB5\uFF1A${keys.slice(0, 8).join(", ")}${keys.length > 8 ? "\u2026" : ""}`;
|
|
7321
|
-
}
|
|
7322
|
-
return String(data);
|
|
7323
|
-
}
|
|
7324
7327
|
async function fetchSectionPayload(def, opts, config, id) {
|
|
7325
7328
|
const extras = {};
|
|
7326
7329
|
if (def.keywordOptions) {
|
|
@@ -7363,63 +7366,6 @@ function endpointHintForSection(def) {
|
|
|
7363
7366
|
if (def.name === "materials") return "CampaignAssetView+Videos";
|
|
7364
7367
|
return endpointHintFrom(def);
|
|
7365
7368
|
}
|
|
7366
|
-
async function runOneSection(def, opts) {
|
|
7367
|
-
const config = loadConfig(opts.token);
|
|
7368
|
-
const id = opts.account.trim();
|
|
7369
|
-
if (!/^\d+$/.test(id)) {
|
|
7370
|
-
console.error("\n\u274C --account \u987B\u4E3A\u6570\u5B57 mediaCustomerId\u3002\n");
|
|
7371
|
-
process.exit(1);
|
|
7372
|
-
}
|
|
7373
|
-
if (opts.json && opts.jsonOut) {
|
|
7374
|
-
console.error(
|
|
7375
|
-
"\n\u274C --json \u4E0E --json-out \u4E0D\u80FD\u540C\u65F6\u4F7F\u7528\u3002\n"
|
|
7376
|
-
);
|
|
7377
|
-
process.exit(1);
|
|
7378
|
-
}
|
|
7379
|
-
try {
|
|
7380
|
-
const payload = await fetchSectionPayload(def, opts, config, id);
|
|
7381
|
-
if (opts.json) {
|
|
7382
|
-
console.log(JSON.stringify(payload, null, 2));
|
|
7383
|
-
return;
|
|
7384
|
-
}
|
|
7385
|
-
if (opts.jsonOut) {
|
|
7386
|
-
const summary = await writeGoogleAnalysisSnapshot({
|
|
7387
|
-
snapshotDir: opts.jsonOut,
|
|
7388
|
-
section: def.name,
|
|
7389
|
-
accountId: id,
|
|
7390
|
-
dateRange: manifestDateRange(def, opts.start, opts.end),
|
|
7391
|
-
payload,
|
|
7392
|
-
cliVersion: getCurrentVersion2(),
|
|
7393
|
-
endpointHint: endpointHintForSection(def)
|
|
7394
|
-
});
|
|
7395
|
-
console.log(JSON.stringify(summary));
|
|
7396
|
-
return;
|
|
7397
|
-
}
|
|
7398
|
-
if (def.name === "materials") {
|
|
7399
|
-
const m = payload;
|
|
7400
|
-
const iLen = Array.isArray(m.images) ? m.images.length : 0;
|
|
7401
|
-
const vLen = Array.isArray(m.videos) ? m.videos.length : 0;
|
|
7402
|
-
console.log(
|
|
7403
|
-
`
|
|
7404
|
-
\u2705 google-analysis materials \u8D26\u6237 ${id}
|
|
7405
|
-
\u56FE\u7247\u7D20\u6750\uFF1A${iLen} \u6761\uFF0C\u89C6\u9891\u7D20\u6750\uFF1A${vLen} \u6761\uFF08\u5B8C\u6574\u6570\u636E\u8BF7\u52A0 --json-out <\u76EE\u5F55>\uFF09
|
|
7406
|
-
`
|
|
7407
|
-
);
|
|
7408
|
-
return;
|
|
7409
|
-
}
|
|
7410
|
-
console.log(
|
|
7411
|
-
`
|
|
7412
|
-
\u2705 google-analysis ${def.name} \u8D26\u6237 ${id}
|
|
7413
|
-
${summarizeHuman(def.name, payload)}
|
|
7414
|
-
`
|
|
7415
|
-
);
|
|
7416
|
-
} catch (err) {
|
|
7417
|
-
console.error(`
|
|
7418
|
-
\u274C \u8BF7\u6C42\u5931\u8D25\uFF1A${err instanceof Error ? err.message : String(err)}
|
|
7419
|
-
`);
|
|
7420
|
-
process.exit(1);
|
|
7421
|
-
}
|
|
7422
|
-
}
|
|
7423
7369
|
function resolveSectionList(sections, exclude) {
|
|
7424
7370
|
const allNames = SECTIONS.map((s) => s.name);
|
|
7425
7371
|
const splitClean = (s) => (s ?? "").split(",").map((x) => x.trim()).filter(Boolean);
|
|
@@ -7523,13 +7469,15 @@ async function runAllSections(opts) {
|
|
|
7523
7469
|
if (failed > 0) process.exit(2);
|
|
7524
7470
|
}
|
|
7525
7471
|
function registerGoogleAnalysisCommands(program2) {
|
|
7526
|
-
|
|
7527
|
-
|
|
7528
|
-
|
|
7529
|
-
).requiredOption("-a, --account <id>", "Google mediaCustomerId").requiredOption(
|
|
7472
|
+
program2.command("google-analysis").description(
|
|
7473
|
+
"Google \u8D26\u6237\u5206\u6790\uFF08googleApiUrl\uFF09\uFF1A\u5355\u8FDB\u7A0B\u6279\u91CF\u62C9\u53D6\u4E00\u4E2A\u6216\u591A\u4E2A\u7EF4\u5EA6\uFF0C\u81EA\u52A8\u590D\u7528 keep-alive \u8FDE\u63A5"
|
|
7474
|
+
).argument("[legacy-section]", "\uFF08\u5DF2\u5E9F\u5F03\uFF09\u5386\u53F2\u7684\u5355\u7EF4\u5EA6\u5B50\u547D\u4EE4\u540D\uFF0C\u8BF7\u6539\u7528 --sections <name>").requiredOption("-a, --account <id>", "Google mediaCustomerId").requiredOption(
|
|
7530
7475
|
"--json-out <dir>",
|
|
7531
|
-
"\u7ED3\u679C\u843D\u76D8\u76EE\u5F55\uFF1B\u6BCF\
|
|
7532
|
-
).option("-t, --token <token>", "Auth Token").option(
|
|
7476
|
+
"\u7ED3\u679C\u843D\u76D8\u76EE\u5F55\uFF1B\u6BCF\u7EF4\u5EA6\u4E00\u4E2A <section>-<accountId>.json\uFF0C\u4E0E manifest-<accountId>.json \u540C\u7EA7"
|
|
7477
|
+
).option("-t, --token <token>", "Auth Token").option(
|
|
7478
|
+
"--start <date>",
|
|
7479
|
+
"\u5F00\u59CB\u65E5\u671F YYYY-MM-DD\uFF08range \u7C7B\u7EF4\u5EA6\u751F\u6548\uFF1B\u7701\u7565=\u8FD1 7 \u5929\u622A\u81F3\u6628\u5929\uFF1B\u4E0E --end \u540C\u4F20\u6216\u540C\u7701\uFF09"
|
|
7480
|
+
).option("--end <date>", "\u7ED3\u675F\u65E5\u671F YYYY-MM-DD").option(
|
|
7533
7481
|
"--sections <list>",
|
|
7534
7482
|
"\u4EC5\u6267\u884C\u6307\u5B9A\u7EF4\u5EA6\uFF08\u9017\u53F7\u5206\u9694\uFF09\uFF0C\u5982 overview,keywords,ads\uFF1B\u7701\u7565=\u5168\u90E8 21 \u4E2A"
|
|
7535
7483
|
).option(
|
|
@@ -7537,35 +7485,48 @@ function registerGoogleAnalysisCommands(program2) {
|
|
|
7537
7485
|
"\u6392\u9664\u6307\u5B9A\u7EF4\u5EA6\uFF08\u9017\u53F7\u5206\u9694\uFF09\uFF0C\u5982 materials,gold-account\uFF1B\u4E0E --sections \u53EF\u53E0\u52A0"
|
|
7538
7486
|
).option(
|
|
7539
7487
|
"--concurrency <n>",
|
|
7540
|
-
"\u5E76\u53D1\u6570\uFF0C\u9ED8\u8BA4 5\uFF1B\u4E0A\u9650 16\uFF08\u4E0E http-raw maxSockets \u5BF9\u9F50\uFF09",
|
|
7488
|
+
"\u5E76\u53D1\u6570\uFF0C\u9ED8\u8BA4 5\uFF1B\u4E0A\u9650 16\uFF08\u4E0E http-raw maxSockets \u5BF9\u9F50\uFF09\uFF1B\u8D26\u6237\u5927\u6216\u7F51\u7EDC\u6162\u65F6\u8C03\u5C0F",
|
|
7541
7489
|
(v) => parseInt(v, 10)
|
|
7542
|
-
).option("--limit <n>", "keywords/search-terms \u7684\u6761\u6570\u4E0A\u9650", (v) => parseInt(v, 10)).option("--no-order-by-cost", "
|
|
7543
|
-
|
|
7544
|
-
|
|
7545
|
-
|
|
7546
|
-
|
|
7547
|
-
|
|
7548
|
-
|
|
7549
|
-
|
|
7550
|
-
|
|
7551
|
-
|
|
7552
|
-
|
|
7553
|
-
|
|
7554
|
-
|
|
7555
|
-
|
|
7556
|
-
|
|
7557
|
-
|
|
7558
|
-
|
|
7559
|
-
|
|
7490
|
+
).option("--limit <n>", "\u900F\u4F20\u7ED9 keywords / search-terms \u7EF4\u5EA6\u7684\u6761\u6570\u4E0A\u9650", (v) => parseInt(v, 10)).option("--no-order-by-cost", "\u900F\u4F20\uFF1Akeywords / search-terms \u4E0D\u6309\u6D88\u8017\u6392\u5E8F", false).option(
|
|
7491
|
+
"--level <level>",
|
|
7492
|
+
"\u900F\u4F20\u7ED9 extensions \u7EF4\u5EA6\u7684 level \u8FC7\u6EE4\uFF1AAccount | Campaign | Ad Group"
|
|
7493
|
+
).option(
|
|
7494
|
+
"--audience-type <type>",
|
|
7495
|
+
"\u900F\u4F20\u7ED9 audience \u7EF4\u5EA6\u7684 audienceTypeFilter\uFF1ASystemDefined | UserDefined"
|
|
7496
|
+
).option("--verbose", "\u8BE6\u7EC6\u9519\u8BEF\u4FE1\u606F", false).addHelpText(
|
|
7497
|
+
"after",
|
|
7498
|
+
[
|
|
7499
|
+
"",
|
|
7500
|
+
"\u53EF\u7528\u7EF4\u5EA6\uFF0821 \u4E2A\uFF0C\u4E0E --sections / --exclude \u53D6\u503C\u4E00\u81F4\uFF09\uFF1A",
|
|
7501
|
+
...SECTIONS.map((s) => ` ${s.name.padEnd(20)} ${s.description}`),
|
|
7502
|
+
"",
|
|
7503
|
+
"\u793A\u4F8B\uFF1A",
|
|
7504
|
+
" # \u62C9\u5168\u90E8 21 \u4E2A\u7EF4\u5EA6",
|
|
7505
|
+
" siluzan-tso google-analysis -a <mediaCustomerId> --json-out ./snap",
|
|
7506
|
+
"",
|
|
7507
|
+
" # \u4EC5\u62C9\u5355\u4E2A\u7EF4\u5EA6\uFF08\u66FF\u4EE3\u5386\u53F2\u7684 google-analysis overview ...\uFF09",
|
|
7508
|
+
" siluzan-tso google-analysis -a <mediaCustomerId> --sections overview --json-out ./snap",
|
|
7509
|
+
"",
|
|
7510
|
+
" # \u4EC5\u62C9\u62A5\u544A\u9700\u8981\u7684\u5B50\u96C6",
|
|
7511
|
+
" siluzan-tso google-analysis -a <mediaCustomerId> --start 2026-04-01 --end 2026-04-30 \\",
|
|
7512
|
+
" --sections overview,daily-metrics,campaigns,devices,geographic,keywords --json-out ./snap"
|
|
7513
|
+
].join("\n")
|
|
7514
|
+
).action(async (legacySection, opts) => {
|
|
7515
|
+
if (legacySection) {
|
|
7516
|
+
const sectionNames = SECTIONS.map((s) => s.name);
|
|
7517
|
+
const isKnown = sectionNames.includes(legacySection);
|
|
7518
|
+
const fixHint = isKnown ? ` siluzan-tso google-analysis -a ${opts.account ?? "<id>"} --sections ${legacySection} --json-out <dir>` : ` \u672A\u77E5\u7EF4\u5EA6\u540D"${legacySection}"\u3002\u53EF\u9009\u7EF4\u5EA6\uFF1A${sectionNames.join(", ")}`;
|
|
7519
|
+
console.error(
|
|
7520
|
+
`
|
|
7521
|
+
\u274C google-analysis \u5DF2\u4E0D\u518D\u652F\u6301\u5355\u7EF4\u5EA6\u5B50\u547D\u4EE4\uFF08\u66FE\u7ECF\u7684 \`google-analysis ${legacySection} ...\` \u7528\u6CD5\u5DF2\u5220\u9664\uFF09\u3002
|
|
7522
|
+
\u73B0\u5728\u6240\u6709\u7EF4\u5EA6\u90FD\u901A\u8FC7 --sections \u9009\u53D6\uFF0C\u5355\u7EF4\u5EA6\u7B49\u4EF7\u5199\u6CD5\uFF1A
|
|
7523
|
+
${fixHint}
|
|
7524
|
+
`
|
|
7560
7525
|
);
|
|
7526
|
+
process.exit(1);
|
|
7561
7527
|
}
|
|
7562
|
-
|
|
7563
|
-
|
|
7564
|
-
}
|
|
7565
|
-
cmd.action(async (opts) => {
|
|
7566
|
-
await runOneSection(def, opts);
|
|
7567
|
-
});
|
|
7568
|
-
}
|
|
7528
|
+
await runAllSections(opts);
|
|
7529
|
+
});
|
|
7569
7530
|
}
|
|
7570
7531
|
|
|
7571
7532
|
// src/commands/report-tiktok-analysis.ts
|