siluzan-tso-cli 1.1.58-beta.4 → 1.1.58
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 -2
- package/dist/index.js +72 -47
- package/dist/skill/_meta.json +2 -2
- package/dist/skill/references/accounts/accounts-list.md +1 -1
- package/dist/skill/references/accounts/accounts-permissions.md +2 -2
- package/dist/skill/references/accounts/finance.md +1 -1
- package/dist/skill/references/accounts/open-account-by-media.md +1 -1
- package/dist/skill/references/accounts/open-account-google-ui.md +1 -1
- package/dist/skill/references/analytics/keyword-planner-workflows.md +9 -9
- package/dist/skill/references/analytics/rag.md +1 -1
- package/dist/skill/references/analytics/reporting.md +5 -5
- package/dist/skill/references/core/intent-routing.md +1 -1
- package/dist/skill/references/core/setup.md +5 -5
- package/dist/skill/references/core/workflows.md +2 -2
- package/dist/skill/references/google-ads/google-ads-read.md +1 -1
- package/dist/skill/references/google-ads/google-ads-write.md +3 -3
- package/dist/skill/references/google-ads/google-ads.md +1 -1
- package/dist/skill/references/misc/tso-home.md +2 -2
- package/dist/skill/scripts/install.ps1 +3 -3
- package/dist/skill/scripts/install.sh +3 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -43,7 +43,7 @@ HTML 报告模板外部资源:**ECharts** 统一使用 `https://staticpn.siluz
|
|
|
43
43
|
在**用户的目标项目根目录**执行(根据用户使用的助手选择 `--ai`):
|
|
44
44
|
|
|
45
45
|
```bash
|
|
46
|
-
npm install -g siluzan-tso-cli
|
|
46
|
+
npm install -g siluzan-tso-cli
|
|
47
47
|
siluzan-tso init --ai cursor # 写入 Cursor(默认)
|
|
48
48
|
siluzan-tso init --ai cursor,claude # 同时写入多个平台
|
|
49
49
|
siluzan-tso init --ai all # 写入所有支持的平台
|
|
@@ -51,7 +51,6 @@ siluzan-tso init -d /path/to/skills # 写入自定义目录
|
|
|
51
51
|
siluzan-tso init --force # 强制覆盖已存在文件
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
-
> **注意**:当前为测试版(1.1.58-beta.4),供内部测试使用。正式发布后安装命令将改为 `npm install -g siluzan-tso-cli`。
|
|
55
54
|
|
|
56
55
|
| 助手 | 建议 `--ai` |
|
|
57
56
|
| ----------------------- | ------------------------------------ |
|
package/dist/index.js
CHANGED
|
@@ -4049,7 +4049,7 @@ var DEFAULT_API_BASE;
|
|
|
4049
4049
|
var init_defaults = __esm({
|
|
4050
4050
|
"src/config/defaults.ts"() {
|
|
4051
4051
|
"use strict";
|
|
4052
|
-
DEFAULT_API_BASE = "https://tso-api
|
|
4052
|
+
DEFAULT_API_BASE = "https://tso-api.siluzan.com";
|
|
4053
4053
|
}
|
|
4054
4054
|
});
|
|
4055
4055
|
|
|
@@ -114282,6 +114282,12 @@ function campaignEditPatchPairs(input) {
|
|
|
114282
114282
|
if (input.manualCpcEnhanced !== void 0) {
|
|
114283
114283
|
pairs.push(["manualCpc_EnhancedCpcEnabled", input.manualCpcEnhanced]);
|
|
114284
114284
|
}
|
|
114285
|
+
if (input.targetSearchNetwork !== void 0) {
|
|
114286
|
+
pairs.push(["targetSearchNetwork", input.targetSearchNetwork]);
|
|
114287
|
+
}
|
|
114288
|
+
if (input.targetContentNetwork !== void 0) {
|
|
114289
|
+
pairs.push(["targetContentNetwork", input.targetContentNetwork]);
|
|
114290
|
+
}
|
|
114285
114291
|
return pairs;
|
|
114286
114292
|
}
|
|
114287
114293
|
function campaignStatusPatchPairs(status) {
|
|
@@ -117160,10 +117166,11 @@ async function runAdCampaignEdit(opts) {
|
|
|
117160
117166
|
targetSpendBidCeilingCents: opts.targetSpendBidCeiling !== void 0 ? toCentAmount(opts.targetSpendBidCeiling) : void 0,
|
|
117161
117167
|
targetCpaCents: opts.targetCpa !== void 0 ? toCentAmount(opts.targetCpa) : void 0,
|
|
117162
117168
|
targetRoas: opts.targetRoas,
|
|
117163
|
-
manualCpcEnhanced: opts.manualCpcEnhanced
|
|
117169
|
+
manualCpcEnhanced: opts.manualCpcEnhanced,
|
|
117170
|
+
targetSearchNetwork: opts.targetSearchNetwork,
|
|
117171
|
+
targetContentNetwork: opts.targetContentNetwork
|
|
117164
117172
|
});
|
|
117165
|
-
|
|
117166
|
-
if (patchPairs.length === 0 && !wantsNetwork) {
|
|
117173
|
+
if (patchPairs.length === 0) {
|
|
117167
117174
|
console.error("\n\u274C \u8BF7\u81F3\u5C11\u6307\u5B9A\u4E00\u4E2A\u4FEE\u6539\u9879\uFF08--name / --budget / --bidding / \u2026\uFF09\n");
|
|
117168
117175
|
process.exit(1);
|
|
117169
117176
|
}
|
|
@@ -117201,39 +117208,6 @@ async function runAdCampaignEdit(opts) {
|
|
|
117201
117208
|
return;
|
|
117202
117209
|
}
|
|
117203
117210
|
}
|
|
117204
|
-
if (wantsNetwork) {
|
|
117205
|
-
try {
|
|
117206
|
-
const fresh = await fetchCampaignRecord(detailUrl, config, opts.verbose);
|
|
117207
|
-
const networkBody = { ...fresh };
|
|
117208
|
-
if (opts.targetSearchNetwork !== void 0) {
|
|
117209
|
-
networkBody["targetSearchNetwork"] = opts.targetSearchNetwork;
|
|
117210
|
-
}
|
|
117211
|
-
if (opts.targetContentNetwork !== void 0) {
|
|
117212
|
-
networkBody["targetContentNetwork"] = opts.targetContentNetwork;
|
|
117213
|
-
}
|
|
117214
|
-
await apiFetch2(
|
|
117215
|
-
detailUrl,
|
|
117216
|
-
config,
|
|
117217
|
-
{ method: "PUT", body: JSON.stringify(networkBody) },
|
|
117218
|
-
opts.verbose
|
|
117219
|
-
);
|
|
117220
|
-
} catch (err) {
|
|
117221
|
-
await reportFailedCampaignPut({
|
|
117222
|
-
err,
|
|
117223
|
-
detailUrl,
|
|
117224
|
-
config,
|
|
117225
|
-
verbose: opts.verbose,
|
|
117226
|
-
budgetCentsBefore: readCampaignBudgetCents(campaign),
|
|
117227
|
-
jsonOut: opts.jsonOut,
|
|
117228
|
-
account: opts.account,
|
|
117229
|
-
id: opts.id,
|
|
117230
|
-
section: "ad-campaign-edit",
|
|
117231
|
-
commandLabel: "ad campaign-edit",
|
|
117232
|
-
failureLabel: "\u7F16\u8F91\u5E7F\u544A\u7CFB\u5217\u5931\u8D25"
|
|
117233
|
-
});
|
|
117234
|
-
return;
|
|
117235
|
-
}
|
|
117236
|
-
}
|
|
117237
117211
|
const parts = [];
|
|
117238
117212
|
if (opts.name !== void 0) parts.push(`\u540D\u79F0\u2192${opts.name}`);
|
|
117239
117213
|
if (opts.budget !== void 0) parts.push(`\u9884\u7B97\u2192${opts.budget}`);
|
|
@@ -125591,7 +125565,7 @@ function register21(program2) {
|
|
|
125591
125565
|
});
|
|
125592
125566
|
});
|
|
125593
125567
|
adCmd.command("campaign-edit").description(
|
|
125594
|
-
"\u7F16\u8F91\u641C\u7D22\u5E7F\u544A\u7CFB\u5217\u3002\u540D\u79F0
|
|
125568
|
+
"\u7F16\u8F91\u641C\u7D22\u5E7F\u544A\u7CFB\u5217\u3002\u540D\u79F0\u3001\u9884\u7B97\u3001\u51FA\u4EF7\u3001\u6295\u653E\u7F51\u7EDC\u90FD\u8D70\u5B57\u6BB5\u7EA7 PATCH\u3002\u81F3\u5C11\u4F20\u4E00\u4E2A\u4FEE\u6539\u9879"
|
|
125595
125569
|
).requiredOption("-a, --account <id>", "Google \u8D26\u6237 mediaCustomerId").requiredOption("--id <campaignId>", "\u5E7F\u544A\u7CFB\u5217 ID").option("--name <name>", "\u65B0\u540D\u79F0").option(
|
|
125596
125570
|
"--budget <amount>",
|
|
125597
125571
|
"\u65B0\u9884\u7B97\uFF0C\u4E3B\u5E01\u79CD\u91D1\u989D\uFF08\u5982 100 \u8868\u793A \xA5100\uFF1B\u652F\u6301\u5C0F\u6570\uFF1BCLI \u5185\u90E8\u81EA\u52A8 \xD7100 \u5199\u5165\u300C\u5206\u300D\u5B57\u6BB5\uFF09",
|
|
@@ -125613,9 +125587,13 @@ function register21(program2) {
|
|
|
125613
125587
|
(v) => v === "true"
|
|
125614
125588
|
).option(
|
|
125615
125589
|
"--search-network <bool>",
|
|
125616
|
-
"\
|
|
125590
|
+
"\u641C\u7D22\u5408\u4F5C\u4F19\u4F34\uFF1Atrue | false\u3002\u5173\u95ED\u4F20 false",
|
|
125617
125591
|
(v) => v === "true"
|
|
125618
|
-
).option(
|
|
125592
|
+
).option(
|
|
125593
|
+
"--content-network <bool>",
|
|
125594
|
+
"\u5C55\u793A\u7F51\u7EDC\u6269\u5C55\uFF1Atrue | false\u3002\u5173\u95ED\u4F20 false",
|
|
125595
|
+
(v) => v === "true"
|
|
125596
|
+
).option("--json-out <path>", "\u843D\u76D8\u6838\u9A8C\u7ED3\u679C\uFF08writeScope=search-field-patch\uFF09").option("-t, --token <token>", "Auth Token").option("--verbose", "\u8BE6\u7EC6\u9519\u8BEF\u4FE1\u606F", false).action(
|
|
125619
125597
|
async (opts) => {
|
|
125620
125598
|
await runAdCampaignEdit({
|
|
125621
125599
|
token: opts.token,
|
|
@@ -129143,6 +129121,45 @@ function annotateKeywordSuggestWithAccountPresence(items3, accountNormSet) {
|
|
|
129143
129121
|
}
|
|
129144
129122
|
|
|
129145
129123
|
// src/commands/keyword-geo.ts
|
|
129124
|
+
var KNOWN_GEO_LABELS = {
|
|
129125
|
+
2840: "\u7F8E\u56FD",
|
|
129126
|
+
2156: "\u4E2D\u56FD",
|
|
129127
|
+
2826: "\u82F1\u56FD"
|
|
129128
|
+
};
|
|
129129
|
+
function geoLabel(id) {
|
|
129130
|
+
const name2 = KNOWN_GEO_LABELS[id];
|
|
129131
|
+
return name2 ? `${name2}\uFF08${id}\uFF09` : String(id);
|
|
129132
|
+
}
|
|
129133
|
+
function describeKeywordTargetMarket(ids) {
|
|
129134
|
+
const geoTargetConstantIds = [...new Set(ids)];
|
|
129135
|
+
if (geoTargetConstantIds.length === 0) {
|
|
129136
|
+
return {
|
|
129137
|
+
geoTargetConstantIds,
|
|
129138
|
+
label: "\u672A\u9650\u5B9A\u56FD\u5BB6",
|
|
129139
|
+
unspecified: true,
|
|
129140
|
+
aggregated: false,
|
|
129141
|
+
note: "\u8FD9\u6B21\u6CA1\u6709 --geo\u3002\u6708\u641C\u7D22\u91CF\u3001CPC\u3001\u7ADE\u4E89\u5EA6\u672A\u6309\u56FD\u5BB6\u9650\u5B9A\uFF0C\u4E0D\u8981\u5199\u6210\u67D0\u4E00\u76EE\u6807\u5E02\u573A\uFF0C\u4E5F\u4E0D\u8981\u548C\u89C4\u5212\u5E08\u91CC\u9009\u4E86\u300C\u5168\u7403\u300D\u6216\u67D0\u4E2A\u56FD\u5BB6\u7684\u6570\u5B57\u5BF9\u6BD4\u3002"
|
|
129142
|
+
};
|
|
129143
|
+
}
|
|
129144
|
+
if (geoTargetConstantIds.length === 1) {
|
|
129145
|
+
const label3 = geoLabel(geoTargetConstantIds[0]);
|
|
129146
|
+
return {
|
|
129147
|
+
geoTargetConstantIds,
|
|
129148
|
+
label: label3,
|
|
129149
|
+
unspecified: false,
|
|
129150
|
+
aggregated: false,
|
|
129151
|
+
note: `\u6708\u641C\u7D22\u91CF\u3001CPC\u3001\u7ADE\u4E89\u5EA6\u53EA\u5C5E\u4E8E\u76EE\u6807\u5E02\u573A ${label3}\uFF0C\u4E0D\u662F\u5168\u7403\u3002\u5B98\u65B9\u89C4\u5212\u5E08\u82E5\u9009\u7684\u662F\u5168\u7403\u6216\u522B\u7684\u56FD\u5BB6\uFF0C\u6570\u5B57\u4E0D\u4F1A\u4E00\u81F4\u3002`
|
|
129152
|
+
};
|
|
129153
|
+
}
|
|
129154
|
+
const label2 = geoTargetConstantIds.map(geoLabel).join("\u3001");
|
|
129155
|
+
return {
|
|
129156
|
+
geoTargetConstantIds,
|
|
129157
|
+
label: `${label2}\uFF08\u6C47\u603B\uFF09`,
|
|
129158
|
+
unspecified: false,
|
|
129159
|
+
aggregated: true,
|
|
129160
|
+
note: `\u6708\u641C\u7D22\u91CF\u3001CPC\u3001\u7ADE\u4E89\u5EA6\u662F ${label2} \u52A0\u5728\u4E00\u8D77\u7684\u6C47\u603B\uFF0C\u4E0D\u662F\u6BCF\u4E2A\u56FD\u5BB6\u4E00\u884C\uFF0C\u4E5F\u4E0D\u662F\u5168\u7403\u3002`
|
|
129161
|
+
};
|
|
129162
|
+
}
|
|
129146
129163
|
function parseGeoTargetConstantIds(raw) {
|
|
129147
129164
|
if (!raw?.trim()) return [];
|
|
129148
129165
|
const ids = [];
|
|
@@ -129218,7 +129235,8 @@ function buildKeywordSuggestJsonPayload(items3, opts) {
|
|
|
129218
129235
|
const n = normalized.length;
|
|
129219
129236
|
return {
|
|
129220
129237
|
...wrapListJson({ page: 1, pageSize: Math.max(n, 1), total: n, items: normalized }),
|
|
129221
|
-
bidAmountCurrency: currency
|
|
129238
|
+
bidAmountCurrency: currency,
|
|
129239
|
+
targetMarket: describeKeywordTargetMarket(opts.geoTargetConstantIds ?? [])
|
|
129222
129240
|
};
|
|
129223
129241
|
}
|
|
129224
129242
|
async function fetchUrlKeywords(url, keywords, verbose) {
|
|
@@ -129319,7 +129337,7 @@ Google Ads \u56FD\u5BB6/\u5730\u533A\u5E38\u91CF\uFF08\u5171 ${n} \u6761\uFF09
|
|
|
129319
129337
|
]
|
|
129320
129338
|
);
|
|
129321
129339
|
console.log(
|
|
129322
|
-
'\n\u62D3\u8BCD\u65F6\u6307\u5B9A\u5730\u533A\uFF1Asiluzan-tso keyword -k "\u79CD\u5B50" --geo <id>\n \u4F8B\uFF1A\u7F8E\u56FD=2840\uFF0C\u4E2D\u56FD=2826\n \u591A\u4E2A --geo \u4E3A\u6C47\u603B\u6570\u636E\uFF1B\u5206\u5E02\u573A\u5BF9\u6BD4\u8BF7\u591A\u6B21\u8C03\u7528\u3001\u6BCF\u6B21\u53EA\u4F20\u4E00\u4E2A id\n'
|
|
129340
|
+
'\n\u62D3\u8BCD\u65F6\u6307\u5B9A\u5730\u533A\uFF1Asiluzan-tso keyword -k "\u79CD\u5B50" --geo <id>\n \u4F8B\uFF1A\u7F8E\u56FD=2840\uFF0C\u4E2D\u56FD=2156\uFF0C\u82F1\u56FD=2826\n \u591A\u4E2A --geo \u4E3A\u6C47\u603B\u6570\u636E\uFF1B\u5206\u5E02\u573A\u5BF9\u6BD4\u8BF7\u591A\u6B21\u8C03\u7528\u3001\u6BCF\u6B21\u53EA\u4F20\u4E00\u4E2A id\n'
|
|
129323
129341
|
);
|
|
129324
129342
|
}
|
|
129325
129343
|
async function runKeywordSuggest(opts) {
|
|
@@ -129433,8 +129451,13 @@ async function runKeywordSuggest(opts) {
|
|
|
129433
129451
|
}
|
|
129434
129452
|
}
|
|
129435
129453
|
const n = items3.length;
|
|
129436
|
-
const
|
|
129454
|
+
const targetMarket = describeKeywordTargetMarket(geoTargetConstantIds);
|
|
129455
|
+
const kwPayload = buildKeywordSuggestJsonPayload(items3, {
|
|
129456
|
+
bidAmountCurrency,
|
|
129457
|
+
geoTargetConstantIds
|
|
129458
|
+
});
|
|
129437
129459
|
const displayItems = kwPayload.items;
|
|
129460
|
+
console.error(` [keyword] \u76EE\u6807\u5E02\u573A\uFF1A${targetMarket.label}\u3002${targetMarket.note}`);
|
|
129438
129461
|
if (await emitCliJsonOrSnapshot(opts, {
|
|
129439
129462
|
section: "keyword-suggest",
|
|
129440
129463
|
commandLabel: "keyword",
|
|
@@ -129442,9 +129465,11 @@ async function runKeywordSuggest(opts) {
|
|
|
129442
129465
|
})) {
|
|
129443
129466
|
return;
|
|
129444
129467
|
}
|
|
129445
|
-
console.log(
|
|
129446
|
-
|
|
129447
|
-
|
|
129468
|
+
console.log(
|
|
129469
|
+
`
|
|
129470
|
+
\u5173\u952E\u5B57\u63A8\u8350\uFF08\u76EE\u6807\u5E02\u573A\uFF1A${targetMarket.label}\uFF1B\u7B2C 1 \u9875\uFF0C\u672C\u9875 ${items3.length} \u6761\uFF0C\u5171 ${items3.length} \u6761\uFF09
|
|
129471
|
+
`
|
|
129472
|
+
);
|
|
129448
129473
|
if (items3.length === 0) {
|
|
129449
129474
|
console.log(" \u6682\u65E0\u63A8\u8350\u5173\u952E\u8BCD\u3002\n");
|
|
129450
129475
|
return;
|
|
@@ -129454,7 +129479,7 @@ async function runKeywordSuggest(opts) {
|
|
|
129454
129479
|
const cols = [
|
|
129455
129480
|
{ key: "keyword", header: "\u5173\u952E\u8BCD" },
|
|
129456
129481
|
...accountId ? [{ key: "alreadyInAccount", header: "\u5DF2\u5728\u8D26\u6237\u4E2D" }] : [],
|
|
129457
|
-
{ key: "montlySearch", header:
|
|
129482
|
+
{ key: "montlySearch", header: `\u6708\u5747\u641C\u7D22\xB7${targetMarket.label}` },
|
|
129458
129483
|
{ key: "cpcMain", header: `\u5E73\u5747CPC(${cur})` },
|
|
129459
129484
|
{ key: "bidRangeMain", header: `\u9875\u9996\u51FA\u4EF7(${cur})` },
|
|
129460
129485
|
{ key: "competition", header: "\u7ADE\u4E89\u5EA6" }
|
package/dist/skill/_meta.json
CHANGED
|
@@ -170,7 +170,7 @@ siluzan-tso account-history --start 2026-03-01 --end 2026-03-31 --json-out ./sna
|
|
|
170
170
|
| 状态 | 含义 | 下一步操作 |
|
|
171
171
|
| ---------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
172
172
|
| `Pending` | 审核中 | 等待,可反复运行此命令轮询;审核周期因媒体而异 |
|
|
173
|
-
| `Approved` | 审核通过 | 运行 `list-accounts -m <媒体>` 确认账户已出现;引导用户充值激活(`config show` 取 `webUrl`,按 `finance.md` 打开对应媒体充值页;例如 Google 为 `https://www
|
|
173
|
+
| `Approved` | 审核通过 | 运行 `list-accounts -m <媒体>` 确认账户已出现;引导用户充值激活(`config show` 取 `webUrl`,按 `finance.md` 打开对应媒体充值页;例如 Google 为 `https://www.siluzan.com/v3/foreign_trade/tso/recharge/pay?mediaType=Google`;Yandex 当前没有对应充值界面) |
|
|
174
174
|
| `Rejected` | 被拒 | 查看 `--json-out` 落盘中的 `reason` 字段了解拒绝原因;修改资料后重新提交;若原因不明,引导用户联系丝路赞客服 |
|
|
175
175
|
|
|
176
176
|
---
|
|
@@ -490,7 +490,7 @@ siluzan-tso account email-deauth -c <mediaCustomerId> --invitation-id <id> --res
|
|
|
490
490
|
|
|
491
491
|
| 功能 | 媒体 | 网页路径 |
|
|
492
492
|
| --------------------------------------- | ------ | ------------------------------------------------- |
|
|
493
|
-
| **账户激活**(邀请他人激活 / 充值激活) | Google | `https://www
|
|
493
|
+
| **账户激活**(邀请他人激活 / 充值激活) | Google | `https://www.siluzan.com/v3/foreign_trade/tso/manageAccounts` |
|
|
494
494
|
|
|
495
495
|
**Agent 建议话术**:
|
|
496
496
|
|
|
@@ -499,5 +499,5 @@ siluzan-tso account email-deauth -c <mediaCustomerId> --invitation-id <id> --res
|
|
|
499
499
|
siluzan-tso config show # 查看 webUrl 字段
|
|
500
500
|
|
|
501
501
|
# 账户激活(Google)→ 引导至账户管理页
|
|
502
|
-
# https://www
|
|
502
|
+
# https://www.siluzan.com/v3/foreign_trade/tso/manageAccounts
|
|
503
503
|
```
|
|
@@ -126,7 +126,7 @@ siluzan-tso config show
|
|
|
126
126
|
|
|
127
127
|
### 充值页链接(按媒体 × 类型)
|
|
128
128
|
|
|
129
|
-
链接模式:`https://www
|
|
129
|
+
链接模式:`https://www.siluzan.com/v3/foreign_trade/tso/recharge/<page>?mediaType=<mediaType>`;丝路赞钱包:`https://www.siluzan.com/v3/foreign_trade/tso/recharge/siluzanWallet`(无媒体参数)。
|
|
130
130
|
|
|
131
131
|
| 充值类型 | `<page>` | 支持媒体(`mediaType` 参数) |
|
|
132
132
|
| ------------------------- | --------------------- | ------------------------------------------- |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 各媒体开户
|
|
2
2
|
|
|
3
|
-
> 网页链接:`https://www
|
|
3
|
+
> 网页链接:`https://www.siluzan.com/v3/foreign_trade/tso/accountOpeningHistory?tso=%2Fv3umijs%2Ftso%2FaccountOpeningHistory`
|
|
4
4
|
> 多命令串联见 `references/core/workflows.md` § 流程一。
|
|
5
5
|
|
|
6
6
|
## Contents
|
|
@@ -65,7 +65,7 @@ siluzan-tso open-account google-wizard
|
|
|
65
65
|
|
|
66
66
|
```bash
|
|
67
67
|
siluzan-tso account-history -m Google
|
|
68
|
-
# 审核通过后:config show → https://www
|
|
68
|
+
# 审核通过后:config show → https://www.siluzan.com/v3/foreign_trade/tso/recharge/pay?mediaType=Google
|
|
69
69
|
```
|
|
70
70
|
|
|
71
71
|
---
|
|
@@ -101,7 +101,7 @@
|
|
|
101
101
|
- 按 `montlySearch` 过滤(如 1500–6000 视为「约 3000」区间);
|
|
102
102
|
- 按 `competition` / `competitionV2` 筛「中低」(LOW / MEDIUM 或数值阈值,以当次 outline 为准);
|
|
103
103
|
- 每个核心词保留 Top N(用户指定如 30 条);不足时扩大 `-k` 变体或放宽阈值并在说明中标注。
|
|
104
|
-
4. 交付 Markdown/表格:**英文关键词 | 中文翻译 |
|
|
104
|
+
4. 交付 Markdown/表格:**英文关键词 | 中文翻译 | 所属核心词 | 月搜索量 | 竞争度 | 目标市场**。目标市场用落盘 JSON 根上的 `targetMarket.label`(例如「美国(2840)」),表题写明 **月搜索量不是全球**。把 `targetMarket.note` 写进表头说明。首行仍注明 **Google Keyword Planner(`keywordidea/google`)**。用户拿官方规划师对数字时,先核对规划师选的是不是同一个国家;选「全球」或别的国家时数字本来就不会一致。
|
|
105
105
|
|
|
106
106
|
**禁止**:纯 WebSearch/WebFetch 输出带「月搜索量」的终稿;禁止跳过 `keyword` CLI。
|
|
107
107
|
|
|
@@ -109,7 +109,7 @@
|
|
|
109
109
|
|
|
110
110
|
## 指定拓词市场地区(geoTargetConstant)
|
|
111
111
|
|
|
112
|
-
Google Keyword Planner 的搜索量/CPC
|
|
112
|
+
Google Keyword Planner 的搜索量/CPC 与**目标国家/地区**相关,**不是全球**。指定地区:
|
|
113
113
|
|
|
114
114
|
1. **查国家 ID**:
|
|
115
115
|
```bash
|
|
@@ -121,26 +121,26 @@ Google Keyword Planner 的搜索量/CPC 与**目标国家/地区**相关。指
|
|
|
121
121
|
siluzan-tso keyword -k "pipe" --geo 2840 --json-out ./snap-kw-us
|
|
122
122
|
```
|
|
123
123
|
|
|
124
|
-
常见 ID
|
|
124
|
+
常见 ID(以 `keyword geo-list` 为准):美国 `2840`,中国 `2156`,英国 `2826`。`2826` 不是中国。
|
|
125
125
|
|
|
126
126
|
### 多地区 `--geo`:返回汇总数据,无法按地区拆分
|
|
127
127
|
|
|
128
|
-
`--geo` 可传多个 ID(逗号分隔,如 `--geo 2840,
|
|
128
|
+
`--geo` 可传多个 ID(逗号分隔,如 `--geo 2840,2156`),网关会把它们一并传给 `keywordidea/google?geoTargetConstantIds=...`。此时 Google Keyword Planner 返回的 `montlySearch`、CPC、竞争度等是**跨所传地区的汇总/合并口径**,**不是**「每个国家各一行」或 JSON 里带 `geoTargetConstantId` 分字段。
|
|
129
129
|
|
|
130
130
|
| 需求 | 做法 |
|
|
131
131
|
| ----------------------------------- | ------------------------------------------------------------------------------------------------------------- |
|
|
132
|
-
| 只要「美国+中国合在一起」的市场参考 | 一次调用:`--geo 2840,
|
|
132
|
+
| 只要「美国+中国合在一起」的市场参考 | 一次调用:`--geo 2840,2156` |
|
|
133
133
|
| 要对比美国 vs 中国各自搜索量/CPC | **多次调用**,每次 `--geo` **只传一个** ID,分别 `--json-out` 到不同目录(如 `./snap-kw-us`、`./snap-kw-cn`) |
|
|
134
134
|
|
|
135
|
-
**禁止**把 `--geo 2840,
|
|
135
|
+
**禁止**把 `--geo 2840,2156` 的单次落盘结果当成「美国一套、中国一套」两张表;报告里若写多市场对比,须注明数据来源为分次 `keyword` 调用。
|
|
136
136
|
|
|
137
137
|
```bash
|
|
138
138
|
# 正确:分市场各查一次
|
|
139
139
|
siluzan-tso keyword -k "pipe" --geo 2840 --json-out ./snap-kw-us
|
|
140
|
-
siluzan-tso keyword -k "pipe" --geo
|
|
140
|
+
siluzan-tso keyword -k "pipe" --geo 2156 --json-out ./snap-kw-cn
|
|
141
141
|
|
|
142
142
|
# 易误解:单次多 geo 只有汇总指标,无法在 items[] 内按国家拆开
|
|
143
|
-
siluzan-tso keyword -k "pipe" --geo 2840,
|
|
143
|
+
siluzan-tso keyword -k "pipe" --geo 2840,2156 --json-out ./snap-kw-merged
|
|
144
144
|
```
|
|
145
145
|
|
|
146
146
|
---
|
|
@@ -246,6 +246,6 @@ siluzan-tso keyword geo-list [--country-code <codes>] [--name-contains <text>] [
|
|
|
246
246
|
|
|
247
247
|
`--google-only`:只调 Google 推荐主接口(有 `-a` 为账户接口,无 `-a` 为 `keywordidea/google`),不叠加 `--url` 的网址拓词;**分支 B(仅 Google)必加**。
|
|
248
248
|
|
|
249
|
-
**返回字段**(与后端 `Samm.Core.Service.KeywordRecommendation`
|
|
249
|
+
**返回字段**(与后端 `Samm.Core.Service.KeywordRecommendation` 对齐):根级 **`targetMarket`**(`label` 是给用户看的目标市场,如「美国(2840)」;没传 `--geo` 时为「未限定国家」;`note` 说明搜索量不是全球)。根级与每条 **`bidAmountCurrency`**(无账户=`USD`;有账户=`list-accounts` 的 `currencyCode`);`averageCpc` / `lowTopOfPageBid` / `highTopOfPageBid`(微元 ÷1,000,000,**与 `bidAmountCurrency` 一致**)。另有 `keyword` / `montlySearch` / `monthlySearchVolumes` / `competition` / `competitionV2` / `source` 等;**有 `-a` 时**每条多 **`alreadyInAccount`**(`0` | `1`)。交给用户的表必须带 `targetMarket.label`,并写明不是全球。
|
|
250
250
|
|
|
251
251
|
与只读账户关键词列表、否词 CRUD 的对照:查询见 **`google-ads-read.md`**,写入见 **`google-ads-write.md`**。
|
|
@@ -190,9 +190,9 @@ siluzan-tso report push receive-emails -m Google [--json-out ./snap]
|
|
|
190
190
|
|
|
191
191
|
| 媒体 | 报告类型 | URL 模板 |
|
|
192
192
|
| ------ | ---------------- | ----------------------------------------------------------- |
|
|
193
|
-
| Google | 日报(Daily) | `https://www
|
|
194
|
-
| Google | 小时报(Hourly) | `https://www
|
|
195
|
-
| TikTok | 日报 | `https://www
|
|
193
|
+
| Google | 日报(Daily) | `https://www.siluzan.com/media-report/publish/{entityId}?culture=zh-CN` |
|
|
194
|
+
| Google | 小时报(Hourly) | `https://www.siluzan.com/media-report/hour/{entityId}?culture=zh-CN` |
|
|
195
|
+
| TikTok | 日报 | `https://www.siluzan.com/media-report/publish/{entityId}?culture=zh-CN` |
|
|
196
196
|
|
|
197
197
|
`entityId` 来自 `siluzan-tso report list --json-out ./snap` 中每条记录的 `entityId` 字段。
|
|
198
198
|
|
|
@@ -205,8 +205,8 @@ siluzan-tso report list -m Google --json-out ./snap
|
|
|
205
205
|
|
|
206
206
|
# 第二步:查看 webUrl
|
|
207
207
|
siluzan-tso config show
|
|
208
|
-
# webUrl: https://www
|
|
208
|
+
# webUrl: https://www.siluzan.com
|
|
209
209
|
|
|
210
210
|
# 第三步:拼接链接(Google 日报)
|
|
211
|
-
# https://www
|
|
211
|
+
# https://www.siluzan.com/media-report/publish/rpt_abc123?culture=zh-CN
|
|
212
212
|
```
|
|
@@ -115,7 +115,7 @@
|
|
|
115
115
|
1. **直接定工作流 W5** → Read `workflows.md` W5 + `analytics/keyword-planner-workflows.md`。
|
|
116
116
|
2. **必走 CLI**:`siluzan-tso keyword -k "种子1,种子2,..." [--url "<落地页>"] [--geo <id>] --google-only --json-out ./snap-kw`(要官方 Planner 指标时 **必加 `--google-only`**;多核心词 **分批** `-k`,避免单次 body 过大)。
|
|
117
117
|
3. **网址/文章**:可用 WebFetch 读页面 **仅归纳种子词与产品语境**;**月搜索量 / 竞争度 / CPC 只能来自 `keyword` 落盘 JSON**(字段 `montlySearch`、`competition`/`competitionV2`、`averageCpc` 等),脚本过滤(如「约 3000 搜索量、竞争中低」)后再交付表格。
|
|
118
|
-
4.
|
|
118
|
+
4. **交付列**(用户未指定时):英文关键词、中文翻译、所属核心词、月搜索量、竞争度、**目标市场**。目标市场抄落盘 JSON 的 `targetMarket.label`,表题写明 **不是全球**。表头注明 **数据来源:Google Keyword Planner(`keywordidea/google`)**。
|
|
119
119
|
|
|
120
120
|
### C.3 与 W3 / P8 / P9 区分
|
|
121
121
|
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
## 安装 CLI
|
|
11
11
|
|
|
12
12
|
```bash
|
|
13
|
-
npm install -g siluzan-tso-cli
|
|
13
|
+
npm install -g siluzan-tso-cli
|
|
14
14
|
```
|
|
15
15
|
|
|
16
16
|
---
|
|
@@ -64,7 +64,7 @@ siluzan-tso config set --api-key <Key> # 或 config 直接写入
|
|
|
64
64
|
siluzan-tso config set --token <Token> # 备用:设置 JWT Token
|
|
65
65
|
```
|
|
66
66
|
|
|
67
|
-
API Key 获取入口:`https://www
|
|
67
|
+
API Key 获取入口:`https://www.siluzan.com/v3/foreign_trade/settings/apiKeyManagement`
|
|
68
68
|
|
|
69
69
|
```bash
|
|
70
70
|
# 第 1 步:让用户报出手机号后,立刻发码(命令立即返回,不会等待输入)
|
|
@@ -127,9 +127,9 @@ siluzan-tso config show
|
|
|
127
127
|
|
|
128
128
|
```
|
|
129
129
|
构建环境 : production
|
|
130
|
-
apiBaseUrl : https://tso-api
|
|
131
|
-
googleApiUrl : https://googleapi
|
|
132
|
-
webUrl : https://www
|
|
130
|
+
apiBaseUrl : https://tso-api.siluzan.com
|
|
131
|
+
googleApiUrl : https://googleapi.mysiluzan.com
|
|
132
|
+
webUrl : https://www.siluzan.com
|
|
133
133
|
apiKey : abcd****1234
|
|
134
134
|
```
|
|
135
135
|
|
|
@@ -119,8 +119,8 @@
|
|
|
119
119
|
- **步骤**:
|
|
120
120
|
1. (可选)WebFetch 读用户 URL/文章 **仅归纳种子词**;或 RAG:`rag list --rag-only --json-out ./snap` → `rag query … --json-out ./snap`。
|
|
121
121
|
2. 拓词(**必 `--google-only --json-out`**):`keyword -k "种子1,种子2,..." [--url "<落地页>"] [--geo <id>] --google-only --json-out ./snap-kw`;**多核心词分批** `-k`(每批 3–8 词),避免单次过大。
|
|
122
|
-
3. 脚本读落盘 `items`(`montlySearch`/`averageCpc`/`competition`,币种见 `bidAmountCurrency
|
|
123
|
-
-
|
|
122
|
+
3. 脚本读落盘 `items`(`montlySearch`/`averageCpc`/`competition`,币种见 `bidAmountCurrency`)和根上的 **`targetMarket.label`** → 按用户阈值洗词(如搜索量≈3000、竞争中低)→ 去重/分组/截 Top N,标注 **数据来源:Google Keyword Planner**,并写明 **目标市场(不是全球)**。
|
|
123
|
+
- **产物**:表格列含英文词、中文翻译、所属核心词、月搜索量、竞争度、**目标市场**(`targetMarket.label`,并写明不是全球)。指标**仅**来自 CLI;联网/文章语境与 Planner 指标**分列标注**;账户内 `google-analysis keywords` 表现**不可**与市场侧拓词合并。完整 campaign 见 **W3**。
|
|
124
124
|
|
|
125
125
|
---
|
|
126
126
|
|
|
@@ -249,7 +249,7 @@ siluzan-tso keyword -k <搜索词> [-a <mediaCustomerId>] [--geo <geoTargetConst
|
|
|
249
249
|
siluzan-tso keyword geo-list [--country-code <US,CN,...>] [--name-contains <text>] [--json-out ./snap]
|
|
250
250
|
```
|
|
251
251
|
|
|
252
|
-
`--geo` 传多个 ID(如 `2840,
|
|
252
|
+
`keyword --json-out` 的根字段 **`targetMarket.label`** 是这次搜索量所属的目标市场(如「美国(2840)」)。没传 `--geo` 时为「未限定国家」。交给用户的表要带上这个市场,并写明 **不是全球**。`--geo` 传多个 ID(如 `2840,2156`)时,返回的搜索量/CPC/竞争度为**跨所传地区的汇总数据**,响应中**无**按地区拆分的字段。若要分别查看各市场指标,须**多次调用**且每次 `--geo` **只传一个** ID(详见 **`references/analytics/keyword-planner-workflows.md`**「多地区 `--geo`」)。
|
|
253
253
|
|
|
254
254
|
`--url` 触发网址拓词(`websitereco`)并合并进结果;与 `--google-only` 互斥(仅 Google Keyword Planner 时用后者)。`--include`/`--exclude` 为本地过滤。仅 Google、不联网搜索的 Agent 编排见 **`references/analytics/keyword-planner-workflows.md`**「分支 B」。
|
|
255
255
|
|
|
@@ -260,11 +260,11 @@ siluzan-tso ad campaign-edit -a <accountId> --id <campaignId> \
|
|
|
260
260
|
|
|
261
261
|
相对运算:先 `ad campaigns --json-out ./snap` 读 `budget`(已为主币种元)、`biddingStrategyTypeV2`,再传入。
|
|
262
262
|
|
|
263
|
-
`campaign-edit`
|
|
263
|
+
`campaign-edit` 的名称、预算、出价、投放网络,以及 `campaign-status`,走字段级 PATCH(`writeScope=search-field-patch`)。请求只带本次传入的字段,没传的字段保持原样。金额仍是主币种元,CLI ×100 写入网关「分」。`--search-network` / `--content-network` 传 `true` 或 `false`,关闭传 `false`,不能传空。`budgetShared=true` 时本命令直接拒绝 `--budget`,不会改共享预算。PMax 不要用本命令。
|
|
264
264
|
|
|
265
|
-
|
|
265
|
+
网关还支持开始/结束时间、地区类型、地区/语言/时段/否定 IP/设备的整表替换,以及动态搜索广告域名。CLI 还没有这些参数,不要自己拼 PUT 或 PATCH。
|
|
266
266
|
|
|
267
|
-
|
|
267
|
+
写完会再 GET:`verification=verified` 才表示对上了本次字段;没改预算但回读预算变了则是 `partial`;读不到是 `unknown`(再查 `ad campaigns`,不要当成没改成,也不要立刻重发)。请求失败时会再 GET 一次预算:金额相对提交前变了是 `partial`(退出码 0),读不到或无法对比是 `unknown`(退出码 0),都不要立刻重发;金额没变才是失败(退出码 1)。
|
|
268
268
|
|
|
269
269
|
> PMax / 部分智能系列类型 Google 可能拒绝切换出价策略;以 API 返回错误为准。已上线 PMax 用 `ad pmax-edit`,不要用本命令。
|
|
270
270
|
|
|
@@ -30,7 +30,7 @@ Meta / Facebook 线索广告走 **`meta-ad`(W13)**,**禁止**用本命令
|
|
|
30
30
|
## Gotchas
|
|
31
31
|
|
|
32
32
|
- **广告类型**:仅 Search + PMax;**不支持 Display**(见上文「支持的广告类型」)。
|
|
33
|
-
- **Search 改字段**:`campaign-status`、`campaign-edit`
|
|
33
|
+
- **Search 改字段**:`campaign-status`、`campaign-edit` 的名称/预算/出价/投放网络、`adgroup-status` / `adgroup-rename` / `adgroup-edit`、`keyword-status`、`keyword-edit` 的状态/出价/网址、`ad-status` / `ad-edit` 都是字段级 PATCH,只写本次参数。词面和匹配类型仍是批量 PUT。关闭搜索合作伙伴或展示网络传 `--search-network false` / `--content-network false`。PMax 用 `pmax-edit`,不要用 `campaign-edit`。
|
|
34
34
|
- **命令名**:系列列表是 `ad campaigns`(别名 `campaign-list`),**禁止** `ad-campaigns` / `campaign list`。`balance`/`stats` 须 `-m Google`。
|
|
35
35
|
- **Google 客户 ID(CID)带连字符**:UI / 用户口述常为 `123-456-7890`,平台 `mediaCustomerId` 与 Google 网关路径需要 `1234567890`。`ad campaigns` / `ad groups` / `ad list` 等 `-a` 与 JSON 顶层 `account` **可带连字符**(CLI 自动去掉)。若错误为 `HTTP 403:123-456-7890`(回显带横杠),先换纯数字重试,**禁止**据此直接判断 OAuth 过期或 `reauth`。
|
|
36
36
|
- **禁止臆测授权过期**:`ad *` / geo / 拉数出现 403/500 时,**禁止**对用户说「授权可能过期」。须核验 ID 后执行 `account check-access -a <mediaCustomerId>`,仅当 `reauth_required`(或与 `invalidOAuthToken=true` 交叉确认)才走重授权;无激活字段时禁止谈套餐。见 [`accounts-permissions.md`](../accounts/accounts-permissions.md)。
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
siluzan-tso config show # 取 webUrl
|
|
7
7
|
```
|
|
8
8
|
|
|
9
|
-
首页地址:`https://www
|
|
9
|
+
首页地址:`https://www.siluzan.com/v3/foreign_trade/tso/home`
|
|
10
10
|
|
|
11
11
|
---
|
|
12
12
|
|
|
@@ -25,7 +25,7 @@ siluzan-tso config show # 取 webUrl
|
|
|
25
25
|
|
|
26
26
|
## 推荐话术
|
|
27
27
|
|
|
28
|
-
1. **「和首页一样的总览」** → 打开 `https://www
|
|
28
|
+
1. **「和首页一样的总览」** → 打开 `https://www.siluzan.com/v3/foreign_trade/tso/home`。
|
|
29
29
|
2. **「某个 Google 账户昨天花了多少」** → `list-accounts -m Google` + `stats -m Google -a <id>`。
|
|
30
30
|
3. **「有待充值账户」** → 说明聚合数据在首页;CLI 可 `list-accounts` + `balance` 逐户排查,或引导充值页。
|
|
31
31
|
|
|
@@ -9,11 +9,11 @@ $ErrorActionPreference = 'Stop'
|
|
|
9
9
|
# -- Package info (injected at build time) ------------------------------------
|
|
10
10
|
$PKG_NAME = 'siluzan-tso-cli'
|
|
11
11
|
# PKG_VERSION 锁定到与本脚本同批构建产物一致的版本,避免与 dist/skill 错位
|
|
12
|
-
$PKG_VERSION = '1.1.58
|
|
12
|
+
$PKG_VERSION = '1.1.58'
|
|
13
13
|
$CLI_BIN = 'siluzan-tso'
|
|
14
14
|
$SKILL_LABEL = 'Siluzan TSO'
|
|
15
|
-
$INSTALL_CMD = 'npm install -g siluzan-tso-cli
|
|
16
|
-
$WEB_BASE = 'https://www
|
|
15
|
+
$INSTALL_CMD = 'npm install -g siluzan-tso-cli'
|
|
16
|
+
$WEB_BASE = 'https://www.siluzan.com'
|
|
17
17
|
|
|
18
18
|
# -- Constants ----------------------------------------------------------------
|
|
19
19
|
$NODE_MAJOR_MIN = 18
|
|
@@ -9,11 +9,11 @@ set -euo pipefail
|
|
|
9
9
|
# -- Package info (injected at build time) ------------------------------------
|
|
10
10
|
readonly PKG_NAME="siluzan-tso-cli"
|
|
11
11
|
# PKG_VERSION 锁定到与本脚本同批构建产物一致的版本,避免与 dist/skill 错位
|
|
12
|
-
readonly PKG_VERSION="1.1.58
|
|
12
|
+
readonly PKG_VERSION="1.1.58"
|
|
13
13
|
readonly CLI_BIN="siluzan-tso"
|
|
14
14
|
readonly SKILL_LABEL="Siluzan TSO"
|
|
15
|
-
readonly INSTALL_CMD="npm install -g siluzan-tso-cli
|
|
16
|
-
readonly WEB_BASE="https://www
|
|
15
|
+
readonly INSTALL_CMD="npm install -g siluzan-tso-cli"
|
|
16
|
+
readonly WEB_BASE="https://www.siluzan.com"
|
|
17
17
|
|
|
18
18
|
# -- Constants ----------------------------------------------------------------
|
|
19
19
|
readonly NODE_MAJOR_MIN=18
|