@clize/clize 0.26.1 → 0.28.0

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.
@@ -0,0 +1,595 @@
1
+ import { ClizeError } from "../lib/errors.js";
2
+ import { sha256hex } from "../lib/crypto.js";
3
+ import { DataForSeo, KEYWORDS_PER_CALL, normalizeHost, } from "../providers/seo/dataforseo.js";
4
+ import { classifySerp } from "./seo-classify.js";
5
+ import { Gsc, toGscProperty } from "../providers/seo/gsc.js";
6
+ import { readTraffic } from "./seo-traffic.js";
7
+ /** 对客加价:成本 × (1 + 4) = ×5。刻意不复用 platform.billing.markupPct(0.2)——
8
+ * 那是给域名 / 媒体等大额供给定的,套在美分级数据上会让定价失真(一次 serp 收 8 厘)。 */
9
+ export const SEO_MARKUP_PCT = 4;
10
+ /** 无 domain 归属的查询(keywords/competitors/serp)按租户走的月度兜底。
11
+ * 有 domain 的路径(PR2 的 check)用 seo_domains.budget_monthly_usd,同一个默认值。 */
12
+ export const SEO_BUDGET_DEFAULT_USD = 5;
13
+ /** 缓存 TTL:词/竞品指标月更口径 30 天;结果页时效短,7 天。 */
14
+ const TTL_DAYS = { keywords: 30, competitors: 30, serp: 7 };
15
+ /** competitors 每个域取多少个词(成本 ≈ $0.01 + 行数 × $0.0001)。 */
16
+ const RANKED_KEYWORDS_LIMIT = 25;
17
+ /** serp 抓多深(前 20 条足够看清占位格局;判定只用前 10)。 */
18
+ const SERP_DEPTH = 20;
19
+ /** 支持的 locale(上游要 location_code + language_code,CLI 只收 `en-US` 这种人话)。 */
20
+ const LOCALES = {
21
+ "en-US": { locationCode: 2840, languageCode: "en" },
22
+ "en-GB": { locationCode: 2826, languageCode: "en" },
23
+ "en-CA": { locationCode: 2124, languageCode: "en" },
24
+ "en-AU": { locationCode: 2036, languageCode: "en" },
25
+ "de-DE": { locationCode: 2276, languageCode: "de" },
26
+ "fr-FR": { locationCode: 2250, languageCode: "fr" },
27
+ "es-ES": { locationCode: 2724, languageCode: "es" },
28
+ "ja-JP": { locationCode: 2392, languageCode: "ja" },
29
+ };
30
+ export const DEFAULT_LOCALE = "en-US";
31
+ export function resolveLocale(tag) {
32
+ const t = (tag || DEFAULT_LOCALE).trim();
33
+ const codes = LOCALES[t] ?? LOCALES[t.replace(/_/g, "-")];
34
+ if (!codes)
35
+ throw new ClizeError(`unsupported locale "${t}" — supported: ${Object.keys(LOCALES).join(", ")}`, 400);
36
+ return { tag: LOCALES[t] ? t : t.replace(/_/g, "-"), codes };
37
+ }
38
+ /** 对客金额(4 位小数;上游成本是厘级,2 位会把一次 serp 抹成 $0.02 vs $0.02 —— 保 4 位如实)。 */
39
+ export function chargedForSeo(upstreamCostUsd) {
40
+ return Number((upstreamCostUsd * (1 + SEO_MARKUP_PCT)).toFixed(4));
41
+ }
42
+ export function keywordBand(sv, kd) {
43
+ if (sv === null || sv === 0)
44
+ return "no_volume";
45
+ if (kd === null)
46
+ return "stretch"; // 有量但上游没给 KD:落中档,不假装知道
47
+ if (kd < 10)
48
+ return "attackable";
49
+ if (kd <= 30)
50
+ return "stretch";
51
+ return "wall";
52
+ }
53
+ /** 行动优先级排序:能打的在前(低 KD 优先,同档大量优先),无量的沉底。 */
54
+ const BAND_ORDER = { attackable: 0, stretch: 1, wall: 2, no_volume: 3 };
55
+ // ---------------- 计费与预算 ----------------
56
+ /** 本月该租户(可选:限定 domain)的 seo 支出,口径 = 用户实付额。 */
57
+ export async function seoSpentThisMonth(db, tenantId, domain) {
58
+ const month = new Date().toISOString().slice(0, 7);
59
+ const sql = "SELECT COALESCE(SUM(amount_usd),0) AS s FROM ledger WHERE tenant_id=? AND kind='debit' AND action='seo' AND substr(ts,1,7)=?" +
60
+ (domain ? " AND json_extract(detail,'$.domain')=?" : "");
61
+ const binds = domain ? [tenantId, month, domain] : [tenantId, month];
62
+ const row = await db
63
+ .prepare(sql)
64
+ .bind(...binds)
65
+ .first();
66
+ return row?.s ?? 0;
67
+ }
68
+ /** 预算闸:超了给 429 + 解法(免逐次 confirm 的对价是花钱透明 + 有上限兜底)。 */
69
+ export async function assertSeoBudget(ctx, db, opts = {}) {
70
+ const domain = opts.domain;
71
+ let cap = SEO_BUDGET_DEFAULT_USD;
72
+ if (domain) {
73
+ const row = await db
74
+ .prepare("SELECT budget_monthly_usd FROM seo_domains WHERE domain=? AND tenant_id=?")
75
+ .bind(domain, ctx.tenantId)
76
+ .first();
77
+ if (row?.budget_monthly_usd != null)
78
+ cap = Number(row.budget_monthly_usd);
79
+ }
80
+ const spent = await seoSpentThisMonth(db, ctx.tenantId, domain);
81
+ if (spent < cap)
82
+ return;
83
+ const scope = domain ? `for ${domain}` : "this month";
84
+ const raise = domain
85
+ ? `clize seo check --domain ${domain} --budget ${Math.ceil(cap * 2)}`
86
+ : "top up the cap by contacting support (per-domain budgets are set by `clize seo check --budget`)";
87
+ throw new ClizeError(`monthly seo budget reached ${scope}: $${spent.toFixed(2)} of $${cap.toFixed(2)}. raise: ${raise}`, 429);
88
+ }
89
+ /** 扣费 + 入账(缓存命中不扣、不入账,ledger 里就不会出现一条 $0 噪音行)。 */
90
+ async function chargeSeo(ctx, op, upstreamCostUsd, detail = {}) {
91
+ const usd = chargedForSeo(upstreamCostUsd);
92
+ if (usd <= 0)
93
+ return { usd: 0, cacheHit: false };
94
+ await ctx.store.chargeBalance(ctx.tenantId, usd, {
95
+ action: "seo",
96
+ detail: { op, upstreamCost: Number(upstreamCostUsd.toFixed(5)), ...detail },
97
+ });
98
+ return { usd, cacheHit: false };
99
+ }
100
+ // ---------------- 缓存 ----------------
101
+ async function cacheKey(op, target, locale) {
102
+ // key 不含 tenant:租户隔离靠 tenant_id 列;Phase 1 开跨租户共享只需去掉查询条件。
103
+ return sha256hex(`${op}:${target.toLowerCase()}:${locale}`);
104
+ }
105
+ async function readCache(db, tenantId, key, ttlDays) {
106
+ const row = await db
107
+ .prepare("SELECT payload, fetched_at FROM seo_keyword_cache WHERE tenant_id=? AND cache_key=?")
108
+ .bind(tenantId, key)
109
+ .first();
110
+ if (!row)
111
+ return null;
112
+ const age = Date.now() - Date.parse(row.fetched_at);
113
+ if (!Number.isFinite(age) || age > ttlDays * 86_400_000)
114
+ return null;
115
+ try {
116
+ return JSON.parse(row.payload);
117
+ }
118
+ catch {
119
+ return null;
120
+ }
121
+ }
122
+ async function writeCache(db, tenantId, key, payload, costUsd) {
123
+ await db
124
+ .prepare("INSERT INTO seo_keyword_cache (tenant_id, cache_key, payload, cost_usd, fetched_at) VALUES (?,?,?,?,?)" +
125
+ " ON CONFLICT(tenant_id, cache_key) DO UPDATE SET payload=excluded.payload, cost_usd=excluded.cost_usd, fetched_at=excluded.fetched_at")
126
+ .bind(tenantId, key, JSON.stringify(payload), costUsd, new Date().toISOString())
127
+ .run();
128
+ }
129
+ function client(ctx) {
130
+ const e = ctx.platform.seo;
131
+ return new DataForSeo({ login: e.dataforseoLogin, password: e.dataforseoPassword });
132
+ }
133
+ /** 词指标。批量便宜(一次调用固定开销 + 每词几厘),所以 seeds 一次给全比逐个查省钱。 */
134
+ export async function keywords(ctx, db, opts) {
135
+ const seeds = [...new Set(opts.seeds.map((s) => s.trim().toLowerCase()).filter(Boolean))];
136
+ if (!seeds.length)
137
+ throw new ClizeError("no keywords given", 400);
138
+ if (seeds.length > KEYWORDS_PER_CALL)
139
+ throw new ClizeError(`too many keywords (${seeds.length}); max ${KEYWORDS_PER_CALL} per call`, 400);
140
+ const { tag, codes } = resolveLocale(opts.locale);
141
+ const op = opts.ai ? "keywords+ai" : "keywords";
142
+ const key = await cacheKey(op, seeds.slice().sort().join("|"), tag);
143
+ const cached = await readCache(db, ctx.tenantId, key, TTL_DAYS.keywords);
144
+ if (cached)
145
+ return { locale: tag, keywords: cached, charged: { usd: 0, cacheHit: true } };
146
+ await assertSeoBudget(ctx, db);
147
+ const api = client(ctx);
148
+ const base = await api.keywordOverview(seeds, codes);
149
+ let cost = base.costUsd;
150
+ const aiByKw = new Map();
151
+ if (opts.ai) {
152
+ const ai = await api.aiKeywordData(seeds, codes);
153
+ cost += ai.costUsd;
154
+ for (const r of ai.result)
155
+ aiByKw.set(r.keyword.toLowerCase(), r.aiSv);
156
+ }
157
+ const rows = base.result
158
+ .map((m) => ({
159
+ keyword: m.keyword,
160
+ sv: m.sv,
161
+ kd: m.kd,
162
+ cpc: m.cpc,
163
+ intent: m.intent,
164
+ ...(opts.ai ? { aiSv: aiByKw.get(m.keyword.toLowerCase()) ?? null } : {}),
165
+ band: keywordBand(m.sv, m.kd),
166
+ }))
167
+ .sort((a, b) => BAND_ORDER[a.band] - BAND_ORDER[b.band] ||
168
+ (a.kd ?? 999) - (b.kd ?? 999) ||
169
+ (b.sv ?? 0) - (a.sv ?? 0));
170
+ await writeCache(db, ctx.tenantId, key, rows, cost);
171
+ const charged = await chargeSeo(ctx, op, cost, { keywords: seeds.length, locale: tag });
172
+ return { locale: tag, keywords: rows, charged };
173
+ }
174
+ /** 竞品反查:一次问多个域的流量画像 + 每个域靠什么词活。 */
175
+ export async function competitors(ctx, db, opts) {
176
+ const domains = [...new Set(opts.domains.map(normalizeHost).filter(Boolean))];
177
+ if (!domains.length)
178
+ throw new ClizeError("no domains given", 400);
179
+ if (domains.length > 10)
180
+ throw new ClizeError(`too many domains (${domains.length}); max 10`, 400);
181
+ const { tag, codes } = resolveLocale(opts.locale);
182
+ const limit = Math.min(Math.max(opts.limit ?? RANKED_KEYWORDS_LIMIT, 1), 100);
183
+ const key = await cacheKey(`competitors:${limit}`, domains.slice().sort().join("|"), tag);
184
+ const cached = await readCache(db, ctx.tenantId, key, TTL_DAYS.competitors);
185
+ if (cached)
186
+ return { locale: tag, competitors: cached, charged: { usd: 0, cacheHit: true } };
187
+ await assertSeoBudget(ctx, db);
188
+ const api = client(ctx);
189
+ const traffic = await api.bulkTraffic(domains, codes);
190
+ let cost = traffic.costUsd;
191
+ const byDomain = new Map(traffic.result.map((t) => [t.domain, t]));
192
+ const rows = [];
193
+ for (const domain of domains) {
194
+ const ranked = await api.rankedKeywords(domain, codes, limit);
195
+ cost += ranked.costUsd;
196
+ const t = byDomain.get(domain);
197
+ rows.push({
198
+ domain,
199
+ etv: t?.etv ?? null,
200
+ keywordCount: t?.keywordCount ?? null,
201
+ topKeywords: ranked.result.items.map((k) => ({
202
+ keyword: k.keyword,
203
+ position: k.position,
204
+ sv: k.sv,
205
+ kd: k.kd,
206
+ etv: k.etv,
207
+ url: k.url,
208
+ })),
209
+ });
210
+ }
211
+ rows.sort((a, b) => (b.etv ?? 0) - (a.etv ?? 0));
212
+ await writeCache(db, ctx.tenantId, key, rows, cost);
213
+ const charged = await chargeSeo(ctx, "competitors", cost, { domains: domains.length, locale: tag });
214
+ return { locale: tag, competitors: rows, charged };
215
+ }
216
+ /** 结果页真相:自然结果 + 占位判定 + 寄生目标。 */
217
+ export async function serp(ctx, db, opts) {
218
+ const keyword = opts.keyword.trim();
219
+ if (!keyword)
220
+ throw new ClizeError("no keyword given", 400);
221
+ const { tag, codes } = resolveLocale(opts.locale);
222
+ const depth = Math.min(Math.max(opts.depth ?? SERP_DEPTH, 10), 100);
223
+ const key = await cacheKey(`serp:${depth}`, keyword, tag);
224
+ const cached = await readCache(db, ctx.tenantId, key, TTL_DAYS.serp);
225
+ if (cached)
226
+ return { ...cached, charged: { usd: 0, cacheHit: true } };
227
+ await assertSeoBudget(ctx, db);
228
+ const { result: page, costUsd } = await client(ctx).serpLiveAdvanced(keyword, codes, depth);
229
+ const classified = classifySerp(keyword, page.items);
230
+ const payload = {
231
+ keyword: page.keyword,
232
+ locale: tag,
233
+ verdict: classified.verdict,
234
+ aiOverview: page.aiOverview,
235
+ itemTypes: page.itemTypes,
236
+ counts: classified.counts,
237
+ items: classified.items.map((i) => ({
238
+ pos: i.pos,
239
+ host: i.host,
240
+ url: i.url,
241
+ title: i.title,
242
+ type: i.type,
243
+ })),
244
+ parasiteTargets: classified.parasiteTargets,
245
+ checkedAt: page.checkedAt,
246
+ };
247
+ await writeCache(db, ctx.tenantId, key, payload, costUsd);
248
+ const charged = await chargeSeo(ctx, "serp", costUsd, { keyword, locale: tag });
249
+ return { ...payload, charged };
250
+ }
251
+ /** GSC 窗口重拉的天数:Google 会事后修正近日数据,固定重拉最近 N 天并替换。 */
252
+ const GSC_WINDOW_DAYS = 30;
253
+ /** 窗口末端留出的定稿滞后天数(dataState:final 也要等 Google 收口)。 */
254
+ const GSC_LAG_DAYS = 3;
255
+ /** GSC 新词回填上限(按曝光降序取):词表是给人/agent 看的,不是倾倒 GSC 全量。 */
256
+ const GSC_BACKFILL_MAX = 20;
257
+ /** GSC 新词回填的曝光下限(窗口内)。低于此量的词与噪声不可分——实测尾部全是
258
+ * 品牌拼写错误(clice ai / craze ai / calise ai,各 7–8 次)与泛词碎片。
259
+ * 这是个判断阈值,不是自然常量:改它只动这一行。 */
260
+ const GSC_BACKFILL_MIN_IMPRESSIONS = 10;
261
+ /** 位次时序回看多少周(周口径:SEO 是周月尺度的慢系统,日粒度只是噪声 + context 字节)。 */
262
+ const RANK_SERIES_WEEKS = 12;
263
+ /** 算 mover 的位移阈值(GSC 均位次,±3 名以内是采样抖动)。 */
264
+ const RANK_MOVER_MIN = 3;
265
+ /** 流量的默认回看窗口。 */
266
+ const TRAFFIC_DAYS = 30;
267
+ /** `--gsc none` 存进 gsc_property 的哨兵:显式关闭 ≠ 还没探测过(null),下轮不再问。 */
268
+ const GSC_OFF = "none";
269
+ const DAY_MS = 86_400_000;
270
+ const day = (ms) => new Date(ms).toISOString().slice(0, 10);
271
+ const dayMs = (d) => Date.parse(`${d}T00:00:00Z`);
272
+ /** 本轮的测量窗口 + 用来算 delta 的上一窗口(等长、紧邻,不重叠)。 */
273
+ function measureWindow(now) {
274
+ const to = day(now - GSC_LAG_DAYS * DAY_MS);
275
+ const from = day(now - GSC_WINDOW_DAYS * DAY_MS);
276
+ const span = Math.round((dayMs(to) - dayMs(from)) / DAY_MS); // 含头不含尾的天数差
277
+ const prevTo = day(dayMs(from) - DAY_MS);
278
+ const prevFrom = day(dayMs(prevTo) - span * DAY_MS);
279
+ return { from, to, prevFrom, prevTo };
280
+ }
281
+ /** 配置 upsert:带参则更新,不带则沿用已存的(首次给出后记住)。 */
282
+ async function upsertDomain(ctx, db, domain, cfg) {
283
+ const existing = await db
284
+ .prepare("SELECT domain, brand, competitors, gsc_property, budget_monthly_usd FROM seo_domains WHERE domain=? AND tenant_id=?")
285
+ .bind(domain, ctx.tenantId)
286
+ .first();
287
+ const row = {
288
+ domain,
289
+ brand: cfg.brand ?? existing?.brand ?? null,
290
+ competitors: cfg.competitors
291
+ ? JSON.stringify(cfg.competitors.map(normalizeHost))
292
+ : (existing?.competitors ?? null),
293
+ // "none" 存成哨兵而不是清空:清空等于「还没探测过」,下轮又会去问一遍 —— 那句
294
+ // 「pass --gsc none to stop asking」就成了空头支票。
295
+ gsc_property: cfg.gsc === GSC_OFF ? GSC_OFF : (cfg.gsc ?? existing?.gsc_property ?? null),
296
+ budget_monthly_usd: cfg.budgetUsd ?? existing?.budget_monthly_usd ?? SEO_BUDGET_DEFAULT_USD,
297
+ };
298
+ await db
299
+ .prepare("INSERT INTO seo_domains (domain, tenant_id, brand, competitors, gsc_property, budget_monthly_usd, created_at) VALUES (?,?,?,?,?,?,?)" +
300
+ " ON CONFLICT(domain) DO UPDATE SET brand=excluded.brand, competitors=excluded.competitors," +
301
+ " gsc_property=excluded.gsc_property, budget_monthly_usd=excluded.budget_monthly_usd")
302
+ .bind(domain, ctx.tenantId, row.brand, row.competitors, row.gsc_property, row.budget_monthly_usd, new Date().toISOString())
303
+ .run();
304
+ return row;
305
+ }
306
+ async function readKeywords(db, domain) {
307
+ const { results } = await db
308
+ .prepare("SELECT keyword, sv, kd, source FROM seo_keywords WHERE domain=? ORDER BY id")
309
+ .bind(domain)
310
+ .all();
311
+ return results;
312
+ }
313
+ /** 词表:--keywords 是**全量替换**(保留已有行的指标),不带则读已存的。 */
314
+ async function syncKeywords(db, domain, keywords, now) {
315
+ if (keywords) {
316
+ const wanted = [...new Set(keywords.map((k) => k.trim().toLowerCase()).filter(Boolean))];
317
+ // 全量替换语义:不在新表里的词删掉(含之前 gsc_backfill 进来的)。
318
+ const { results: existing } = await db
319
+ .prepare("SELECT keyword FROM seo_keywords WHERE domain=?")
320
+ .bind(domain)
321
+ .all();
322
+ for (const e of existing)
323
+ if (!wanted.includes(e.keyword))
324
+ await db.prepare("DELETE FROM seo_keywords WHERE domain=? AND keyword=?").bind(domain, e.keyword).run();
325
+ for (const k of wanted)
326
+ await db
327
+ .prepare("INSERT INTO seo_keywords (domain, keyword, locale, source, saved_at) VALUES (?,?,?,?,?)" +
328
+ " ON CONFLICT(domain, keyword, locale) DO UPDATE SET source='check'")
329
+ .bind(domain, k, DEFAULT_LOCALE, "check", now)
330
+ .run();
331
+ }
332
+ return readKeywords(db, domain);
333
+ }
334
+ /** 测一轮。cron 若将来复活,定期跑的就是这个函数(同一条代码路径)。 */
335
+ export async function checkOne(ctx, db, domain0, cfg = {}, now = Date.now()) {
336
+ const domain = normalizeHost(domain0.replace(/^https?:\/\//, "").split("/")[0] ?? "");
337
+ if (!domain)
338
+ throw new ClizeError("no domain: pass --domain or run inside a clize project", 400);
339
+ // 预算闸刻意不在这里:check 不打上游数据源,没有可花的钱。花钱的是查询三条。
340
+ const ranAt = new Date(now).toISOString();
341
+ const win = measureWindow(now);
342
+ const conf = await upsertDomain(ctx, db, domain, cfg);
343
+ const competitors = conf.competitors ? JSON.parse(conf.competitors) : [];
344
+ const kwRows = await syncKeywords(db, domain, cfg.keywords, ranAt);
345
+ const notes = [];
346
+ // ── 流量分源(自有基建,不花数据钱)。AI 来源单列;全零也返回,零就是信息。
347
+ let traffic = null;
348
+ try {
349
+ traffic = await readTraffic(ctx, {
350
+ host: domain,
351
+ from: new Date(now - TRAFFIC_DAYS * DAY_MS).toISOString().replace(/\.\d{3}Z$/, "Z"),
352
+ to: new Date(now).toISOString().replace(/\.\d{3}Z$/, "Z"),
353
+ });
354
+ }
355
+ catch (e) {
356
+ notes.push(`traffic unavailable: ${e instanceof Error ? e.message : String(e)}`);
357
+ }
358
+ if (traffic)
359
+ await db
360
+ .prepare("INSERT INTO seo_traffic_snapshots (domain, period_start, period_end, pv, referrers, ai_sources) VALUES (?,?,?,?,?,?)" +
361
+ " ON CONFLICT(domain, period_start) DO UPDATE SET period_end=excluded.period_end, pv=excluded.pv," +
362
+ " referrers=excluded.referrers, ai_sources=excluded.ai_sources")
363
+ .bind(domain, traffic.from.slice(0, 10), traffic.to.slice(0, 10), traffic.pv, JSON.stringify(Object.fromEntries(traffic.topReferrers.map((r) => [r.host, r.pv]))), JSON.stringify(traffic.ai.byEngine))
364
+ .run();
365
+ // ── GSC(唯一的搜索面)。拿不到不中断整轮 —— 给 null + hint。
366
+ const gsc = await gscSection(ctx, db, domain, conf, kwRows, notes, win, now);
367
+ // ── 位次:词表 join 刚落库的 GSC 明细。零上游调用、零成本。
368
+ // 回填可能刚往词表里加了词,所以重新读一次 —— 否则 total 会漏掉本轮的新发现。
369
+ const kwAll = await readKeywords(db, domain);
370
+ const tracked = kwAll.filter((k) => k.source !== "gsc_backfill");
371
+ let rank = null;
372
+ if (!gsc)
373
+ notes.push("rank unavailable: positions come from Search Console (free) — see the gsc note above; for a single keyword's exact position use `clize seo serp <keyword>`");
374
+ else if (!tracked.length)
375
+ notes.push("no keyword list yet — pass --keywords a,b,c to start tracking positions");
376
+ else
377
+ rank = await rankSection(db, domain, tracked, win);
378
+ // byBand 只统计**取过指标**的词:sv 为空是「没问过量」,不是「没有量」——
379
+ // 把它算进 no_volume 会让分桶恒真且误导(2026-08-31 线上首轮 check 暴露)。
380
+ const byBand = {};
381
+ let unpriced = 0;
382
+ for (const k of kwAll) {
383
+ if (k.sv === null) {
384
+ unpriced++;
385
+ continue;
386
+ }
387
+ const b = keywordBand(k.sv, k.kd);
388
+ byBand[b] = (byBand[b] ?? 0) + 1;
389
+ }
390
+ if (unpriced)
391
+ notes.push(`keywords: no metrics on file for ${unpriced} of ${kwAll.length} — byBand counts only priced keywords (the saved list stores words, not metrics)`);
392
+ const spent = await seoSpentThisMonth(db, ctx.tenantId);
393
+ return {
394
+ domain,
395
+ brand: conf.brand,
396
+ competitors,
397
+ ranAt,
398
+ budget: { monthlyUsd: conf.budget_monthly_usd, spentThisMonth: Number(spent.toFixed(4)) },
399
+ keywords: { total: kwAll.length, byBand, tracked: tracked.length },
400
+ rank,
401
+ traffic,
402
+ gsc,
403
+ notes,
404
+ // check 免费:两个数据源都是自有的(GSC service account + 自家 CF RUM)。
405
+ charged: { usd: 0, cacheHit: false },
406
+ };
407
+ }
408
+ /** 按 query 聚合一段窗口的 GSC 明细。位次 = **曝光加权均值**(GSC 自己的 average position 口径)。 */
409
+ async function aggregateGsc(db, domain, from, to) {
410
+ const { results } = await db
411
+ .prepare("SELECT query, SUM(clicks) AS clicks, SUM(impressions) AS impressions," +
412
+ " SUM(position*impressions) AS pw FROM seo_gsc_daily" +
413
+ " WHERE domain=? AND date>=? AND date<=? GROUP BY query")
414
+ .bind(domain, from, to)
415
+ .all();
416
+ const out = new Map();
417
+ for (const r of results) {
418
+ if (!r.impressions)
419
+ continue; // 曝光 0 的行没有可加权的位次
420
+ out.set(r.query, {
421
+ position: Number((r.pw / r.impressions).toFixed(1)),
422
+ clicks: r.clicks,
423
+ impressions: r.impressions,
424
+ });
425
+ }
426
+ return out;
427
+ }
428
+ /** 位次段:词表 join GSC 明细。纯 D1 读,零上游调用。 */
429
+ async function rankSection(db, domain, tracked, win) {
430
+ const cur = await aggregateGsc(db, domain, win.from, win.to);
431
+ const prev = await aggregateGsc(db, domain, win.prevFrom, win.prevTo);
432
+ const wanted = new Set(tracked.map((k) => k.keyword));
433
+ const series = await weeklySeries(db, domain, wanted, win.to);
434
+ const latest = [];
435
+ const unseen = [];
436
+ for (const k of tracked) {
437
+ const a = cur.get(k.keyword);
438
+ if (!a) {
439
+ // GSC 本窗口没见过这个词。**只列名,零成本** —— 对它做深抓只会一遍遍确认「仍未见」。
440
+ unseen.push(k.keyword);
441
+ continue;
442
+ }
443
+ const p = prev.get(k.keyword);
444
+ latest.push({
445
+ keyword: k.keyword,
446
+ position: a.position,
447
+ clicks: a.clicks,
448
+ impressions: a.impressions,
449
+ // 位次变小 = 前进,所以 delta = 旧 - 新(正数是好消息)。上一窗口没数据 → null。
450
+ delta: p ? Number((p.position - a.position).toFixed(1)) : null,
451
+ series: series.get(k.keyword) ?? [],
452
+ });
453
+ }
454
+ latest.sort((x, y) => x.position - y.position);
455
+ const movers = latest
456
+ .filter((r) => r.delta != null && Math.abs(r.delta) >= RANK_MOVER_MIN)
457
+ .sort((x, y) => Math.abs(y.delta ?? 0) - Math.abs(x.delta ?? 0));
458
+ return {
459
+ source: "gsc",
460
+ window: { from: win.from, to: win.to },
461
+ prevWindow: { from: win.prevFrom, to: win.prevTo },
462
+ latest,
463
+ movers,
464
+ unseen,
465
+ };
466
+ }
467
+ /** 周口径时序:从窗口末端往回按 7 天分桶(不用自然周,免得口径受星期几影响)。 */
468
+ async function weeklySeries(db, domain, wanted, to) {
469
+ const endMs = dayMs(to);
470
+ const since = day(endMs - (RANK_SERIES_WEEKS * 7 - 1) * DAY_MS);
471
+ const { results } = await db
472
+ .prepare("SELECT query, date, SUM(impressions) AS impressions, SUM(position*impressions) AS pw" +
473
+ " FROM seo_gsc_daily WHERE domain=? AND date>=? AND date<=? GROUP BY query, date")
474
+ .bind(domain, since, to)
475
+ .all();
476
+ const buckets = new Map();
477
+ for (const r of results) {
478
+ if (!wanted.has(r.query) || !r.impressions)
479
+ continue;
480
+ const idx = Math.floor((endMs - dayMs(r.date)) / (7 * DAY_MS));
481
+ if (idx < 0 || idx >= RANK_SERIES_WEEKS)
482
+ continue;
483
+ const byWeek = buckets.get(r.query) ?? new Map();
484
+ const cell = byWeek.get(idx) ?? { pw: 0, imp: 0 };
485
+ cell.pw += r.pw;
486
+ cell.imp += r.impressions;
487
+ byWeek.set(idx, cell);
488
+ buckets.set(r.query, byWeek);
489
+ }
490
+ const out = new Map();
491
+ for (const [query, byWeek] of buckets)
492
+ out.set(query, [...byWeek.entries()]
493
+ .sort((a, b) => a[0] - b[0]) // 倒序:最近的周在前
494
+ .map(([idx, c]) => [
495
+ day(endMs - (idx * 7 + 6) * DAY_MS), // 该周的起始日
496
+ Number((c.pw / c.imp).toFixed(1)),
497
+ ]));
498
+ return out;
499
+ }
500
+ /** GSC 段:窗口重拉替换 + 新词回填。任何失败都降级成 note,不中断 check。 */
501
+ async function gscSection(ctx, db, domain, conf, kwRows, notes, win, now) {
502
+ if (conf.gsc_property === GSC_OFF) {
503
+ notes.push("gsc: switched off for this domain (--gsc none) — pass --gsc <property> to turn it back on");
504
+ return null;
505
+ }
506
+ const saKey = ctx.platform.seo.gscServiceAccountKey;
507
+ if (!saKey) {
508
+ notes.push("gsc: not configured on this deployment (GSC_SA_KEY missing)");
509
+ return null;
510
+ }
511
+ const gscClient = new Gsc(saKey);
512
+ let property = conf.gsc_property;
513
+ if (!property) {
514
+ // 首跑自动探测:SA 能读哪个 property 就用哪个(域名属性覆盖全子域,通常一击即中)。
515
+ try {
516
+ const sites = await gscClient.listSites();
517
+ const want = [toGscProperty(domain), `https://${domain}/`, `https://www.${domain}/`];
518
+ property = sites.find((s) => want.includes(s.siteUrl.toLowerCase()))?.siteUrl ?? null;
519
+ }
520
+ catch (e) {
521
+ notes.push(`gsc: ${e instanceof Error ? e.message : String(e)}`);
522
+ return null;
523
+ }
524
+ if (!property) {
525
+ notes.push(`gsc: no accessible property for ${domain} — add ${gscClient.serviceAccountEmail} as a Restricted user in Search Console, then re-run (or pass --gsc none to stop asking)`);
526
+ return null;
527
+ }
528
+ await db.prepare("UPDATE seo_domains SET gsc_property=? WHERE domain=?").bind(property, domain).run();
529
+ }
530
+ // Google 会事后修正近日数据 → 固定窗口重拉 + 整窗替换(不做 append-only,
531
+ // 否则被修正掉的旧值会永久留在时序里)。
532
+ let rows;
533
+ try {
534
+ rows = await gscClient.queryAnalytics(property, win.from, win.to);
535
+ }
536
+ catch (e) {
537
+ notes.push(`gsc: ${e instanceof Error ? e.message : String(e)}`);
538
+ return null;
539
+ }
540
+ await db
541
+ .prepare("DELETE FROM seo_gsc_daily WHERE domain=? AND date>=? AND date<=?")
542
+ .bind(domain, win.from, win.to)
543
+ .run();
544
+ for (const r of rows)
545
+ await db
546
+ .prepare("INSERT INTO seo_gsc_daily (domain, date, query, page, clicks, impressions, position) VALUES (?,?,?,?,?,?,?)" +
547
+ " ON CONFLICT(domain, date, query, page) DO UPDATE SET clicks=excluded.clicks," +
548
+ " impressions=excluded.impressions, position=excluded.position")
549
+ .bind(domain, r.date, r.query, r.page, r.clicks, r.impressions, r.position)
550
+ .run();
551
+ // 按 query 聚合(明细已落库,返回只给摘要——为 context 优化)。
552
+ const agg = new Map();
553
+ for (const r of rows) {
554
+ const a = agg.get(r.query) ?? { clicks: 0, impressions: 0, posSum: 0, n: 0 };
555
+ a.clicks += r.clicks;
556
+ a.impressions += r.impressions;
557
+ a.posSum += r.position * r.impressions;
558
+ a.n += r.impressions;
559
+ agg.set(r.query, a);
560
+ }
561
+ const byQuery = [...agg.entries()]
562
+ .map(([query, a]) => ({
563
+ query,
564
+ clicks: a.clicks,
565
+ impressions: a.impressions,
566
+ position: a.n ? Number((a.posSum / a.n).toFixed(1)) : 0,
567
+ }))
568
+ .sort((x, y) => y.impressions - x.impressions);
569
+ // 新词回填:GSC 冒出的、词表里还没有的词 —— 环 4 → 环 1 的反哺回路闭合。
570
+ // 只是「发现」,不计入位次对照清单(source=gsc_backfill)。
571
+ const known = new Set(kwRows.map((k) => k.keyword));
572
+ const brand = (conf.brand ?? "").toLowerCase();
573
+ const fresh = byQuery
574
+ .filter((q) => !known.has(q.query))
575
+ .filter((q) => q.impressions >= GSC_BACKFILL_MIN_IMPRESSIONS) // 低于此量与噪声不可分
576
+ .filter((q) => !q.query.startsWith("site:")) // 自查污染,不是需求信号
577
+ .filter((q) => !brand || !q.query.includes(brand)) // 品牌词不是新发现
578
+ .slice(0, GSC_BACKFILL_MAX);
579
+ const savedAt = new Date(now).toISOString();
580
+ for (const q of fresh)
581
+ await db
582
+ .prepare("INSERT INTO seo_keywords (domain, keyword, locale, source, saved_at) VALUES (?,?,?,?,?)" +
583
+ " ON CONFLICT(domain, keyword, locale) DO NOTHING")
584
+ .bind(domain, q.query, DEFAULT_LOCALE, "gsc_backfill", savedAt)
585
+ .run();
586
+ return {
587
+ property,
588
+ window: { from: win.from, to: win.to },
589
+ clicks: byQuery.reduce((s, q) => s + q.clicks, 0),
590
+ impressions: byQuery.reduce((s, q) => s + q.impressions, 0),
591
+ topQueries: byQuery.slice(0, 15),
592
+ newQueries: fresh.map((q) => ({ query: q.query, impressions: q.impressions, position: q.position })),
593
+ };
594
+ }
595
+ //# sourceMappingURL=seo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seo.js","sourceRoot":"","sources":["../../src/core/seo.ts"],"names":[],"mappings":"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"}