pagesight 0.17.0 → 0.18.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/README.md +17 -83
- package/docs/credentials.md +54 -0
- package/docs/diagnostics.md +85 -0
- package/docs/snapshots.md +123 -0
- package/docs/usage.md +130 -0
- package/package.json +26 -29
- package/src/api/bing.ts +83 -0
- package/src/api/compare-snapshots.ts +377 -0
- package/src/api/discover.ts +39 -0
- package/src/api/doctor.ts +35 -0
- package/src/api/evidence-schema.ts +78 -0
- package/src/api/evidence.ts +99 -0
- package/src/api/execute.ts +147 -0
- package/src/api/index.ts +5 -0
- package/src/api/reports.ts +90 -0
- package/src/api/schema.ts +207 -0
- package/src/api/snapshot.ts +183 -0
- package/src/api/ui-findings.ts +68 -0
- package/src/cli.ts +182 -0
- package/src/http.ts +39 -0
- package/src/index.ts +8 -25
- package/src/mcp-server.ts +27 -0
- package/src/mcp.ts +5 -0
- package/src/providers/bing.ts +48 -0
- package/src/{lib → providers}/crux.ts +4 -9
- package/src/providers/ga.ts +114 -0
- package/src/providers/google-tokens.ts +86 -0
- package/src/providers/gsc-auth.ts +93 -0
- package/src/{lib → providers}/gsc.ts +27 -24
- package/src/{lib/psi.ts → providers/pagespeed.ts} +3 -14
- package/src/shared/dates.ts +32 -0
- package/src/shared/http.ts +63 -0
- package/src/tools/ai.ts +19 -27
- package/src/tools/audit.ts +18 -98
- package/src/tools/observe.ts +28 -0
- package/src/tools/page/analyze.ts +194 -0
- package/src/tools/page/batch.ts +163 -0
- package/src/tools/page/contrast.ts +128 -0
- package/src/tools/page/links.ts +200 -0
- package/src/tools/page/metadata.ts +225 -0
- package/src/tools/page/structured-data.ts +288 -0
- package/src/tools/page/tool.ts +48 -0
- package/src/tools/search/actions.ts +56 -0
- package/src/tools/search/analytics.ts +266 -0
- package/src/tools/search/coverage.ts +247 -0
- package/src/tools/search/gaps.ts +129 -0
- package/src/tools/search/inspection.ts +160 -0
- package/src/tools/search/result.ts +3 -0
- package/src/tools/search/sample.ts +110 -0
- package/src/tools/search/schema.ts +62 -0
- package/src/{lib/sitemap.ts → tools/search/sitemap-sampling.ts} +1 -45
- package/src/tools/search/sites.ts +86 -0
- package/src/tools/search/tool.ts +11 -0
- package/src/tools/setup.ts +1 -1
- package/src/tools/speed/analyze.ts +191 -0
- package/src/tools/speed/batch.ts +265 -0
- package/src/tools/speed/crux.ts +176 -0
- package/src/tools/speed/pagespeed.ts +273 -0
- package/src/tools/speed/schema.ts +39 -0
- package/src/tools/speed/tool.ts +11 -0
- package/src/web/fetch.ts +31 -0
- package/src/web/images.ts +62 -0
- package/src/web/page-observation.ts +69 -0
- package/src/{lib → web}/robots.ts +20 -12
- package/src/web/sitemap-inventory.ts +64 -0
- package/src/web/sitemap-parser.ts +59 -0
- package/src/lib/auth.ts +0 -187
- package/src/tools/page.ts +0 -1241
- package/src/tools/search.ts +0 -1118
- package/src/tools/speed.ts +0 -956
package/README.md
CHANGED
|
@@ -1,94 +1,28 @@
|
|
|
1
1
|
# Pagesight
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
SEO, analytics, page, and performance evidence for developers and AI assistants.
|
|
4
|
+
Use it through the TypeScript API, CLI, local HTTP server, or MCP.
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
Requires Bun. Try a page check without provider credentials:
|
|
6
7
|
|
|
7
|
-
```
|
|
8
|
-
|
|
8
|
+
```sh
|
|
9
|
+
bun add pagesight
|
|
10
|
+
bunx --bun pagesight page --url https://example.com
|
|
9
11
|
```
|
|
10
12
|
|
|
11
|
-
|
|
13
|
+
```ts
|
|
14
|
+
import { execute } from "pagesight";
|
|
12
15
|
|
|
16
|
+
const result = await execute({ operation: "page", url: "https://example.com" });
|
|
17
|
+
console.log(result);
|
|
13
18
|
```
|
|
14
|
-
=== Site Audit: https://example.com ===
|
|
15
19
|
|
|
16
|
-
|
|
20
|
+
Provider reports need access to the relevant Google or Bing account. Results keep
|
|
21
|
+
raw observations, failures, and limits; missing data is not zero.
|
|
17
22
|
|
|
18
|
-
|
|
19
|
-
|
|
23
|
+
- [API, CLI, HTTP, and MCP](docs/usage.md)
|
|
24
|
+
- [Snapshots and comparisons](docs/snapshots.md)
|
|
25
|
+
- [Provider access](docs/credentials.md)
|
|
26
|
+
- [Bing diagnostics, HTML images, and UI findings](docs/diagnostics.md)
|
|
20
27
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
HIGH Missing canonical URL
|
|
24
|
-
HIGH 22 sitemap URLs submitted, 0 indexed
|
|
25
|
-
Auto-inspected 5 URLs:
|
|
26
|
-
- 2/5 indexed
|
|
27
|
-
- 3/5 Discovered - currently not indexed: /docs/, /pricing/, /about/
|
|
28
|
-
MEDIUM Missing og:image — no social preview image
|
|
29
|
-
LOW Missing Twitter Card tags
|
|
30
|
-
LOW 6/139 AI crawlers blocked
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
## Tools
|
|
34
|
-
|
|
35
|
-
6 tools organized by intent:
|
|
36
|
-
|
|
37
|
-
| Tool | Intent | What it does |
|
|
38
|
-
|------|--------|-------------|
|
|
39
|
-
| `audit` | How's my site? | One-call site audit. Runs all checks in parallel. Prioritized findings with auto-drill-down on indexing issues. |
|
|
40
|
-
| `page` | What's on this URL? | Meta tags, OG, Twitter Card, JSON-LD validation (19 schema types), internal link health, redirect chains, WCAG contrast checker. Batch mode for multiple URLs. |
|
|
41
|
-
| `speed` | How fast is it? | PageSpeed single/batch/compare with Lighthouse scores and opportunities. CrUX real-user metrics (snapshot + history trends). |
|
|
42
|
-
| `search` | How's Google seeing me? | URL inspection, sample-inspect from sitemaps, sitemap management, search analytics with period-over-period comparison. |
|
|
43
|
-
| `ai` | How's AI seeing me? | AI crawler audit (139+ bots by category), robots.txt validation (RFC 9309), llms.txt detection, path access checks. |
|
|
44
|
-
| `setup` | Auth config | Auth status check and OAuth setup flow. |
|
|
45
|
-
|
|
46
|
-
## Setup
|
|
47
|
-
|
|
48
|
-
Add to your MCP config:
|
|
49
|
-
|
|
50
|
-
```json
|
|
51
|
-
{
|
|
52
|
-
"mcpServers": {
|
|
53
|
-
"pagesight": {
|
|
54
|
-
"command": "npx",
|
|
55
|
-
"args": ["pagesight"],
|
|
56
|
-
"env": {
|
|
57
|
-
"GSC_CLIENT_ID": "your-client-id",
|
|
58
|
-
"GSC_CLIENT_SECRET": "your-secret",
|
|
59
|
-
"GSC_REFRESH_TOKEN": "your-token",
|
|
60
|
-
"GOOGLE_API_KEY": "your-api-key"
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
`page`, `speed`, and `ai` work without credentials. `search` and `audit` (for GSC checks) require OAuth or a service account.
|
|
68
|
-
|
|
69
|
-
### Full setup
|
|
70
|
-
|
|
71
|
-
1. [Google Cloud Console](https://console.cloud.google.com/) — enable Search Console API, PageSpeed Insights API, Chrome UX Report API
|
|
72
|
-
2. Create OAuth client ID (Desktop app) + API key
|
|
73
|
-
3. Configure:
|
|
74
|
-
|
|
75
|
-
```env
|
|
76
|
-
GSC_CLIENT_ID=your-client-id.apps.googleusercontent.com
|
|
77
|
-
GSC_CLIENT_SECRET=your-client-secret
|
|
78
|
-
GSC_REFRESH_TOKEN=your-refresh-token
|
|
79
|
-
GOOGLE_API_KEY=your-api-key
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
## Why Pagesight
|
|
83
|
-
|
|
84
|
-
Every data point comes from a verifiable source. Google's APIs, real Chrome users, RFC 9309, schema.org, a community-maintained bot registry. No invented scores. No rules we can't cite.
|
|
85
|
-
|
|
86
|
-
- **"Title must be under 60 characters"** — Gary Illyes: "an externally made-up metric."
|
|
87
|
-
- **"Only one H1 per page"** — John Mueller: "You can use H1 tags as often as you want."
|
|
88
|
-
- **"Minimum 300 words per page"** — Mueller: "not a quality factor."
|
|
89
|
-
|
|
90
|
-
Pagesight reports what the sources report. Nothing more.
|
|
91
|
-
|
|
92
|
-
## License
|
|
93
|
-
|
|
94
|
-
MIT
|
|
28
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Provider access
|
|
2
|
+
|
|
3
|
+
## Credentials
|
|
4
|
+
|
|
5
|
+
| Provider | Configuration |
|
|
6
|
+
| -------------- | ------------------------------------------------------------------------------------------------------- |
|
|
7
|
+
| Search Console | `GSC_SERVICE_ACCOUNT_KEY`, or `GSC_CLIENT_ID`, `GSC_CLIENT_SECRET`, `GSC_REFRESH_TOKEN` |
|
|
8
|
+
| GA4 | `PAGESIGHT_GA_CREDENTIALS`, then `GOOGLE_APPLICATION_CREDENTIALS`, then the usual local gcloud ADC file |
|
|
9
|
+
| PageSpeed | `GOOGLE_API_KEY` optional |
|
|
10
|
+
| CrUX | `GOOGLE_API_KEY` required |
|
|
11
|
+
|
|
12
|
+
GA accepts service-account JSON or `authorized_user` ADC JSON. Use
|
|
13
|
+
`analytics.readonly` permission and grant property access. Enable both Analytics
|
|
14
|
+
Admin and Data APIs. GSC authentication remains separate with `webmasters.readonly`.
|
|
15
|
+
No new consent flow or provider settings are created by the read API.
|
|
16
|
+
|
|
17
|
+
Keep credentials in an environment file outside the repository and use Bun's
|
|
18
|
+
`--env-file` option. No tokens, API-key URLs, or provider error bodies are included
|
|
19
|
+
in report envelopes. Configuration files and operation requests must contain only
|
|
20
|
+
nonsecret identifiers and report parameters.
|
|
21
|
+
|
|
22
|
+
## Bing Webmaster reports
|
|
23
|
+
|
|
24
|
+
Set `BING_WEBMASTER_API_KEY` from Bing Webmaster Tools API Access, then discover
|
|
25
|
+
sites before copying a verified `Url` verbatim into `bingSite` in your config
|
|
26
|
+
(including its scheme and trailing-slash form):
|
|
27
|
+
|
|
28
|
+
```sh
|
|
29
|
+
pagesight discover --url https://example.com/ --providers bing
|
|
30
|
+
pagesight bing sites
|
|
31
|
+
pagesight bing queries --site https://example.com/
|
|
32
|
+
pagesight bing pages --site https://example.com/
|
|
33
|
+
pagesight bing traffic --site https://example.com/
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
The API operations are `bing.sites`, `bing.queries`, `bing.pages` and `bing.traffic`.
|
|
37
|
+
MCP `observe` and HTTP use the same operation objects. A configured `bingSite`
|
|
38
|
+
adds all three reports to snapshots; doctor checks traffic access. Google discovery
|
|
39
|
+
remains the default; use `--providers gsc,ga,bing` to include all providers.
|
|
40
|
+
|
|
41
|
+
These methods accept no date range or pagination options. Snapshot requested dates
|
|
42
|
+
apply to Google reports; Bing returns its provider-defined range. Responses retain
|
|
43
|
+
Bing's raw `d` envelope, numeric fields and `/Date(...)/` strings; reporting timezone
|
|
44
|
+
and coverage remain unknown. Query/page statistics update weekly, traffic daily.
|
|
45
|
+
`GetPageStats` uses `Query` for the page URL. Since March 24, 2023 traffic includes
|
|
46
|
+
Web, Chat, News, Images, Videos and Knowledge Panel; this is not isolated AI-citation
|
|
47
|
+
evidence or a Google Web equivalent. Site verification is not indexing evidence.
|
|
48
|
+
|
|
49
|
+
Contracts were checked against Microsoft Learn's [GetUserSites](https://learn.microsoft.com/en-us/dotnet/api/microsoft.bing.webmaster.api.interfaces.iwebmasterapi.getusersites),
|
|
50
|
+
[GetQueryStats](https://learn.microsoft.com/en-us/dotnet/api/microsoft.bing.webmaster.api.interfaces.iwebmasterapi.getquerystats),
|
|
51
|
+
[GetPageStats](https://learn.microsoft.com/en-us/dotnet/api/microsoft.bing.webmaster.api.interfaces.iwebmasterapi.getpagestats)
|
|
52
|
+
and [GetRankAndTrafficStats](https://learn.microsoft.com/en-us/dotnet/api/microsoft.bing.webmaster.api.interfaces.iwebmasterapi.getrankandtrafficstats).
|
|
53
|
+
Fixture tests verify these contracts and safe failures. Live Bing access has not
|
|
54
|
+
been verified because no API key is configured in the development environment.
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# Provider diagnostics and imported findings
|
|
2
|
+
|
|
3
|
+
## Bing crawl, URL and backlink evidence
|
|
4
|
+
|
|
5
|
+
```sh
|
|
6
|
+
pagesight bing crawl-stats --site https://example.com/
|
|
7
|
+
pagesight bing crawl-issues --site https://example.com/
|
|
8
|
+
pagesight bing url-info --site https://example.com/ --url https://example.com/page
|
|
9
|
+
pagesight bing link-counts --site https://example.com/ --max-pages 4
|
|
10
|
+
pagesight bing url-links --site https://example.com/ --url https://example.com/page --max-pages 4
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
These read operations use `BING_WEBMASTER_API_KEY` and the registered site URL.
|
|
14
|
+
They expose Microsoft's `GetCrawlStats`, `GetCrawlIssues`, `GetUrlInfo`,
|
|
15
|
+
`GetLinkCounts` and `GetUrlLinks` JSON methods. Link reports start at page zero;
|
|
16
|
+
`maxPages` defaults to one and accepts 1–20. Hitting the limit returns partial
|
|
17
|
+
status (CLI exit 3); raise the limit to repeat from page zero. `nextOffset` is a
|
|
18
|
+
provider page number. Failed later requests preserve successful pages. Changing
|
|
19
|
+
`TotalPages` stops pagination with partial coverage.
|
|
20
|
+
|
|
21
|
+
Raw provider dates and counts stay intact. Do not derive daily error rates without
|
|
22
|
+
verifying their periods and units. `HttpStatus: 0` in URL metadata is not an HTTP
|
|
23
|
+
success. Link report exhaustion does not establish a complete backlink inventory;
|
|
24
|
+
empty rows are not zero links, and link counts do not measure domain quality.
|
|
25
|
+
`InIndex` and sitemap counts have different scopes. Crawl issues are not the UI
|
|
26
|
+
recommendations list. These operations are explicit reads; existing snapshot
|
|
27
|
+
provider selection and call counts are unchanged.
|
|
28
|
+
|
|
29
|
+
## HTML image evidence
|
|
30
|
+
|
|
31
|
+
`pagesight page --url https://example.com/` now includes `descriptionLength`
|
|
32
|
+
(Unicode code points, or null) and `imageEvidence`. Images include raw `src`,
|
|
33
|
+
`altPresent`, `altText`, `inNoscript`, width/height, role and aria-hidden attributes.
|
|
34
|
+
Missing ALT has `altPresent: false, altText: null`; an explicitly empty ALT is
|
|
35
|
+
`altPresent: true, altText: ""`. Empty ALT can be appropriate for decorative images.
|
|
36
|
+
No description-length threshold or image-purpose verdict is imposed.
|
|
37
|
+
|
|
38
|
+
The inventory includes noscript fallback markup, retains at most 200 images,
|
|
39
|
+
and reports `omittedImages` and `truncated`. Fallback images follow ordinary images
|
|
40
|
+
in output; this is not DOM order. No scripts run or image URLs are requested.
|
|
41
|
+
The existing 2 MB page limit still applies. This is markup evidence, not a full
|
|
42
|
+
accessibility or rendered-page audit.
|
|
43
|
+
|
|
44
|
+
## Import provider UI findings
|
|
45
|
+
|
|
46
|
+
Use a small JSON transcription when a UI report has no verified API equivalent:
|
|
47
|
+
|
|
48
|
+
```json
|
|
49
|
+
{
|
|
50
|
+
"provider": "bing",
|
|
51
|
+
"site": "https://example.com/",
|
|
52
|
+
"source": {
|
|
53
|
+
"kind": "csv",
|
|
54
|
+
"label": "Affected URLs export; rule copied from report screen",
|
|
55
|
+
"capturedAt": null,
|
|
56
|
+
"scannedAt": null,
|
|
57
|
+
"coverage": "Only affected URLs were exported; total site coverage unknown"
|
|
58
|
+
},
|
|
59
|
+
"findings": [
|
|
60
|
+
{
|
|
61
|
+
"rule": "Meta descriptions are too short",
|
|
62
|
+
"severity": "unknown",
|
|
63
|
+
"urls": ["https://example.com/explore"]
|
|
64
|
+
}
|
|
65
|
+
]
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
```sh
|
|
70
|
+
pagesight evidence import --request findings.json --out imported.json
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
This validates JSON, preserves its attribution and labels it `user-import` and
|
|
74
|
+
`unverified`. It does not parse screenshots/CSV automatically, contact the provider,
|
|
75
|
+
fetch listed URLs or verify the finding. Use null for unknown capture/scan dates;
|
|
76
|
+
known dates must be ISO timestamps with offsets. Do not infer severity from a
|
|
77
|
+
URL-only CSV. Sources can be `csv`, `screenshot` or `manual`; providers can be
|
|
78
|
+
`bing`, `gsc` or `other`. An optional `source.artifactSha256` is caller supplied,
|
|
79
|
+
not verified. The generated `normalizedDocumentSha256` identifies normalized JSON,
|
|
80
|
+
not original file bytes. Import at most 100 findings and 1,000 URL references.
|
|
81
|
+
|
|
82
|
+
All additions use the shared API: operation names are `bing.crawl-stats`,
|
|
83
|
+
`bing.crawl-issues`, `bing.url-info`, `bing.link-counts`, `bing.url-links`, and
|
|
84
|
+
`evidence.import` (with a `document` field). They are also available through HTTP
|
|
85
|
+
`POST /v1/query`, CLI `api --request`, and MCP `observe`.
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# Snapshots and comparisons
|
|
2
|
+
|
|
3
|
+
## Site snapshots
|
|
4
|
+
|
|
5
|
+
A minimal config needs only a site:
|
|
6
|
+
|
|
7
|
+
```json
|
|
8
|
+
{ "site": "https://example.com/" }
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
It collects that page without Google credentials. Add `gscSite` or `gaProperty`
|
|
12
|
+
to select those providers independently. Omitted providers appear as `not_selected`;
|
|
13
|
+
a selected provider that fails produces error evidence. `sitemap` is opt-in, and
|
|
14
|
+
`pages` defaults to the site URL. `productionHostname` defaults to its hostname.
|
|
15
|
+
Existing full configurations still work. Context defaults identify unspecified
|
|
16
|
+
objectives, locale and country rather than inferring them.
|
|
17
|
+
|
|
18
|
+
`discover` lists candidates from the selected Google providers and returns a usable
|
|
19
|
+
site-only config in `pages[0].response.config`. Copy that object to a config file,
|
|
20
|
+
then add the property IDs you verified. It does not automatically select properties:
|
|
21
|
+
GA account display names are not proof of hostname ownership. Discovery failures
|
|
22
|
+
remain independent; inspect raw responses and `nextPageToken` for incomplete lists.
|
|
23
|
+
|
|
24
|
+
A config holds nonsecret provider IDs and the site's meaning:
|
|
25
|
+
|
|
26
|
+
```json
|
|
27
|
+
{
|
|
28
|
+
"site": "https://example.com/",
|
|
29
|
+
"productionHostname": "example.com",
|
|
30
|
+
"gscSite": "sc-domain:example.com",
|
|
31
|
+
"gaProperty": "123456",
|
|
32
|
+
"sitemap": "https://example.com/sitemap.xml",
|
|
33
|
+
"pages": ["https://example.com/"],
|
|
34
|
+
"context": {
|
|
35
|
+
"objective": "Help visitors use the product",
|
|
36
|
+
"successEvents": [],
|
|
37
|
+
"excludedKeyEvents": [],
|
|
38
|
+
"locale": "en-US",
|
|
39
|
+
"country": "US",
|
|
40
|
+
"routes": [{ "pattern": "/", "purpose": "Public entry", "indexing": "index" }],
|
|
41
|
+
"measurementCaveats": []
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
CLI snapshots default to 28 days ending Pacific today minus three days. Supply both
|
|
47
|
+
`--start YYYY-MM-DD` and `--end YYYY-MM-DD` to reproduce another interval. The API
|
|
48
|
+
requires explicit dates. The country and locale are context, not implicit filters.
|
|
49
|
+
|
|
50
|
+
A snapshot collects independent GSC property/page/query/date reports and sitemaps;
|
|
51
|
+
GA property/key-event configuration, unfiltered hostname census, production channels,
|
|
52
|
+
named events and organic landing reports; configured page fetches and GSC inspections;
|
|
53
|
+
and a sitemap inventory bounded to five same-origin XML files and 8 MB.
|
|
54
|
+
This inventory accepts ordinary unprefixed sitemap XML; unsupported prefixed or
|
|
55
|
+
compressed documents are reported as incomplete rather than empty coverage.
|
|
56
|
+
|
|
57
|
+
Snapshots embed the config used, observations, content hashes, requested/observed
|
|
58
|
+
dates and unknown deployment/reference identities. A failed observation remains
|
|
59
|
+
visible while successful data is retained. `doctor` probes GSC, GA Admin, GA Data
|
|
60
|
+
when selected, plus live HTML. Run speed operations to probe PSI/CrUX separately.
|
|
61
|
+
Snapshot responses carry `snapshotVersion: 1` and stable observation `name` values,
|
|
62
|
+
also present in the summary, so identity does not depend on array position.
|
|
63
|
+
|
|
64
|
+
Interpretation rules:
|
|
65
|
+
|
|
66
|
+
- GSC query privacy exclusions and aggregation differences mean row sums are not
|
|
67
|
+
property totals. Missing rows are not zero. Comparisons are descriptive, not causal.
|
|
68
|
+
- GA key events must be interpreted by name and the site's selected objective.
|
|
69
|
+
A hostname filter excludes development hosts but not internal use of production.
|
|
70
|
+
- Sitemap membership is not indexing. Google's `contents[].indexed` field is deprecated.
|
|
71
|
+
URL inspections describe the selected URLs in Google's stored state, not live access
|
|
72
|
+
or a statistically representative whole-site coverage rate.
|
|
73
|
+
- PSI is a lab run. CrUX NOT_FOUND is no record for that scope, not zero performance.
|
|
74
|
+
CrUX history periods overlap. AI referrals do not establish citations.
|
|
75
|
+
- Keep raw landing query strings and observed canonicals. Functional URL parameters
|
|
76
|
+
need site-specific interpretation; Pagesight does not silently join GA to GSC.
|
|
77
|
+
|
|
78
|
+
## Compare saved snapshots
|
|
79
|
+
|
|
80
|
+
Capture two snapshots with the same config and equal-length, nonoverlapping report
|
|
81
|
+
periods, then compare them locally:
|
|
82
|
+
|
|
83
|
+
```sh
|
|
84
|
+
pagesight snapshot --config seo.config.json --start 2026-07-04 --end 2026-07-31 --out before.json
|
|
85
|
+
pagesight snapshot --config seo.config.json --start 2026-08-01 --end 2026-08-28 --out after.json
|
|
86
|
+
pagesight compare --baseline before.json --current after.json --max-rows 100
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
The shared operation is `{ operation: "compare", baseline, current, maxRows: 100 }`,
|
|
90
|
+
where baseline and current are parsed snapshot evidence objects. Only the CLI reads
|
|
91
|
+
file paths. HTTP accepts objects up to 32 MB per request; larger pairs can use the
|
|
92
|
+
local API or CLI. MCP `observe` accepts the same object. `evidenceSchema` and
|
|
93
|
+
`snapshotEvidenceSchema` are exported for callers validating stored reports.
|
|
94
|
+
|
|
95
|
+
This first comparison supports GSC reports with non-time row keys and GA reports
|
|
96
|
+
using snapshot dimensions: `hostName`, `sessionDefaultChannelGroup`,
|
|
97
|
+
`sessionSourceMedium`, `eventName`, `landingPagePlusQueryString`, and `sessionSource`.
|
|
98
|
+
Reports without dimensions are also supported. Other GA dimensions and
|
|
99
|
+
`dimensionExpression` aliases require a separate comparison policy. It checks
|
|
100
|
+
snapshot format version 1, unique observation names, site, property, dimensions,
|
|
101
|
+
metrics, filters, aggregation, report periods and GA timezone/currency/metric types.
|
|
102
|
+
GSC data must be finalized. Time dimensions, Bing's provider-defined windows, HTML,
|
|
103
|
+
sitemap and provider metadata observations are explicitly unsupported for comparison.
|
|
104
|
+
Recapture snapshots created before versioned, named observations were introduced.
|
|
105
|
+
|
|
106
|
+
Each observation is `compared`, `limited`, `incompatible`, `unavailable`, or
|
|
107
|
+
`unsupported`. The outer evidence reports whether the comparison operation ran;
|
|
108
|
+
inspect the response status-count summary and per-observation statuses before using deltas. Partial pagination,
|
|
109
|
+
sampling, thresholding and high-cardinality aggregation remain visible limitations.
|
|
110
|
+
Missing trailing GSC date rows and recently collected GA data also mark comparisons
|
|
111
|
+
as limited; observed dates cannot prove complete coverage.
|
|
112
|
+
Only keys observed in both periods get numeric deltas. Keys seen in one period stay
|
|
113
|
+
unknown in the other, and their bounded lists include full counts. No row sums or
|
|
114
|
+
site-wide extrapolations are generated. Each row retains the original numeric values,
|
|
115
|
+
including GA strings; invalid or unsafe numbers get a null delta. Percent change is
|
|
116
|
+
null when the baseline is zero. CTR and position remain in their provider units.
|
|
117
|
+
|
|
118
|
+
`maxRows` defaults to 100 and is capped at 1,000 per observation/list; omitted counts
|
|
119
|
+
are explicit. The comparison includes `canonicalSha256` hashes of validated source objects, with
|
|
120
|
+
object keys sorted lexically and array order retained. These identify comparison
|
|
121
|
+
inputs, not raw file bytes; whitespace changes in saved JSON do not change them. Keep source snapshots for their full requests,
|
|
122
|
+
responses and metadata. Changes are descriptive and do not establish that an SEO
|
|
123
|
+
edit caused traffic changes; Pagesight does not apply SEO edits automatically.
|
package/docs/usage.md
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# Using Pagesight
|
|
2
|
+
|
|
3
|
+
## API
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
import { execute } from "pagesight";
|
|
7
|
+
|
|
8
|
+
const report = await execute({
|
|
9
|
+
operation: "gsc.report",
|
|
10
|
+
site: "sc-domain:example.com",
|
|
11
|
+
request: {
|
|
12
|
+
startDate: "2026-08-01",
|
|
13
|
+
endDate: "2026-08-28",
|
|
14
|
+
dimensions: ["page"],
|
|
15
|
+
},
|
|
16
|
+
maxPages: 4,
|
|
17
|
+
});
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Each result contains `schemaVersion`, `provider`, `operation`, `target`, collection
|
|
21
|
+
timestamps, `status`, request/response `pages`, `warnings`, and any `error` and
|
|
22
|
+
`failedRequest`. Reports include `pagination` with `exhausted`, `nextOffset` and
|
|
23
|
+
`rowsReturned`. Raw provider metadata, aggregation, quota, sampling and thresholding
|
|
24
|
+
are retained. Exhausted pagination does **not** imply exhaustive search coverage.
|
|
25
|
+
GA evidence identifies the credential source variable, credential type, and service
|
|
26
|
+
account email when present. It never includes the token or private key. Aggregate
|
|
27
|
+
results include a concise per-observation `summary` alongside full observations.
|
|
28
|
+
|
|
29
|
+
| Operation | Required inputs |
|
|
30
|
+
| -------------------------------------------- | -------------------------------------------------------- |
|
|
31
|
+
| `discover` | `url`; optional `providers` (`["gsc", "ga"]` by default) |
|
|
32
|
+
| `bing.sites` | None |
|
|
33
|
+
| `bing.queries`, `bing.pages`, `bing.traffic` | `site` |
|
|
34
|
+
| `gsc.sites` | None |
|
|
35
|
+
| `gsc.sitemaps` | `site` |
|
|
36
|
+
| `gsc.inspect` | `site`, `url` |
|
|
37
|
+
| `gsc.report` | `site`, `request`; optional `maxPages` |
|
|
38
|
+
| `ga.accounts` | None |
|
|
39
|
+
| `ga.property`, `ga.key-events` | `property` |
|
|
40
|
+
| `ga.report` | `property`, `request`; optional `maxPages` |
|
|
41
|
+
| `page` | `url` |
|
|
42
|
+
| `speed.psi` | `url`; optional `strategy` (`mobile` or `desktop`) |
|
|
43
|
+
| `speed.crux`, `speed.history` | `url`; optional `origin: true`, `formFactor` |
|
|
44
|
+
| `doctor` | `config` |
|
|
45
|
+
| `snapshot` | `config`, `startDate`, `endDate`; optional `maxPages` |
|
|
46
|
+
|
|
47
|
+
`operationSchema` and `configSchema` are exported for typed validation. The MCP
|
|
48
|
+
`observe` input uses the same schema. `page` observes fetched HTML, status,
|
|
49
|
+
redirects, canonical, robots directives, JSON-LD and a content hash. It does not
|
|
50
|
+
execute browser JavaScript. The original MCP page tool retains its additional
|
|
51
|
+
link, social-meta and contrast checks.
|
|
52
|
+
|
|
53
|
+
## CLI
|
|
54
|
+
|
|
55
|
+
```sh
|
|
56
|
+
pagesight --help
|
|
57
|
+
pagesight discover --url https://example.com/ --providers gsc,ga
|
|
58
|
+
pagesight doctor --config seo.config.json
|
|
59
|
+
pagesight gsc report --site sc-domain:example.com --request report.json --max-pages 4
|
|
60
|
+
pagesight ga report --property 123456 --request ga-report.json
|
|
61
|
+
pagesight page --url https://example.com/
|
|
62
|
+
pagesight speed psi --url https://example.com/
|
|
63
|
+
pagesight speed crux --url https://example.com/ --origin
|
|
64
|
+
pagesight snapshot --config seo.config.json --out observations/baseline.json
|
|
65
|
+
pagesight api --request operation.json
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
A GSC `report.json` uses the provider request shape. Defaults are finalized data,
|
|
69
|
+
Web search, no dimensions, 25,000 rows, offset zero. Ad hoc commands fetch one page
|
|
70
|
+
unless `--max-pages` is supplied (maximum 20). Request examples:
|
|
71
|
+
|
|
72
|
+
```json
|
|
73
|
+
{ "startDate": "2026-08-01", "endDate": "2026-08-28", "dimensions": ["page"] }
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
```json
|
|
77
|
+
{
|
|
78
|
+
"dateRanges": [{ "startDate": "2026-08-01", "endDate": "2026-08-28" }],
|
|
79
|
+
"dimensions": [{ "name": "eventName" }],
|
|
80
|
+
"metrics": [{ "name": "eventCount" }, { "name": "keyEvents" }],
|
|
81
|
+
"dimensionFilter": {
|
|
82
|
+
"filter": { "fieldName": "hostName", "stringFilter": { "matchType": "EXACT", "value": "example.com" } }
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
GA report defaults are 10,000 rows, offset zero and quota metadata requested.
|
|
88
|
+
`rowCount` determines remaining pages. For discovery/key-event lists, retain and
|
|
89
|
+
check any `nextPageToken`; these small metadata requests currently return one page.
|
|
90
|
+
They return `status: partial` when another metadata page is available.
|
|
91
|
+
|
|
92
|
+
All data commands output JSON; `--json` is accepted. `--out` writes the same result.
|
|
93
|
+
Exit codes: 0 success, 1 provider failure, 2 invalid input, 3 partial evidence.
|
|
94
|
+
Partial snapshots are saved. A successful report can still have provider coverage
|
|
95
|
+
limitations; inspect warnings and metadata before making comparisons.
|
|
96
|
+
|
|
97
|
+
## Local HTTP interface
|
|
98
|
+
|
|
99
|
+
```sh
|
|
100
|
+
# Set PAGESIGHT_API_TOKEN in your private environment file (at least 24 characters).
|
|
101
|
+
pagesight serve --port 6095
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Send the shared operation JSON to `POST http://127.0.0.1:6095/v1/query` with
|
|
105
|
+
`Authorization: Bearer <PAGESIGHT_API_TOKEN>`. The server binds only to loopback.
|
|
106
|
+
Missing/invalid authentication returns 401; invalid operations return 400; provider
|
|
107
|
+
failures return 502; partial evidence returns 200 with `status: partial`.
|
|
108
|
+
This interface is for local agents, not an Internet deployment.
|
|
109
|
+
|
|
110
|
+
## MCP compatibility
|
|
111
|
+
|
|
112
|
+
Run `pagesight mcp` to start the stdio MCP server. Configure your host to run
|
|
113
|
+
`bun /path/to/pagesight/packages/pagesight/src/index.ts mcp` with the environment above. Existing MCP
|
|
114
|
+
launch configurations must include the `mcp` argument; no arguments show CLI help.
|
|
115
|
+
|
|
116
|
+
The new `observe` tool accepts `{ "request": <operation object> }` and returns
|
|
117
|
+
structured API evidence. The original six tools remain available:
|
|
118
|
+
|
|
119
|
+
| Tool | Capability |
|
|
120
|
+
| -------- | ------------------------------------------------------------------------- |
|
|
121
|
+
| `audit` | PageSpeed, metadata, robots, sitemap processing errors and URL inspection |
|
|
122
|
+
| `page` | Metadata, links, JSON-LD checks, redirects and contrast |
|
|
123
|
+
| `speed` | PageSpeed and CrUX snapshots/history |
|
|
124
|
+
| `search` | GSC reports, sitemap metadata and selected URL inspection |
|
|
125
|
+
| `ai` | Robots and crawler-registry checks, llms.txt detection |
|
|
126
|
+
| `setup` | Existing GSC authentication helpers |
|
|
127
|
+
|
|
128
|
+
The legacy text tools do not invent indexed counts from deprecated sitemap fields,
|
|
129
|
+
extrapolate sample verdicts to the whole site, or treat missing comparison rows as zero.
|
|
130
|
+
Use `observe` for exact request/response evidence and pagination status.
|
package/package.json
CHANGED
|
@@ -1,54 +1,51 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pagesight",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.0",
|
|
4
4
|
"description": "See your site the way search engines and AI see it.",
|
|
5
5
|
"keywords": [
|
|
6
|
-
"
|
|
6
|
+
"ai-crawlers",
|
|
7
|
+
"core-web-vitals",
|
|
7
8
|
"geo",
|
|
8
9
|
"google-search-console",
|
|
10
|
+
"mcp",
|
|
9
11
|
"pagespeed-insights",
|
|
10
|
-
"core-web-vitals",
|
|
11
|
-
"web-performance",
|
|
12
12
|
"robots-txt",
|
|
13
|
-
"
|
|
14
|
-
"
|
|
13
|
+
"seo",
|
|
14
|
+
"web-performance"
|
|
15
15
|
],
|
|
16
|
+
"homepage": "https://github.com/caiopizzol/pagesight",
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"author": "Caio Pizzol",
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "git+https://github.com/caiopizzol/pagesight.git",
|
|
22
|
+
"directory": "packages/pagesight"
|
|
23
|
+
},
|
|
24
|
+
"bin": {
|
|
25
|
+
"pagesight": "src/index.ts"
|
|
26
|
+
},
|
|
16
27
|
"files": [
|
|
17
28
|
"src",
|
|
18
29
|
"README.md",
|
|
19
|
-
"LICENSE"
|
|
30
|
+
"LICENSE",
|
|
31
|
+
"docs"
|
|
20
32
|
],
|
|
21
33
|
"type": "module",
|
|
22
|
-
"main": "src/index.ts",
|
|
23
|
-
"
|
|
24
|
-
"
|
|
34
|
+
"main": "src/api/index.ts",
|
|
35
|
+
"exports": {
|
|
36
|
+
".": "./src/api/index.ts"
|
|
25
37
|
},
|
|
26
|
-
"repository": {
|
|
27
|
-
"type": "git",
|
|
28
|
-
"url": "git+https://github.com/caiopizzol/pagesight.git"
|
|
29
|
-
},
|
|
30
|
-
"homepage": "https://github.com/caiopizzol/pagesight",
|
|
31
|
-
"author": "Caio Pizzol",
|
|
32
38
|
"scripts": {
|
|
33
39
|
"start": "bun run src/index.ts",
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"format": "biome format --write src/"
|
|
40
|
+
"typecheck": "tsc -p tsconfig.json",
|
|
41
|
+
"test": "bun test __tests__"
|
|
37
42
|
},
|
|
38
|
-
"license": "MIT",
|
|
39
43
|
"dependencies": {
|
|
40
44
|
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
45
|
+
"saxes": "^6.0.0",
|
|
41
46
|
"zod": "^3.24.4"
|
|
42
47
|
},
|
|
43
48
|
"devDependencies": {
|
|
44
|
-
"@
|
|
45
|
-
"@semantic-release/commit-analyzer": "^13.0.1",
|
|
46
|
-
"@semantic-release/git": "^10.0.1",
|
|
47
|
-
"@semantic-release/github": "^12.0.6",
|
|
48
|
-
"@semantic-release/npm": "^13.1.5",
|
|
49
|
-
"@types/bun": "^1.3.11",
|
|
50
|
-
"lefthook": "^2.1.4",
|
|
51
|
-
"semantic-release": "^25.0.3",
|
|
52
|
-
"semantic-release-ai-notes": "^0.2.3"
|
|
49
|
+
"@types/bun": "^1.3.11"
|
|
53
50
|
}
|
|
54
51
|
}
|