@itznexus/itznexus-cli 1.136.0 → 1.137.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.
- package/dist/commands/api/seo-backlinks.d.ts +2 -0
- package/dist/commands/api/seo-backlinks.js +132 -0
- package/dist/commands/api/seo-backlinks.js.map +1 -0
- package/dist/commands/api/seo-catalog.d.ts +2 -0
- package/dist/commands/api/seo-catalog.js +184 -0
- package/dist/commands/api/seo-catalog.js.map +1 -0
- package/dist/commands/api/seo-changes.d.ts +2 -0
- package/dist/commands/api/seo-changes.js +101 -0
- package/dist/commands/api/seo-changes.js.map +1 -0
- package/dist/commands/api/seo-data.d.ts +2 -0
- package/dist/commands/api/seo-data.js +175 -0
- package/dist/commands/api/seo-data.js.map +1 -0
- package/dist/commands/api/seo-keyword-writes.d.ts +2 -0
- package/dist/commands/api/seo-keyword-writes.js +132 -0
- package/dist/commands/api/seo-keyword-writes.js.map +1 -0
- package/dist/commands/api/seo-keywords.d.ts +2 -0
- package/dist/commands/api/seo-keywords.js +103 -0
- package/dist/commands/api/seo-keywords.js.map +1 -0
- package/dist/commands/api/seo-page-writes.d.ts +2 -0
- package/dist/commands/api/seo-page-writes.js +130 -0
- package/dist/commands/api/seo-page-writes.js.map +1 -0
- package/dist/commands/api/seo-pages.d.ts +2 -0
- package/dist/commands/api/seo-pages.js +144 -0
- package/dist/commands/api/seo-pages.js.map +1 -0
- package/dist/commands/api/seo-settings.d.ts +2 -0
- package/dist/commands/api/seo-settings.js +148 -0
- package/dist/commands/api/seo-settings.js.map +1 -0
- package/dist/commands/api/seo-shared.d.ts +15 -0
- package/dist/commands/api/seo-shared.js +77 -0
- package/dist/commands/api/seo-shared.js.map +1 -0
- package/dist/commands/api/seo.d.ts +2 -0
- package/dist/commands/api/seo.js +23 -0
- package/dist/commands/api/seo.js.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seo-data.js","sourceRoot":"","sources":["../../../src/commands/api/seo-data.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EACL,IAAI,EAEJ,SAAS,EACT,EAAE,EACF,YAAY,GACb,MAAM,iBAAiB,CAAC;AAEzB,6EAA6E;AAC7E,MAAM,oBAAoB,GAAG,IAAI,CAAC;AAClC,MAAM,4BAA4B,GAAG,IAAI,CAAC;AAE1C,KAAK,UAAU,cAAc,CAC3B,IAAY,EACZ,IAAe,EACf,IAAY;IAEZ,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC;QAC3C,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,IAAI,CAAuB,IAAI,EAAE;YACrD,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC;SAC9B,CAAC,CAAC;QACH,QAAQ,IAAI,GAAG,CAAC,QAAQ,CAAC;IAC3B,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,WAAW,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC;KACpC,WAAW,CAAC,sDAAsD,CAAC;KACnE,MAAM,CAAC,mBAAmB,EAAE,aAAa,CAAC;KAC1C,MAAM,CAAC,iBAAiB,EAAE,aAAa,CAAC;KACxC,MAAM,CAAC,mBAAmB,EAAE,2BAA2B,CAAC;KACxD,MAAM,CAAC,eAAe,EAAE,wBAAwB,CAAC;KACjD,MAAM,CAAC,aAAa,EAAE,sBAAsB,CAAC;KAC7C,MAAM,CAAC,YAAY,EAAE,yBAAyB,CAAC;KAC/C,MAAM,CAAC,iBAAiB,EAAE,mCAAmC,CAAC;KAC9D,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC;KAClC,MAAM,CACL,KAAK,EACH,IAQC,EACD,EAAE;IACF,IAAI,CAAC;QACH,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,MAAM,GAAG,CAAC,WAAW,CAI1C,gBAAgB,EAAE,CAAC;YACjB,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,EAAE,EAAE,IAAI,CAAC,EAAE;YACX,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,QAAQ,EAAE,IAAI,CAAC,QAAQ;SACxB,CAAC,EAAE,CACL,CAAC;QACF,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,SAAS,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;YAC1B,OAAO;QACT,CAAC;QACD,SAAS,CACP,IAAI,EACJ;YACE,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE;YACzC,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE;YACzC,EAAE,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,EAAE;YAC/C,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,EAAE;YAC5C,EAAE,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE;YAC5C,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE;SACxC,EACD,IAAI,CACL,CAAC;QACF,IAAI,IAAI,EAAE,CAAC;YACT,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,GAAG,CACP,QAAQ,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,UAAU,KAAK,IAAI,CAAC,KAAK,QAAQ,CAC5D,CACF,CAAC;QACJ,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,WAAW,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;AACH,CAAC,CACF,CAAC;AAEJ,MAAM,aAAa,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC;KACxC,WAAW,CAAC,4DAA4D,CAAC;KACzE,cAAc,CACb,eAAe,EACf,mFAAmF,CACpF;KACA,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC;KAClC,MAAM,CAAC,KAAK,EAAE,IAAgC,EAAE,EAAE;IACjD,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrC,MAAM,QAAQ,GAAG,MAAM,cAAc,CACnC,eAAe,EACf,IAAI,EACJ,oBAAoB,CACrB,CAAC;QACF,IAAI,CAAC,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,YAAY,QAAQ,eAAe,CAAC,CAAC;IAChE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,WAAW,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,MAAM,cAAc,GAAG,IAAI,OAAO,CAAC,SAAS,CAAC;KAC1C,WAAW,CAAC,6CAA6C,CAAC;KAC1D,UAAU,CAAC,WAAW,CAAC;KACvB,UAAU,CAAC,aAAa,CAAC,CAAC;AAE7B,MAAM,cAAc,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC;KACxC,WAAW,CACV,kFAAkF,CACnF;KACA,MAAM,CAAC,eAAe,EAAE,gDAAgD,CAAC;KACzE,MAAM,CAAC,aAAa,EAAE,wCAAwC,CAAC;KAC/D,MAAM,CACL,qBAAqB,EACrB,0EAA0E,CAC3E;KACA,MAAM,CAAC,eAAe,EAAE,qBAAqB,CAAC;KAC9C,MAAM,CAAC,gBAAgB,EAAE,gBAAgB,CAAC;KAC1C,MAAM,CAAC,kBAAkB,EAAE,4BAA4B,CAAC;KACxD,MAAM,CAAC,mBAAmB,EAAE,2BAA2B,CAAC;KACxD,MAAM,CAAC,iBAAiB,EAAE,oCAAoC,CAAC;KAC/D,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC;KAClC,MAAM,CACL,KAAK,EACH,IASC,EACD,EAAE;IACF,IAAI,CAAC;QACH,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,MAAM,GAAG,CAAC,WAAW,CAS1C,wBAAwB,EAAE,CAAC;YACzB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,EAAE,EAAE,IAAI,CAAC,EAAE;YACX,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,QAAQ,EAAE,IAAI,CAAC,QAAQ;SACxB,CAAC,EAAE,CACL,CAAC;QACF,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,SAAS,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;YAC1B,OAAO;QACT,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,EAAE,UAAU,IAAI,CAAC,MAAM,CAAC,CAAC;QAC1C,SAAS,CACP,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACf,GAAG,CAAC;YACJ,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG;YACnC,QAAQ,EAAE,CAAC,CAAC,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI;SAC5D,CAAC,CAAC,EACH;YACE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBAClB,GAAG,EAAE,CAAC;gBACN,KAAK,EAAE,CAAC;gBACR,KAAK,EAAE,CAAC,KAAK,OAAO,IAAI,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE;aAC/C,CAAC,CAAC;YACH,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,EAAE;YAC5C,EAAE,GAAG,EAAE,aAAa,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE;YAChD,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE;YACtC,EAAE,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE;SAC7C,EACD,IAAI,CACL,CAAC;QACF,IAAI,IAAI;YAAE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,IAAI,OAAO,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IACjE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,WAAW,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;AACH,CAAC,CACF,CAAC;AAEJ,MAAM,eAAe,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC;KAC1C,WAAW,CAAC,6DAA6D,CAAC;KAC1E,cAAc,CACb,eAAe,EACf,oGAAoG,CACrG;KACA,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC;KAClC,MAAM,CAAC,KAAK,EAAE,IAAgC,EAAE,EAAE;IACjD,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrC,MAAM,QAAQ,GAAG,MAAM,cAAc,CACnC,uBAAuB,EACvB,IAAI,EACJ,4BAA4B,CAC7B,CAAC;QACF,IAAI,CAAC,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,YAAY,QAAQ,sBAAsB,CAAC,CAAC;IACvE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,WAAW,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,MAAM,sBAAsB,GAAG,IAAI,OAAO,CAAC,kBAAkB,CAAC;KAC3D,WAAW,CACV,0EAA0E,CAC3E;KACA,UAAU,CAAC,cAAc,CAAC;KAC1B,UAAU,CAAC,eAAe,CAAC,CAAC;AAE/B,MAAM,kBAAkB,GAAG,IAAI,OAAO,CAAC,aAAa,CAAC;KAClD,WAAW,CACV,oEAAoE,CACrE;KACA,MAAM,CAAC,YAAY,EAAE,wCAAwC,CAAC;KAC9D,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC;KAClC,MAAM,CAAC,KAAK,EAAE,IAAiC,EAAE,EAAE;IAClD,IAAI,CAAC;QACH,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,MAAM,GAAG,CAAC,WAAW,CAQ1C,mBAAmB,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;QAChD,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,SAAS,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;YAC1B,OAAO;QACT,CAAC;QACD,SAAS,CACP,IAAI,EACJ;YACE,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,EAAE,EAAE;YACjD,EAAE,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,EAAE;YAChD,EAAE,GAAG,EAAE,eAAe,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE;YAClD,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE;SAC3C,EACD,IAAI,CACL,CAAC;QACF,IAAI,IAAI;YACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,OAAO,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IACvE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,WAAW,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,cAAc;IACd,sBAAsB;IACtB,kBAAkB;CACnB,CAAC"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { api } from "../../lib/api.js";
|
|
3
|
+
import { handleError } from "../../lib/format.js";
|
|
4
|
+
import { compact, done, nullable, nullableInt, parseBool, readJsonFile, } from "./seo-shared.js";
|
|
5
|
+
function withFieldOptions(cmd) {
|
|
6
|
+
return cmd
|
|
7
|
+
.option("--hub <slug>", 'Hub slug ("null" to clear)')
|
|
8
|
+
.option("--category <name>", 'Category inside the hub ("null" to clear)')
|
|
9
|
+
.option("--page-id <id>", 'Page this keyword belongs to ("null" to clear)')
|
|
10
|
+
.option("--intent <intent>", "informational | navigational | commercial | transactional")
|
|
11
|
+
.option("--relevance <n>", "Relevance 1 to 10, lower is more relevant")
|
|
12
|
+
.option("--tracked <bool>", "Include in weekly rank tracking: true | false")
|
|
13
|
+
.option("--branded <bool>", "Branded keyword (own label): true | false")
|
|
14
|
+
.option("--source <source>", "competitor | search-console | keyword-ideas | manual")
|
|
15
|
+
.option("--notes <text>", 'SERP read notes ("null" to clear)');
|
|
16
|
+
}
|
|
17
|
+
function fieldPayload(opts) {
|
|
18
|
+
return compact({
|
|
19
|
+
hub: nullable(opts.hub),
|
|
20
|
+
category: nullable(opts.category),
|
|
21
|
+
pageId: nullable(opts.pageId),
|
|
22
|
+
intent: nullable(opts.intent),
|
|
23
|
+
relevance: nullableInt(opts.relevance, "relevance"),
|
|
24
|
+
tracked: opts.tracked !== undefined
|
|
25
|
+
? parseBool(opts.tracked, "tracked")
|
|
26
|
+
: undefined,
|
|
27
|
+
branded: opts.branded !== undefined
|
|
28
|
+
? parseBool(opts.branded, "branded")
|
|
29
|
+
: undefined,
|
|
30
|
+
source: nullable(opts.source),
|
|
31
|
+
notes: nullable(opts.notes),
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
function statusPayload(status, parkedReason) {
|
|
35
|
+
return status === "parked" ? { status, parkedReason } : { status };
|
|
36
|
+
}
|
|
37
|
+
const setCmd = withFieldOptions(new Command("set")
|
|
38
|
+
.description("Create or update a keyword keyed by (keyword, language); safe to rerun")
|
|
39
|
+
.argument("<keyword>", "The keyword as searched (stored lowercase)")
|
|
40
|
+
.requiredOption("--language <lang>", "en | fr"))
|
|
41
|
+
.option("--status <status>", "candidate | parked | targeted")
|
|
42
|
+
.option("--parked-reason <reason>", "With --status parked: high-da | listicle-serp | mixed-intent | off-offer | ambiguous | online-duplicate | other")
|
|
43
|
+
.option("--json", "Output as JSON")
|
|
44
|
+
.action(async (keyword, opts) => {
|
|
45
|
+
try {
|
|
46
|
+
let data = await api.post("/seo/keywords", {
|
|
47
|
+
keyword,
|
|
48
|
+
language: opts.language,
|
|
49
|
+
...fieldPayload(opts),
|
|
50
|
+
});
|
|
51
|
+
const created = data.created;
|
|
52
|
+
if (opts.status) {
|
|
53
|
+
data = await api.post(`/seo/keywords/${data.id}/status`, statusPayload(opts.status, opts.parkedReason));
|
|
54
|
+
}
|
|
55
|
+
done({ ...data, created }, opts, `Keyword ${created ? "created" : "updated"}: ${data.keyword} (${data.id})`);
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
handleError(err);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
const updateCmd = withFieldOptions(new Command("update")
|
|
62
|
+
.description("Update a keyword's fields (status has its own command)")
|
|
63
|
+
.argument("<id>", "Keyword id"))
|
|
64
|
+
.option("--json", "Output as JSON")
|
|
65
|
+
.action(async (id, opts) => {
|
|
66
|
+
try {
|
|
67
|
+
const data = await api.post(`/seo/keywords/${id}`, fieldPayload(opts));
|
|
68
|
+
done(data, opts, `Keyword updated: ${data.keyword}`);
|
|
69
|
+
}
|
|
70
|
+
catch (err) {
|
|
71
|
+
handleError(err);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
const statusCmd = new Command("status")
|
|
75
|
+
.description("Move a keyword to candidate, parked (with a reason), or targeted")
|
|
76
|
+
.argument("<id>", "Keyword id")
|
|
77
|
+
.argument("<status>", "candidate | parked | targeted")
|
|
78
|
+
.option("--parked-reason <reason>", "Required for parked: high-da | listicle-serp | mixed-intent | off-offer | ambiguous | online-duplicate | other")
|
|
79
|
+
.option("--json", "Output as JSON")
|
|
80
|
+
.action(async (id, status, opts) => {
|
|
81
|
+
try {
|
|
82
|
+
const data = await api.post(`/seo/keywords/${id}/status`, statusPayload(status, opts.parkedReason));
|
|
83
|
+
done(data, opts, `Keyword ${data.keyword}: ${data.status}`);
|
|
84
|
+
}
|
|
85
|
+
catch (err) {
|
|
86
|
+
handleError(err);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
const metricsCmd = new Command("metrics")
|
|
90
|
+
.description("Set a keyword's volume, difficulty, and SERP read in one market")
|
|
91
|
+
.argument("<id>", "Keyword id")
|
|
92
|
+
.argument("<market>", "Market code (us, gb, fr, be, ch, lu, mc)")
|
|
93
|
+
.option("--search-volume <n>", 'Monthly search volume ("null" for no data)')
|
|
94
|
+
.option("--keyword-difficulty <n>", "Keyword difficulty 0 to 100")
|
|
95
|
+
.option("--serp-file <path>", "JSON array of the top results: {position, url, domain, title?, domainAuthority?, pageAuthority?, onPageScore?}")
|
|
96
|
+
.option("--checked-at <iso>", "When the data was read (defaults to now)")
|
|
97
|
+
.option("--json", "Output as JSON")
|
|
98
|
+
.action(async (id, market, opts) => {
|
|
99
|
+
try {
|
|
100
|
+
const data = await api.post(`/seo/keywords/${id}/metrics/${market}`, compact({
|
|
101
|
+
searchVolume: nullableInt(opts.searchVolume, "search-volume"),
|
|
102
|
+
keywordDifficulty: nullableInt(opts.keywordDifficulty, "keyword-difficulty"),
|
|
103
|
+
serp: opts.serpFile ? readJsonFile(opts.serpFile) : undefined,
|
|
104
|
+
checkedAt: opts.checkedAt,
|
|
105
|
+
}));
|
|
106
|
+
done(data, opts, `Metrics set for ${market}`);
|
|
107
|
+
}
|
|
108
|
+
catch (err) {
|
|
109
|
+
handleError(err);
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
const deleteCmd = new Command("delete")
|
|
113
|
+
.description("Delete a keyword with its metrics and rankings")
|
|
114
|
+
.argument("<id>", "Keyword id")
|
|
115
|
+
.option("--json", "Output as JSON")
|
|
116
|
+
.action(async (id, opts) => {
|
|
117
|
+
try {
|
|
118
|
+
const data = await api.delete(`/seo/keywords/${id}`);
|
|
119
|
+
done(data, opts, `Keyword deleted: ${id}`);
|
|
120
|
+
}
|
|
121
|
+
catch (err) {
|
|
122
|
+
handleError(err);
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
export const seoKeywordWriteCommands = [
|
|
126
|
+
setCmd,
|
|
127
|
+
updateCmd,
|
|
128
|
+
statusCmd,
|
|
129
|
+
metricsCmd,
|
|
130
|
+
deleteCmd,
|
|
131
|
+
];
|
|
132
|
+
//# sourceMappingURL=seo-keyword-writes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seo-keyword-writes.js","sourceRoot":"","sources":["../../../src/commands/api/seo-keyword-writes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EACL,OAAO,EACP,IAAI,EAEJ,QAAQ,EACR,WAAW,EACX,SAAS,EACT,YAAY,GACb,MAAM,iBAAiB,CAAC;AAqBzB,SAAS,gBAAgB,CAAC,GAAY;IACpC,OAAO,GAAG;SACP,MAAM,CAAC,cAAc,EAAE,4BAA4B,CAAC;SACpD,MAAM,CAAC,mBAAmB,EAAE,2CAA2C,CAAC;SACxE,MAAM,CAAC,gBAAgB,EAAE,gDAAgD,CAAC;SAC1E,MAAM,CACL,mBAAmB,EACnB,2DAA2D,CAC5D;SACA,MAAM,CAAC,iBAAiB,EAAE,2CAA2C,CAAC;SACtE,MAAM,CAAC,kBAAkB,EAAE,+CAA+C,CAAC;SAC3E,MAAM,CAAC,kBAAkB,EAAE,2CAA2C,CAAC;SACvE,MAAM,CACL,mBAAmB,EACnB,sDAAsD,CACvD;SACA,MAAM,CAAC,gBAAgB,EAAE,mCAAmC,CAAC,CAAC;AACnE,CAAC;AAED,SAAS,YAAY,CAAC,IAAe;IACnC,OAAO,OAAO,CAAC;QACb,GAAG,EAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC;QACvB,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC;QACjC,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC;QAC7B,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC;QAC7B,SAAS,EAAE,WAAW,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC;QACnD,OAAO,EACL,IAAI,CAAC,OAAO,KAAK,SAAS;YACxB,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC;YACpC,CAAC,CAAC,SAAS;QACf,OAAO,EACL,IAAI,CAAC,OAAO,KAAK,SAAS;YACxB,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC;YACpC,CAAC,CAAC,SAAS;QACf,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC;QAC7B,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC;KAC5B,CAAC,CAAC;AACL,CAAC;AAED,SAAS,aAAa,CAAC,MAAc,EAAE,YAAqB;IAC1D,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC;AACrE,CAAC;AAED,MAAM,MAAM,GAAG,gBAAgB,CAC7B,IAAI,OAAO,CAAC,KAAK,CAAC;KACf,WAAW,CACV,wEAAwE,CACzE;KACA,QAAQ,CAAC,WAAW,EAAE,4CAA4C,CAAC;KACnE,cAAc,CAAC,mBAAmB,EAAE,SAAS,CAAC,CAClD;KACE,MAAM,CAAC,mBAAmB,EAAE,+BAA+B,CAAC;KAC5D,MAAM,CACL,0BAA0B,EAC1B,iHAAiH,CAClH;KACA,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC;KAClC,MAAM,CACL,KAAK,EACH,OAAe,EACf,IAKG,EACH,EAAE;IACF,IAAI,CAAC;QACH,IAAI,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,CAAa,eAAe,EAAE;YACrD,OAAO;YACP,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,GAAG,YAAY,CAAC,IAAI,CAAC;SACtB,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;QAC7B,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,CACnB,iBAAiB,IAAI,CAAC,EAAE,SAAS,EACjC,aAAa,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,YAAY,CAAC,CAC9C,CAAC;QACJ,CAAC;QACD,IAAI,CACF,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,EACpB,IAAI,EACJ,WAAW,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,KAAK,IAAI,CAAC,OAAO,KAAK,IAAI,CAAC,EAAE,GAAG,CAC3E,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,WAAW,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;AACH,CAAC,CACF,CAAC;AAEJ,MAAM,SAAS,GAAG,gBAAgB,CAChC,IAAI,OAAO,CAAC,QAAQ,CAAC;KAClB,WAAW,CAAC,wDAAwD,CAAC;KACrE,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC,CAClC;KACE,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC;KAClC,MAAM,CAAC,KAAK,EAAE,EAAU,EAAE,IAAyB,EAAE,EAAE;IACtD,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,CACzB,iBAAiB,EAAE,EAAE,EACrB,YAAY,CAAC,IAAI,CAAC,CACnB,CAAC;QACF,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,oBAAoB,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;IACvD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,WAAW,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,MAAM,SAAS,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC;KACpC,WAAW,CACV,kEAAkE,CACnE;KACA,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;KAC9B,QAAQ,CAAC,UAAU,EAAE,+BAA+B,CAAC;KACrD,MAAM,CACL,0BAA0B,EAC1B,gHAAgH,CACjH;KACA,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC;KAClC,MAAM,CACL,KAAK,EACH,EAAU,EACV,MAAc,EACd,IAAyC,EACzC,EAAE;IACF,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,CACzB,iBAAiB,EAAE,SAAS,EAC5B,aAAa,CAAC,MAAM,EAAE,IAAI,CAAC,YAAY,CAAC,CACzC,CAAC;QACF,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,WAAW,IAAI,CAAC,OAAO,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IAC9D,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,WAAW,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;AACH,CAAC,CACF,CAAC;AAEJ,MAAM,UAAU,GAAG,IAAI,OAAO,CAAC,SAAS,CAAC;KACtC,WAAW,CACV,iEAAiE,CAClE;KACA,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;KAC9B,QAAQ,CAAC,UAAU,EAAE,0CAA0C,CAAC;KAChE,MAAM,CAAC,qBAAqB,EAAE,4CAA4C,CAAC;KAC3E,MAAM,CAAC,0BAA0B,EAAE,6BAA6B,CAAC;KACjE,MAAM,CACL,oBAAoB,EACpB,gHAAgH,CACjH;KACA,MAAM,CAAC,oBAAoB,EAAE,0CAA0C,CAAC;KACxE,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC;KAClC,MAAM,CACL,KAAK,EACH,EAAU,EACV,MAAc,EACd,IAKC,EACD,EAAE;IACF,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,CACzB,iBAAiB,EAAE,YAAY,MAAM,EAAE,EACvC,OAAO,CAAC;YACN,YAAY,EAAE,WAAW,CAAC,IAAI,CAAC,YAAY,EAAE,eAAe,CAAC;YAC7D,iBAAiB,EAAE,WAAW,CAC5B,IAAI,CAAC,iBAAiB,EACtB,oBAAoB,CACrB;YACD,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS;YAC7D,SAAS,EAAE,IAAI,CAAC,SAAS;SAC1B,CAAC,CACH,CAAC;QACF,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,mBAAmB,MAAM,EAAE,CAAC,CAAC;IAChD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,WAAW,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;AACH,CAAC,CACF,CAAC;AAEJ,MAAM,SAAS,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC;KACpC,WAAW,CAAC,gDAAgD,CAAC;KAC7D,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;KAC9B,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC;KAClC,MAAM,CAAC,KAAK,EAAE,EAAU,EAAE,IAAa,EAAE,EAAE;IAC1C,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,MAAM,CAAU,iBAAiB,EAAE,EAAE,CAAC,CAAC;QAC9D,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,oBAAoB,EAAE,EAAE,CAAC,CAAC;IAC7C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,WAAW,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,MAAM;IACN,SAAS;IACT,SAAS;IACT,UAAU;IACV,SAAS;CACV,CAAC"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import { api } from "../../lib/api.js";
|
|
4
|
+
import { handleError, printDetail, printList } from "../../lib/format.js";
|
|
5
|
+
import { printJson, qs } from "./seo-shared.js";
|
|
6
|
+
import { seoKeywordWriteCommands } from "./seo-keyword-writes.js";
|
|
7
|
+
const listCmd = new Command("list")
|
|
8
|
+
.description("List keywords with per-market volume and latest position")
|
|
9
|
+
.option("--language <lang>", "en | fr")
|
|
10
|
+
.option("--status <status>", "candidate | parked | targeted")
|
|
11
|
+
.option("--hub <slug>", "Hub slug")
|
|
12
|
+
.option("--page-id <id>", "Keywords of one page")
|
|
13
|
+
.option("--tracked <bool>", "true | false")
|
|
14
|
+
.option("--q <text>", "Keyword contains")
|
|
15
|
+
.option("--page <n>", "Page number (default 1)")
|
|
16
|
+
.option("--page-size <n>", "Page size (default 100, max 1000)")
|
|
17
|
+
.option("--json", "Output as JSON")
|
|
18
|
+
.action(async (opts) => {
|
|
19
|
+
try {
|
|
20
|
+
const { data, meta } = await api.getWithMeta(`/seo/keywords${qs({
|
|
21
|
+
language: opts.language,
|
|
22
|
+
status: opts.status,
|
|
23
|
+
hub: opts.hub,
|
|
24
|
+
pageId: opts.pageId,
|
|
25
|
+
tracked: opts.tracked,
|
|
26
|
+
q: opts.q,
|
|
27
|
+
page: opts.page,
|
|
28
|
+
pageSize: opts.pageSize,
|
|
29
|
+
})}`);
|
|
30
|
+
if (opts.json) {
|
|
31
|
+
printJson({ data, meta });
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
printList(data.map((k) => ({
|
|
35
|
+
...k,
|
|
36
|
+
markets: (k.markets ?? [])
|
|
37
|
+
.map((m) => `${m.market}:${m.searchVolume ?? "-"}/#${m.position ?? "-"}`)
|
|
38
|
+
.join(" "),
|
|
39
|
+
state: k.status === "parked" ? `parked (${k.parkedReason})` : k.status,
|
|
40
|
+
})), [
|
|
41
|
+
{ key: "keyword", label: "Keyword", width: 36 },
|
|
42
|
+
{ key: "language", label: "Lang", width: 4 },
|
|
43
|
+
{ key: "state", label: "Status", width: 22 },
|
|
44
|
+
{ key: "hubSlug", label: "Hub", width: 12 },
|
|
45
|
+
{ key: "pagePath", label: "Page", width: 28 },
|
|
46
|
+
{ key: "markets", label: "Market:volume/#position", width: 30 },
|
|
47
|
+
{ key: "id", label: "Id", width: 36 },
|
|
48
|
+
], opts);
|
|
49
|
+
if (meta) {
|
|
50
|
+
console.log(chalk.dim(`page ${meta.page}/${meta.totalPages}, ${meta.total} total`));
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
catch (err) {
|
|
54
|
+
handleError(err);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
const getCmd = new Command("get")
|
|
58
|
+
.description("Show a keyword with its SERP reads per market and rank history")
|
|
59
|
+
.argument("<id>", "Keyword id")
|
|
60
|
+
.option("--json", "Output as JSON")
|
|
61
|
+
.action(async (id, opts) => {
|
|
62
|
+
try {
|
|
63
|
+
const data = await api.get(`/seo/keywords/${id}`);
|
|
64
|
+
if (opts.json) {
|
|
65
|
+
printJson(data);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
printDetail(data, [
|
|
69
|
+
{ key: "keyword", label: "Keyword" },
|
|
70
|
+
{ key: "language", label: "Language" },
|
|
71
|
+
{ key: "status", label: "Status" },
|
|
72
|
+
{ key: "parkedReason", label: "Parked reason" },
|
|
73
|
+
{ key: "hubSlug", label: "Hub" },
|
|
74
|
+
{ key: "category", label: "Category" },
|
|
75
|
+
{ key: "pagePath", label: "Page" },
|
|
76
|
+
{ key: "intent", label: "Intent" },
|
|
77
|
+
{ key: "relevance", label: "Relevance" },
|
|
78
|
+
{ key: "tracked", label: "Tracked" },
|
|
79
|
+
{ key: "branded", label: "Branded" },
|
|
80
|
+
{ key: "source", label: "Source" },
|
|
81
|
+
{ key: "notes", label: "Notes" },
|
|
82
|
+
], opts);
|
|
83
|
+
for (const m of data.metrics) {
|
|
84
|
+
const serp = (m.serp ?? [])
|
|
85
|
+
.map((r) => `#${r.position} ${r.domain} DA${r.domainAuthority ?? "?"}`)
|
|
86
|
+
.join(", ");
|
|
87
|
+
console.log(` ${chalk.cyan(m.market)} volume ${m.searchVolume ?? "-"}, KD ${m.keywordDifficulty ?? "-"}${serp ? chalk.dim(`\n ${serp}`) : ""}`);
|
|
88
|
+
}
|
|
89
|
+
if (data.rankings.length) {
|
|
90
|
+
console.log(chalk.dim(` ${data.rankings.length} ranking rows`));
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
catch (err) {
|
|
94
|
+
handleError(err);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
export const seoKeywordCommand = new Command("keyword")
|
|
98
|
+
.description("Keywords per language, qualified by SERP read, linked to pages")
|
|
99
|
+
.addCommand(listCmd)
|
|
100
|
+
.addCommand(getCmd);
|
|
101
|
+
for (const cmd of seoKeywordWriteCommands)
|
|
102
|
+
seoKeywordCommand.addCommand(cmd);
|
|
103
|
+
//# sourceMappingURL=seo-keywords.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seo-keywords.js","sourceRoot":"","sources":["../../../src/commands/api/seo-keywords.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { api } from "../../lib/api.js";
|
|
3
|
+
import { handleError } from "../../lib/format.js";
|
|
4
|
+
import { compact, done, nullable, nullableInt, readJsonObject, } from "./seo-shared.js";
|
|
5
|
+
function withContentOptions(cmd) {
|
|
6
|
+
return cmd
|
|
7
|
+
.option("--hub <slug>", 'Hub slug ("null" to clear)')
|
|
8
|
+
.option("--category <name>", 'Category inside the hub ("null" to clear)')
|
|
9
|
+
.option("--primary-keyword-id <id>", 'Primary keyword ("null" to clear)')
|
|
10
|
+
.option("--title <text>", "Page title: Keyword | Benefit | ITzWorking")
|
|
11
|
+
.option("--meta-description <text>", "Meta description (120 to 158 chars)")
|
|
12
|
+
.option("--og-title <text>", "Open Graph title")
|
|
13
|
+
.option("--og-description <text>", "Open Graph description")
|
|
14
|
+
.option("--h1 <text>", "H1")
|
|
15
|
+
.option("--intro <text>", "Opening paragraph (keyword near the start)")
|
|
16
|
+
.option("--on-page-score <n>", "On-page grader score 0 to 100")
|
|
17
|
+
.option("--notes <text>", 'Content notes ("null" to clear)')
|
|
18
|
+
.option("--file <path>", "JSON object merged into the payload for structured fields: brief {searcher, want, goal}, sections [{heading, body}], cta {label, url}, images [{fileId, alt}]; flags win over the file");
|
|
19
|
+
}
|
|
20
|
+
function contentPayload(opts) {
|
|
21
|
+
const fromFile = opts.file ? readJsonObject(opts.file) : {};
|
|
22
|
+
return {
|
|
23
|
+
...fromFile,
|
|
24
|
+
...compact({
|
|
25
|
+
hub: nullable(opts.hub),
|
|
26
|
+
category: nullable(opts.category),
|
|
27
|
+
primaryKeywordId: nullable(opts.primaryKeywordId),
|
|
28
|
+
title: nullable(opts.title),
|
|
29
|
+
metaDescription: nullable(opts.metaDescription),
|
|
30
|
+
ogTitle: nullable(opts.ogTitle),
|
|
31
|
+
ogDescription: nullable(opts.ogDescription),
|
|
32
|
+
h1: nullable(opts.h1),
|
|
33
|
+
intro: nullable(opts.intro),
|
|
34
|
+
onPageScore: nullableInt(opts.onPageScore, "on-page-score"),
|
|
35
|
+
notes: nullable(opts.notes),
|
|
36
|
+
}),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
const createCmd = withContentOptions(new Command("create")
|
|
40
|
+
.description("Track a page: nexus pages start planned, code pages (already on the site) start published")
|
|
41
|
+
.requiredOption("--path <path>", "URL path as served (/services/x, /fr/...)")
|
|
42
|
+
.requiredOption("--language <lang>", "en | fr (must match the path prefix)")
|
|
43
|
+
.option("--managed-by <who>", "nexus (default) | code"))
|
|
44
|
+
.option("--json", "Output as JSON")
|
|
45
|
+
.action(async (opts) => {
|
|
46
|
+
try {
|
|
47
|
+
const data = await api.post("/seo/pages", {
|
|
48
|
+
...contentPayload(opts),
|
|
49
|
+
...compact({
|
|
50
|
+
path: opts.path,
|
|
51
|
+
language: opts.language,
|
|
52
|
+
managedBy: opts.managedBy,
|
|
53
|
+
}),
|
|
54
|
+
});
|
|
55
|
+
done(data, opts, `Page created: ${data.path} (${data.id})`);
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
handleError(err);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
const updateCmd = withContentOptions(new Command("update")
|
|
62
|
+
.description("Update a page's content and placement (status has its own command)")
|
|
63
|
+
.argument("<id>", "Page id")
|
|
64
|
+
.option("--path <path>", "New path (refused once published)"))
|
|
65
|
+
.option("--json", "Output as JSON")
|
|
66
|
+
.action(async (id, opts) => {
|
|
67
|
+
try {
|
|
68
|
+
const data = await api.post(`/seo/pages/${id}`, {
|
|
69
|
+
...contentPayload(opts),
|
|
70
|
+
...compact({ path: opts.path }),
|
|
71
|
+
});
|
|
72
|
+
done(data, opts, `Page updated: ${data.path}`);
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
handleError(err);
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
const statusCmd = new Command("status")
|
|
79
|
+
.description("Move a page through planned, drafted, approved, published, retired (approve and publish are human acts)")
|
|
80
|
+
.argument("<id>", "Page id")
|
|
81
|
+
.argument("<status>", "planned | drafted | approved | published | retired")
|
|
82
|
+
.option("--json", "Output as JSON")
|
|
83
|
+
.action(async (id, status, opts) => {
|
|
84
|
+
try {
|
|
85
|
+
const data = await api.post(`/seo/pages/${id}/status`, {
|
|
86
|
+
status,
|
|
87
|
+
});
|
|
88
|
+
done(data, opts, `Page ${data.path}: ${data.status}`);
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
handleError(err);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
const alternateCmd = new Command("alternate")
|
|
95
|
+
.description("Pair a page with its counterpart in the other language (hreflang)")
|
|
96
|
+
.argument("<id>", "Page id")
|
|
97
|
+
.argument("<pageId>", 'Counterpart page id, or "none" to unpair')
|
|
98
|
+
.option("--json", "Output as JSON")
|
|
99
|
+
.action(async (id, pageId, opts) => {
|
|
100
|
+
try {
|
|
101
|
+
const data = await api.post(`/seo/pages/${id}/alternate`, {
|
|
102
|
+
pageId: pageId === "none" ? null : pageId,
|
|
103
|
+
});
|
|
104
|
+
done(data, opts, `Alternate set on ${data.path}`);
|
|
105
|
+
}
|
|
106
|
+
catch (err) {
|
|
107
|
+
handleError(err);
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
const deleteCmd = new Command("delete")
|
|
111
|
+
.description("Delete a page that never went live (published pages are retired instead)")
|
|
112
|
+
.argument("<id>", "Page id")
|
|
113
|
+
.option("--json", "Output as JSON")
|
|
114
|
+
.action(async (id, opts) => {
|
|
115
|
+
try {
|
|
116
|
+
const data = await api.delete(`/seo/pages/${id}`);
|
|
117
|
+
done(data, opts, `Page deleted: ${id}`);
|
|
118
|
+
}
|
|
119
|
+
catch (err) {
|
|
120
|
+
handleError(err);
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
export const seoPageWriteCommands = [
|
|
124
|
+
createCmd,
|
|
125
|
+
updateCmd,
|
|
126
|
+
statusCmd,
|
|
127
|
+
alternateCmd,
|
|
128
|
+
deleteCmd,
|
|
129
|
+
];
|
|
130
|
+
//# sourceMappingURL=seo-page-writes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seo-page-writes.js","sourceRoot":"","sources":["../../../src/commands/api/seo-page-writes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import { api } from "../../lib/api.js";
|
|
4
|
+
import { handleError, printDetail, printList } from "../../lib/format.js";
|
|
5
|
+
import { printJson, qs } from "./seo-shared.js";
|
|
6
|
+
import { seoPageWriteCommands } from "./seo-page-writes.js";
|
|
7
|
+
function perfCells(p) {
|
|
8
|
+
return {
|
|
9
|
+
clicks: p?.clicks,
|
|
10
|
+
impressions: p?.impressions,
|
|
11
|
+
ctr: p ? `${(p.ctr * 100).toFixed(1)}%` : undefined,
|
|
12
|
+
position: p?.position != null ? p.position.toFixed(1) : undefined,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
const listCmd = new Command("list")
|
|
16
|
+
.description("List pages with Search Console totals and conversions over a window")
|
|
17
|
+
.option("--status <status>", "planned | drafted | approved | published | retired")
|
|
18
|
+
.option("--language <lang>", "en | fr")
|
|
19
|
+
.option("--hub <slug>", "Hub slug")
|
|
20
|
+
.option("--managed-by <who>", "code | nexus")
|
|
21
|
+
.option("--days <n>", "Window in days ending on the latest complete day (default 28)")
|
|
22
|
+
.option("--json", "Output as JSON")
|
|
23
|
+
.action(async (opts) => {
|
|
24
|
+
try {
|
|
25
|
+
const { data, meta } = await api.getWithMeta(`/seo/pages${qs({
|
|
26
|
+
status: opts.status,
|
|
27
|
+
language: opts.language,
|
|
28
|
+
hub: opts.hub,
|
|
29
|
+
managedBy: opts.managedBy,
|
|
30
|
+
days: opts.days,
|
|
31
|
+
})}`);
|
|
32
|
+
if (opts.json) {
|
|
33
|
+
printJson({ data, meta });
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
printList(data.map((p) => ({
|
|
37
|
+
...p,
|
|
38
|
+
...perfCells(p.performance),
|
|
39
|
+
leads: p.conversions.captures +
|
|
40
|
+
p.conversions.forgeSessions +
|
|
41
|
+
p.conversions.leads,
|
|
42
|
+
})), [
|
|
43
|
+
{ key: "path", label: "Path", width: 34 },
|
|
44
|
+
{ key: "status", label: "Status", width: 10 },
|
|
45
|
+
{ key: "managedBy", label: "By", width: 6 },
|
|
46
|
+
{ key: "primaryKeyword", label: "Primary keyword", width: 28 },
|
|
47
|
+
{ key: "clicks", label: "Clicks", width: 6 },
|
|
48
|
+
{ key: "impressions", label: "Impr.", width: 6 },
|
|
49
|
+
{ key: "ctr", label: "CTR", width: 6 },
|
|
50
|
+
{ key: "position", label: "Pos.", width: 5 },
|
|
51
|
+
{ key: "leads", label: "Conv.", width: 5 },
|
|
52
|
+
{ key: "id", label: "Id", width: 36 },
|
|
53
|
+
], opts);
|
|
54
|
+
if (meta) {
|
|
55
|
+
console.log(chalk.dim(`window ${meta.window.from} to ${meta.window.to}`));
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
handleError(err);
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
const getCmd = new Command("get")
|
|
63
|
+
.description("Show a page: content, keywords, alternate, performance, conversions")
|
|
64
|
+
.argument("<id>", "Page id")
|
|
65
|
+
.option("--days <n>", "Performance window in days (default 28)")
|
|
66
|
+
.option("--json", "Output as JSON")
|
|
67
|
+
.action(async (id, opts) => {
|
|
68
|
+
try {
|
|
69
|
+
const data = await api.get(`/seo/pages/${id}${qs({ days: opts.days })}`);
|
|
70
|
+
if (opts.json) {
|
|
71
|
+
printJson(data);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const p = perfCells(data.performance);
|
|
75
|
+
printDetail({
|
|
76
|
+
...data,
|
|
77
|
+
alternatePath: data.alternate?.path,
|
|
78
|
+
keywordList: data.keywords.map((k) => k.keyword).join(", "),
|
|
79
|
+
headings: data.sections.map((s) => s.heading).join(" / "),
|
|
80
|
+
perf: data.performance
|
|
81
|
+
? `${p.clicks} clicks, ${p.impressions} impressions, CTR ${p.ctr}, position ${p.position ?? "-"}`
|
|
82
|
+
: null,
|
|
83
|
+
conv: `${data.conversions.captures} captures, ${data.conversions.forgeSessions} Forge sessions, ${data.conversions.leads} leads`,
|
|
84
|
+
}, [
|
|
85
|
+
{ key: "path", label: "Path" },
|
|
86
|
+
{ key: "language", label: "Language" },
|
|
87
|
+
{ key: "status", label: "Status" },
|
|
88
|
+
{ key: "managedBy", label: "Managed by" },
|
|
89
|
+
{ key: "title", label: "Title" },
|
|
90
|
+
{ key: "metaDescription", label: "Meta description" },
|
|
91
|
+
{ key: "h1", label: "H1" },
|
|
92
|
+
{ key: "intro", label: "Intro" },
|
|
93
|
+
{ key: "headings", label: "H2s" },
|
|
94
|
+
{ key: "keywordList", label: "Keywords" },
|
|
95
|
+
{ key: "alternatePath", label: "Alternate" },
|
|
96
|
+
{ key: "perf", label: "Search Console" },
|
|
97
|
+
{ key: "conv", label: "Conversions" },
|
|
98
|
+
], opts);
|
|
99
|
+
console.log(chalk.dim(` window ${data.window.from} to ${data.window.to}`));
|
|
100
|
+
}
|
|
101
|
+
catch (err) {
|
|
102
|
+
handleError(err);
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
const conversionsCmd = new Command("conversions")
|
|
106
|
+
.description("List the captures, Forge sessions, and leads that landed on a page")
|
|
107
|
+
.argument("<id>", "Page id")
|
|
108
|
+
.option("--days <n>", "Window in days (default 28)")
|
|
109
|
+
.option("--json", "Output as JSON")
|
|
110
|
+
.action(async (id, opts) => {
|
|
111
|
+
try {
|
|
112
|
+
const data = await api.get(`/seo/pages/${id}/conversions${qs({ days: opts.days })}`);
|
|
113
|
+
if (opts.json) {
|
|
114
|
+
printJson(data);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
console.log(chalk.bold(data.path), chalk.dim(`${data.window.from} to ${data.window.to}`));
|
|
118
|
+
for (const c of data.captures) {
|
|
119
|
+
console.log(` capture ${c.createdAt} ${c.formName ?? "-"} ${c.email}`);
|
|
120
|
+
}
|
|
121
|
+
for (const s of data.forgeSessions) {
|
|
122
|
+
console.log(` forge ${s.createdAt} ${s.status} ${s.name}`);
|
|
123
|
+
}
|
|
124
|
+
for (const l of data.leads) {
|
|
125
|
+
console.log(` lead ${l.createdAt} ${l.status} ${l.title}`);
|
|
126
|
+
}
|
|
127
|
+
if (!data.captures.length &&
|
|
128
|
+
!data.forgeSessions.length &&
|
|
129
|
+
!data.leads.length) {
|
|
130
|
+
console.log(chalk.dim(" No conversions."));
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
catch (err) {
|
|
134
|
+
handleError(err);
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
export const seoPageCommand = new Command("page")
|
|
138
|
+
.description("SEO pages: content, approval status, hreflang pairs, conversions")
|
|
139
|
+
.addCommand(listCmd)
|
|
140
|
+
.addCommand(getCmd)
|
|
141
|
+
.addCommand(conversionsCmd);
|
|
142
|
+
for (const cmd of seoPageWriteCommands)
|
|
143
|
+
seoPageCommand.addCommand(cmd);
|
|
144
|
+
//# sourceMappingURL=seo-pages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seo-pages.js","sourceRoot":"","sources":["../../../src/commands/api/seo-pages.ts"],"names":[],"mappings":"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"}
|