@nuxtseo/cli 0.5.0 → 0.5.3
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.js +9 -3
- package/dist/pull.js +15 -0
- package/dist/render.js +20 -4
- package/package.json +3 -3
- package/skills/nuxtseo-cli/SKILL.md +71 -5
- package/skills/nuxtseo-cli/references/commands.md +61 -14
package/dist/commands.js
CHANGED
|
@@ -1223,7 +1223,11 @@ async function actionDismiss(runtime, globals, args) {
|
|
|
1223
1223
|
return fail(EXIT_CODE.invalidInput, 'Pass the action id to dismiss.', undefined, 'invalid_cli_input');
|
|
1224
1224
|
if (!args.artifactVersion)
|
|
1225
1225
|
return fail(EXIT_CODE.invalidInput, 'Pass --artifact-version, the artifactVersion returned with this action.', undefined, 'invalid_cli_input');
|
|
1226
|
-
|
|
1226
|
+
if (args.note !== undefined && (!args.note.trim() || args.note.trim().length > 2000))
|
|
1227
|
+
return fail(EXIT_CODE.invalidInput, 'Pass --note with 1 to 2000 characters.', undefined, 'invalid_cli_input');
|
|
1228
|
+
const confirmed = await confirmMutation(runtime, globals, args.note
|
|
1229
|
+
? `Dismiss action ${args.actionId}? Your note records this decision. No fix is verified.`
|
|
1230
|
+
: `Dismiss action ${args.actionId}? The page stays removed.`);
|
|
1227
1231
|
if (confirmed._tag === 'Err')
|
|
1228
1232
|
return confirmed;
|
|
1229
1233
|
if (!confirmed.value) {
|
|
@@ -1235,7 +1239,7 @@ async function actionDismiss(runtime, globals, args) {
|
|
|
1235
1239
|
return resolved;
|
|
1236
1240
|
const response = await withSpinner(runtime, 'Dismissing action', () => resolved.value.api.client.actions.dismiss({
|
|
1237
1241
|
params: { siteId: resolved.value.siteId, actionId: args.actionId },
|
|
1238
|
-
body: { artifactVersion: args.artifactVersion },
|
|
1242
|
+
body: { artifactVersion: args.artifactVersion, ...(args.note !== undefined ? { note: args.note.trim() } : {}) },
|
|
1239
1243
|
}, { signal: runtime.requestSignal }));
|
|
1240
1244
|
return present(runtime, globals, response, value => renderActionDismissal(value.data));
|
|
1241
1245
|
}
|
|
@@ -1559,14 +1563,16 @@ export function createRootCommand(runtime, globals, execution) {
|
|
|
1559
1563
|
run: ({ args }) => capture(execution, () => actionsResolve(runtime, globals, args.actionId), args._, 1)(),
|
|
1560
1564
|
}),
|
|
1561
1565
|
dismiss: defineCommand({
|
|
1562
|
-
meta: { name: 'dismiss', description: 'Dismiss a
|
|
1566
|
+
meta: { name: 'dismiss', description: 'Dismiss reviewed work with a note, or confirm an unlinked page removal' },
|
|
1563
1567
|
args: {
|
|
1564
1568
|
'actionId': positional('action-id', 'Action ID'),
|
|
1565
1569
|
'artifact-version': { type: 'string', description: 'The artifactVersion returned with this action' },
|
|
1570
|
+
'note': { type: 'string', description: 'Why this action is intentional or incorrect, 1 to 2000 characters' },
|
|
1566
1571
|
},
|
|
1567
1572
|
run: ({ args }) => capture(execution, () => actionDismiss(runtime, globals, {
|
|
1568
1573
|
actionId: args.actionId,
|
|
1569
1574
|
artifactVersion: args['artifact-version'],
|
|
1575
|
+
note: args.note,
|
|
1570
1576
|
}), args._, 1)(),
|
|
1571
1577
|
}),
|
|
1572
1578
|
},
|
package/dist/pull.js
CHANGED
|
@@ -304,6 +304,7 @@ export async function runPull(runtime, globals, args, resolve, catalogue = PULL_
|
|
|
304
304
|
const skipped = [];
|
|
305
305
|
let stopped = false;
|
|
306
306
|
let completed = 0;
|
|
307
|
+
let explainedAnalyticsConnection = false;
|
|
307
308
|
await forEachBounded(operations, concurrency.value, async (candidate) => {
|
|
308
309
|
if (stopped) {
|
|
309
310
|
skipped.push(candidate.name);
|
|
@@ -318,6 +319,15 @@ export async function runPull(runtime, globals, args, resolve, catalogue = PULL_
|
|
|
318
319
|
});
|
|
319
320
|
const outcome = pullLine(candidate.name, result);
|
|
320
321
|
writeProtocolResponse(runtime, outcome.line);
|
|
322
|
+
if (!explainedAnalyticsConnection
|
|
323
|
+
&& candidate.name.startsWith('analytics ')
|
|
324
|
+
&& result._tag === 'Err'
|
|
325
|
+
&& result.error._tag === 'ApiFailure'
|
|
326
|
+
&& result.error.code === 'conflict'
|
|
327
|
+
&& result.error.details?.action === 'connect_web_analytics') {
|
|
328
|
+
explainedAnalyticsConnection = true;
|
|
329
|
+
writeDiagnostic(runtime, 'Web Analytics is not connected. Connect a property to read these views. For a full SEO pull, use --exclude analytics.');
|
|
330
|
+
}
|
|
321
331
|
exitCodes.push(outcome.exitCode);
|
|
322
332
|
completed++;
|
|
323
333
|
// An expired or rejected credential fails every later read the same way.
|
|
@@ -325,6 +335,11 @@ export async function runPull(runtime, globals, args, resolve, catalogue = PULL_
|
|
|
325
335
|
if (outcome.exitCode === EXIT_CODE.authentication || outcome.exitCode === EXIT_CODE.interrupted)
|
|
326
336
|
stopped = true;
|
|
327
337
|
writeDiagnostic(runtime, `[${completed}/${operations.length}] ${candidate.name} ${outcome.failure ? `failed: ${outcome.failure.code}` : 'ok'}`);
|
|
338
|
+
if (outcome.failure?.code === 'request_timeout' && timeoutMs < 300_000) {
|
|
339
|
+
const retryTimeout = Math.min(timeoutMs * 2, 300_000);
|
|
340
|
+
// Retry only this read. Repeating a full paid pull can spend twice.
|
|
341
|
+
writeDiagnostic(runtime, `Retry: nuxtseo pull --site ${resolved.value.siteId} --include ${JSON.stringify(candidate.name)} --period ${period.value} --timeout-ms ${retryTimeout}${candidate.spendsResearch ? ' --with-research' : ''} --json`);
|
|
342
|
+
}
|
|
328
343
|
});
|
|
329
344
|
const failed = exitCodes.filter(code => code !== EXIT_CODE.success).length;
|
|
330
345
|
writeDiagnostic(runtime, [
|
package/dist/render.js
CHANGED
|
@@ -445,7 +445,7 @@ export function renderIndexingDiagnostics(data) {
|
|
|
445
445
|
if (data.urls.length === 0)
|
|
446
446
|
return 'No Search Console indexing URLs match these filters.';
|
|
447
447
|
return [
|
|
448
|
-
`Search Console indexing URLs (${data.urls.length} of ${data.total})`,
|
|
448
|
+
`Search Console indexing URLs (${data.urls.length} of ${data.totalSemantics === 'lower-bound' ? 'at least ' : ''}${data.total})`,
|
|
449
449
|
...data.urls.map(row => `${row.verdict ?? 'unknown'} ${row.coverageState ?? 'unknown'}\n ${row.url}`),
|
|
450
450
|
data.hasMore ? `More URLs available after offset ${data.offset + data.limit}.` : '',
|
|
451
451
|
].filter(Boolean).join('\n');
|
|
@@ -893,10 +893,26 @@ export function renderScanDetail(data) {
|
|
|
893
893
|
];
|
|
894
894
|
if (data.lcpElement)
|
|
895
895
|
blocks.push(`LCP element ${data.lcpElement.selector ?? data.lcpElement.nodeLabel ?? 'unknown'}`);
|
|
896
|
-
if (data.
|
|
896
|
+
if (data.observedTrace?._tag === 'available') {
|
|
897
|
+
const trace = data.observedTrace;
|
|
897
898
|
blocks.push([
|
|
898
|
-
`
|
|
899
|
-
...
|
|
899
|
+
`Observed trace LCP ${trace.observedLcpMs}ms throttling ${trace.throttlingMethod}`,
|
|
900
|
+
...trace.phases.map(phase => ` ${phase.id} ${phase.durationMs}ms`),
|
|
901
|
+
'Trace phases describe observed LCP. Reported LCP can be simulated.',
|
|
902
|
+
].join('\n'));
|
|
903
|
+
}
|
|
904
|
+
else {
|
|
905
|
+
blocks.push(`Observed trace unavailable ${data.observedTrace?.reason ?? 'legacy-response'}`);
|
|
906
|
+
}
|
|
907
|
+
if (data.javascript) {
|
|
908
|
+
const bytes = (amount) => amount === null ? 'unknown' : `${amount}b`;
|
|
909
|
+
blocks.push(`JavaScript ${bytes(data.javascript.transferBytes)} transferred ${bytes(data.javascript.decodedBytes)} decoded ${data.javascript.scriptCount ?? 'unknown'} resources`);
|
|
910
|
+
}
|
|
911
|
+
const waste = data.performanceIssues.filter(issue => issue.subtype !== 'js-transfer-weight');
|
|
912
|
+
if (waste.length) {
|
|
913
|
+
blocks.push([
|
|
914
|
+
`Wasteful assets (${waste.length})`,
|
|
915
|
+
...waste.map(issue => ` ${issue.wastedMs ?? 0}ms ${issue.wastedBytes ?? 0}b ${issue.subtype ?? issue.type} ${issue.url ?? ''}`.trimEnd()),
|
|
900
916
|
].join('\n'));
|
|
901
917
|
}
|
|
902
918
|
if (data.thirdParties.length) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nuxtseo/cli",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.5.
|
|
4
|
+
"version": "0.5.3",
|
|
5
5
|
"description": "Command line interface for the Nuxt SEO public API.",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"homepage": "https://nuxtseo.com/pro",
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@clack/prompts": "^1.8.0",
|
|
36
|
-
"@nuxtseo/protocol": "^0.5.
|
|
37
|
-
"@nuxtseo/sdk": "^0.5.
|
|
36
|
+
"@nuxtseo/protocol": "^0.5.3",
|
|
37
|
+
"@nuxtseo/sdk": "^0.5.3",
|
|
38
38
|
"citty": "^0.2.2",
|
|
39
39
|
"pathe": "^2.0.3"
|
|
40
40
|
},
|
|
@@ -28,8 +28,18 @@ Read the matching file before you act on its subject:
|
|
|
28
28
|
pnpm add -g @nuxtseo/cli # global install, Node 22+
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
-
Inside the Nuxt SEO monorepo,
|
|
32
|
-
|
|
31
|
+
Inside the Nuxt SEO monorepo, build the workspace dependencies in order
|
|
32
|
+
before using `node packages/cli/dist/cli-entry.js`:
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
pnpm --filter @nuxtseo/protocol build
|
|
36
|
+
pnpm --filter @nuxtseo/sdk build
|
|
37
|
+
pnpm --filter @nuxtseo/cli build
|
|
38
|
+
node packages/cli/dist/cli-entry.js --version --json
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Use a task-owned worktree. Missing `dist` files and missing named exports
|
|
42
|
+
can mean stale builds. Rebuild all three packages before diagnosing source.
|
|
33
43
|
|
|
34
44
|
2. **Skill version.** Run `nuxtseo --version --json`. Compare the CLI version
|
|
35
45
|
with this file's frontmatter version. If the CLI is older, update the CLI
|
|
@@ -112,10 +122,20 @@ nuxtseo status --site <site-id> --json
|
|
|
112
122
|
Route family: a lead to check, never the Site verdict. `assessment.aggregate`
|
|
113
123
|
is always the whole-Site verdict. If `healthStage` is `quality_rejection`,
|
|
114
124
|
the whole Site is affected, whatever a route family shows.
|
|
125
|
+
`quality_rejection` is a broad indexing stage. It includes discovery gaps.
|
|
126
|
+
Read the summary and Google coverage reasons before blaming content quality.
|
|
127
|
+
It does not prove that Google crawled and rejected the pages.
|
|
128
|
+
The stored assessment and retained indexing summary have separate clocks.
|
|
129
|
+
Compare `assessment.assessedAt` with indexing `asOf` before comparing their counts.
|
|
115
130
|
- Read `dataQuality.status` before you quote the verdict. `degraded` means
|
|
116
131
|
proofs were missing, so the verdict is Provisional. `unavailable` means it
|
|
117
132
|
has not run.
|
|
118
133
|
- If `nextAction.kind` is `action`, pass its `actionId` to step 3.
|
|
134
|
+
- `openCount` counts open and in-progress Actions. `actions list` returns the
|
|
135
|
+
admitted, unclaimed worklist. These counts can differ. A stored Next Action
|
|
136
|
+
can still be readable through `actions show` when the worklist omits it.
|
|
137
|
+
- A `candidate:` finding with diagnosis `Shadow observation` is a canary,
|
|
138
|
+
not a verified repair cause. Inspect its details before proposing work.
|
|
119
139
|
|
|
120
140
|
For the whole Site instead of the next action, run one `pull`. It performs
|
|
121
141
|
every spend-free Site read and writes one envelope per line:
|
|
@@ -124,6 +144,18 @@ every spend-free Site read and writes one envelope per line:
|
|
|
124
144
|
nuxtseo pull --site <site-id> --json > site.ndjson
|
|
125
145
|
```
|
|
126
146
|
|
|
147
|
+
Inspect every line's `command` and `error`. If one read times out, retry that
|
|
148
|
+
read with the suggested timeout. Do not repeat successful or paid reads.
|
|
149
|
+
If the longer request returns a provider failure, report the request ID.
|
|
150
|
+
Retained `page issues` rows can name URLs, but do not replace Google's verdict.
|
|
151
|
+
|
|
152
|
+
For full analytics exports, use `--all --limit 100`. Each run stops after
|
|
153
|
+
50 requests. If it exits with `paging_cap_reached`, preserve the arguments
|
|
154
|
+
and continue with the printed resume argument. Save each run separately.
|
|
155
|
+
Check row keys for repeats across pages. Repeated keyword rows can indicate
|
|
156
|
+
unstable upstream ordering. Report that gap instead of claiming complete
|
|
157
|
+
keyword coverage. Use Site timeseries totals for the Site-wide comparison.
|
|
158
|
+
|
|
127
159
|
**2. Pick a ranked action.**
|
|
128
160
|
|
|
129
161
|
```sh
|
|
@@ -133,6 +165,10 @@ nuxtseo actions list --site <site-id> --json
|
|
|
133
165
|
Keep server order. Check `evidence.freshness` on each row. If `verdict` is
|
|
134
166
|
`aged` with a large `ageHours`, live-check a cheap sample before you fix. The
|
|
135
167
|
Site may have changed since the observation.
|
|
168
|
+
If freshness `confidence` is `reasserted`, its age dates the repeated finding.
|
|
169
|
+
It does not date the underlying page observation. Read evidence group source
|
|
170
|
+
clocks in `actions show`. Live-check affected pages when those clocks are
|
|
171
|
+
unknown or old, even when the finding was recently reasserted.
|
|
136
172
|
|
|
137
173
|
**3. Read the evidence.**
|
|
138
174
|
|
|
@@ -142,7 +178,11 @@ nuxtseo actions show <action-id> --site <site-id> --json
|
|
|
142
178
|
|
|
143
179
|
It names the pages, the finding type, and when it was observed. If
|
|
144
180
|
`data.workPrompt` is not null, it is the Work Prompt: the task for this action,
|
|
145
|
-
grounded in its evidence. Start the fix from it.
|
|
181
|
+
grounded in its evidence. Start the fix from it.
|
|
182
|
+
The Work Prompt serves several clients and may name MCP alternatives.
|
|
183
|
+
Use its CLI commands in this workflow. Never switch to MCP as a fallback.
|
|
184
|
+
|
|
185
|
+
Two reads go deeper:
|
|
146
186
|
|
|
147
187
|
- `page issues --action-id <action-id>`: the raw observations, with URLs,
|
|
148
188
|
status codes, redirect targets, and Lighthouse selectors. This is the
|
|
@@ -175,8 +215,14 @@ from `actions show`, then:
|
|
|
175
215
|
nuxtseo actions dismiss <action-id> --site <site-id> --artifact-version <v> --yes --json
|
|
176
216
|
```
|
|
177
217
|
|
|
178
|
-
|
|
179
|
-
410 evidence and no internal referrers.
|
|
218
|
+
Without a note, the server admits a dismiss only for a broken-page action with
|
|
219
|
+
complete 404 or 410 evidence and no internal referrers.
|
|
220
|
+
|
|
221
|
+
If the owner confirms an action is intentional or incorrect, record that
|
|
222
|
+
decision with `--note "<reason>"`. Review the exact scope first. A note dismisses
|
|
223
|
+
the whole action, so never use it to hide a mix of intentional and broken URLs.
|
|
224
|
+
Dismissal keeps the observations and does not verify a fix. The dashboard can
|
|
225
|
+
restore the action later.
|
|
180
226
|
|
|
181
227
|
**7. Mark the day.**
|
|
182
228
|
|
|
@@ -215,6 +261,13 @@ and do not route around it with `pull` or another read.
|
|
|
215
261
|
`coverage.bestPracticesChecksTotal` from `scans show`. `possiblyTruncated:
|
|
216
262
|
true` marks the list as a floor.
|
|
217
263
|
|
|
264
|
+
For `search indexing urls`, read `totalSemantics` before quoting `total`.
|
|
265
|
+
`lower-bound` means the provider used lookahead instead of counting every URL.
|
|
266
|
+
The total can rise between pages without a filter change. Follow `hasMore` or
|
|
267
|
+
use `--all`. A nonempty terminal page reports `exact` for that retained URL population.
|
|
268
|
+
An empty page beyond offset zero reports `unknown`; its total can equal the requested offset.
|
|
269
|
+
Do not compare this population with a summary or cohort from another capture.
|
|
270
|
+
|
|
218
271
|
**Keep these datasets apart:**
|
|
219
272
|
|
|
220
273
|
- `performance` and `scans *` read Lighthouse **lab** Scans. `vitals summary`
|
|
@@ -251,6 +304,19 @@ its two lists:
|
|
|
251
304
|
with `statisticallyEstablished: false` is a lead to verify, for example by
|
|
252
305
|
inspecting its URLs. Presenting it as a cause is a hard failure.
|
|
253
306
|
|
|
307
|
+
**Compare equal windows.** Read `search analytics timeseries` for the Site's
|
|
308
|
+
current and previous totals. `audit content-decay` ships its own `window`.
|
|
309
|
+
It may span three months even when `pull --period 28d` selects 28-day analytics.
|
|
310
|
+
Quote that window separately. Never present its losses as the 28-day decline.
|
|
311
|
+
Content decay and duplicate reports return fixed shortlists. If `total` exceeds the returned
|
|
312
|
+
row count, disclose both counts, even when `page.hasMore` is false. That flag
|
|
313
|
+
does not promise the shortlist includes every Finding.
|
|
314
|
+
|
|
315
|
+
**Check alternate formats.** A `.md` URL can serve the HTML page's content
|
|
316
|
+
with a `Link: <html-url>; rel="canonical"` response header. Compare HTML
|
|
317
|
+
siblings with HTML siblings. Do not remove a valid header canonical or add
|
|
318
|
+
`noindex` just to clear a missing HTML canonical warning.
|
|
319
|
+
|
|
254
320
|
## Guardrails
|
|
255
321
|
|
|
256
322
|
- **Get consent before a mutation.** `page scan`, `actions resolve`, `actions
|
|
@@ -124,7 +124,7 @@ lines.
|
|
|
124
124
|
| `actions list` | Server-ranked issues and opportunities. `--limit 1..25` (default 10), `--offset`. Each row carries `evidence.freshness`; `verdict: "aged"` means the observation is over a day old, so live-check before fixing |
|
|
125
125
|
| `actions show <action-id>` | One issue or opportunity, plus its evidence. `--limit 1..100` (default 50), `--group-id`, `--cursor` |
|
|
126
126
|
| `actions resolve <action-id>` | Mutation. Claims the issue or opportunity and starts server verification. Reads the action first and sends `artifactVersion` for you |
|
|
127
|
-
| `actions dismiss <action-id>` | Mutation.
|
|
127
|
+
| `actions dismiss <action-id>` | Mutation. Needs `--artifact-version`, read from `actions show`. `--note` records why the owner considers the action intentional or incorrect. Without a note, complete unlinked 404 or 410 evidence is required. Dismissal preserves observations and never verifies a fix |
|
|
128
128
|
|
|
129
129
|
## Pages, Scans, and lab performance
|
|
130
130
|
|
|
@@ -132,15 +132,52 @@ lines.
|
|
|
132
132
|
| --- | --- |
|
|
133
133
|
| `page inspect <url>` | Stored observations, Lighthouse rows and keywords for one Page. `--limit 1..200`, `--offset`, `--include-resolved`. Carries `observations.coverage`: `never-scanned` means no source recorded this Page, `scanned-clear` means recorded and all clear |
|
|
134
134
|
| `page issues` | Raw Page Issue rows. Pass `--action-id`, or pass both `--source` and `--issue`. Passing both selectors exits `2`. `--url`, `--path-prefix`, `--include-resolved`, `--limit 1..200`, `--offset`. When the selector matches nothing, `availableKeys` lists the pairs this Site does have. Paused Sites exit `4` or `5`. Removed Sites return `not_found` with exit `8` |
|
|
135
|
-
| `page scan <url>` | Mutation.
|
|
135
|
+
| `page scan <url>` | Mutation. Adds or re-enables the URL as a monitored Page, then starts mobile and desktop Scans |
|
|
136
136
|
| `performance` | Stored Lighthouse lab overview for the Site: medians for perf, a11y, SEO, LCP, TBT, CLS. Lab Scans, never real-user field data |
|
|
137
137
|
| `scans list` | Retained Lighthouse Scans, newest first, with scores, lab vitals, and the error on a failed Scan. `--limit 1..100` (default 25) |
|
|
138
138
|
| `scans show <scan-id>` | One Scan, and the evidence behind its scores: wasteful assets, repeat-visit cache policy, third-party scripts, the LCP element, and every failing accessibility and best-practices check with its CSS selectors and DOM snippets. Read `coverage` before quoting a total |
|
|
139
139
|
| `scans pages` | The Pages this Site scans on a schedule. Add one with `page scan <url>` |
|
|
140
140
|
|
|
141
|
+
`scans show` can include `observedTrace` from the retained Lighthouse projection.
|
|
142
|
+
If its tag is `available`, its phases describe `observedLcpMs` from the browser trace.
|
|
143
|
+
`throttlingMethod` names how Lighthouse computed the reported metrics.
|
|
144
|
+
With `simulate`, reported `lcp` is modeled. Observed trace phases do not partition that modeled value.
|
|
145
|
+
With `devtools` or `provided`, Lighthouse uses observed metrics.
|
|
146
|
+
Neither value is real-user field data.
|
|
147
|
+
An `unavailable` tag names missing, invalid, or legacy evidence.
|
|
148
|
+
Older servers can omit the field. Omission also means unavailable.
|
|
149
|
+
This command never reads raw reports or starts a projection backfill.
|
|
150
|
+
|
|
141
151
|
`page inspect` and `page scan` take an absolute URL, for example
|
|
142
152
|
`https://example.com/about`.
|
|
143
153
|
|
|
154
|
+
### JavaScript byte measurements
|
|
155
|
+
|
|
156
|
+
`scans show` returns `data.javascript` with stored `transferBytes`, `decodedBytes`, and `scriptCount`.
|
|
157
|
+
Each measurement is nullable. `javascript: null` means no stored JavaScript measurement.
|
|
158
|
+
An older server may omit the field.
|
|
159
|
+
|
|
160
|
+
The extractor counts JavaScript by resource type, MIME type, or `.js` / `.mjs` URL.
|
|
161
|
+
It includes downloaded JavaScript labelled `Other`, which can include prefetch requests.
|
|
162
|
+
The stored totals do not separate prefetch from executed JavaScript.
|
|
163
|
+
They do not measure parse, compile, or execution work.
|
|
164
|
+
|
|
165
|
+
For a `js-transfer-weight` diagnostic, `wastedBytes` holds total decoded JavaScript bytes.
|
|
166
|
+
It is not removable code or Lighthouse unused-byte savings.
|
|
167
|
+
Use `data.javascript` for byte comparisons, and `unused` findings for unused-byte evidence.
|
|
168
|
+
Do not infer a reduction in executed JavaScript from download totals alone.
|
|
169
|
+
|
|
170
|
+
`page scan` enables recurring monitoring.
|
|
171
|
+
Read `scans pages` before scanning many new URLs. The server refuses a new
|
|
172
|
+
Page when five monitored Pages are already enabled. That limit comes from
|
|
173
|
+
the Page scan service, not the Team plan.
|
|
174
|
+
|
|
175
|
+
`pageCreated: true` means a monitored Page was created. The URL may already
|
|
176
|
+
have retained Scans. Automatic homepage assessment Scans use a separate
|
|
177
|
+
slot without a monitored Page. A manual homepage Scan can therefore create
|
|
178
|
+
a monitored Page while older homepage assessment Scans exist.
|
|
179
|
+
The monitored Page then follows its own recurring schedule.
|
|
180
|
+
|
|
144
181
|
## Field Core Web Vitals
|
|
145
182
|
|
|
146
183
|
| Command | What it returns, and its flags |
|
|
@@ -177,23 +214,33 @@ different numbers. Read the one that answers your question.
|
|
|
177
214
|
| Field | What it counts |
|
|
178
215
|
| --- | --- |
|
|
179
216
|
| `total` | The number of rows the query matched, not clicks or impressions |
|
|
180
|
-
| `totals` |
|
|
217
|
+
| `totals` | Upstream period totals from a separate read without grouping dimensions. These can include anonymized queries. Read `totalsScope`. `null` means unavailable |
|
|
181
218
|
| `representedTotals` | Clicks and impressions for the rows in this response only, after local filtering. `representedTotalsScope` says so in words |
|
|
182
219
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
`
|
|
220
|
+
Raising `--limit` changes `representedTotals` while `totals` covers the full window.
|
|
221
|
+
Grouped Page impressions can exceed whole-Site impressions when several Pages appear in one search.
|
|
222
|
+
Do not assume `representedTotals` is at or below `totals`.
|
|
223
|
+
Use `totals` for traffic totals, and `representedTotals` for the returned rows.
|
|
224
|
+
Neither row filters nor pagination make `totals` a sum of the returned rows.
|
|
225
|
+
|
|
226
|
+
Keyword lists omit `site:` and `inurl:` search operators after upstream paging.
|
|
227
|
+
`total` and `page` still count upstream rows.
|
|
228
|
+
Even `--all` can return fewer keyword rows than `total`.
|
|
229
|
+
|
|
230
|
+
### Read keyword coverage separately
|
|
186
231
|
|
|
187
|
-
|
|
232
|
+
Google suppresses query rows below a privacy threshold.
|
|
233
|
+
Keyword rows therefore omit some traffic, even after `--all`.
|
|
234
|
+
Their `representedTotals` measure only the returned keywords.
|
|
188
235
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
always at or below page-dimension totals for the same Site and period. Never
|
|
193
|
-
compare the two, and never report one as the Site total.
|
|
236
|
+
The engine can read dimensionless totals that include anonymized traffic.
|
|
237
|
+
Then `keywords.totals` can equal `pages.totals` for the same Site and period.
|
|
238
|
+
Do not assume `keywords.totals` is the sum of visible keyword rows.
|
|
194
239
|
|
|
195
|
-
Read
|
|
196
|
-
|
|
240
|
+
Read `timeseries.totals` for whole-Site traffic, `pages` rows for landing pages,
|
|
241
|
+
and `keywords` rows for visible terms. Use `prevTotals` to compare Site traffic
|
|
242
|
+
across periods.
|
|
243
|
+
A missing query row is never evidence of no demand.
|
|
197
244
|
|
|
198
245
|
## Web Analytics
|
|
199
246
|
|