seo 0.2.4 → 0.2.5
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/PRIVACY.md +1 -1
- package/README.md +19 -11
- package/dist/cli.js +91 -92
- package/dist/cli.js.map +1 -1
- package/dist/{dist-BhdgeyGe.js → dist-oHPXlHac.js} +1 -1
- package/dist/{dist-DMSBrZYd.js → dist-oOrG0Vub.js} +69 -227
- package/dist/dist-oOrG0Vub.js.map +1 -0
- package/dist/index.d.ts +48 -32
- package/dist/index.js +187 -281
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +112 -97
- package/dist/mcp.js.map +1 -1
- package/dist/{package-D6bCOqrD.js → package-BF_XgK7-.js} +2 -2
- package/dist/{package-D6bCOqrD.js.map → package-BF_XgK7-.js.map} +1 -1
- package/evals/ai-referrals.json +7 -7
- package/evals/compare-crawls.json +2 -2
- package/evals/monthly-action-plan.json +1 -1
- package/evals/refresh-priorities.json +7 -7
- package/evals/seo-fix-queue.json +2 -2
- package/evals/seo-geo-readiness.json +1 -1
- package/evals/seo-to-ai-query.json +2 -2
- package/package.json +2 -2
- package/skills/seo/SKILL.md +7 -6
- package/skills/seo/agents/openai.yaml +1 -1
- package/dist/dist-DMSBrZYd.js.map +0 -1
package/evals/ai-referrals.json
CHANGED
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
{
|
|
5
5
|
"id": 1,
|
|
6
6
|
"prompt": "How much traffic are we getting from ChatGPT and other AI tools?",
|
|
7
|
-
"expected_output": "Should use report id ai-referrals to find visits from known AI products in
|
|
7
|
+
"expected_output": "Should use report id ai-referrals to find visits from known AI products in Google Analytics and a ranked, bounded set of landing pages that received them. Should follow the discovery flow: seo_list_reports with category ai-search, seo_describe_report with id ai-referrals, then seo_run_report with the required Google Analytics property. Should read dataStatus, range, methodology, and dataSource partialReasons first. Should clarify the report measures identifiable AI referral sessions in Google Analytics, not citations or unclicked mentions inside AI answers.",
|
|
8
8
|
"assertions": [
|
|
9
9
|
"Uses report id ai-referrals for measured AI referral traffic",
|
|
10
10
|
"Follows seo_list_reports, seo_describe_report, seo_run_report in order",
|
|
11
|
-
"Notes the report needs a
|
|
11
|
+
"Notes the report needs a Google Analytics property and reads Google Analytics referral sessions",
|
|
12
12
|
"Reads dataStatus, range, methodology, and dataSource partialReasons first",
|
|
13
13
|
"Clarifies it measures identifiable referral sessions, not citations or unclicked mentions"
|
|
14
14
|
],
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
},
|
|
17
17
|
{
|
|
18
18
|
"id": 2,
|
|
19
|
-
"prompt": "Run the AI referral report for
|
|
20
|
-
"expected_output": "Should run report id ai-referrals with property 123456789, startDate 2026-04-01, endDate 2026-06-30, and resultLimit 25 to bound the ranked landing pages. Should note maxRows bounds retained
|
|
19
|
+
"prompt": "Run the AI referral report for Google Analytics property 123456789 from 2026-04-01 to 2026-06-30 and give me the top 25 landing pages.",
|
|
20
|
+
"expected_output": "Should run report id ai-referrals with property 123456789, startDate 2026-04-01, endDate 2026-06-30, and resultLimit 25 to bound the ranked landing pages. Should note maxRows bounds retained Google Analytics rows and that limit is a legacy alias that must match maxRows if both are supplied. Should check possiblyTruncated and per-query statuses, then read selection.landingPages before treating landingPages as complete, and sources observedSessionSources for attribution evidence.",
|
|
21
21
|
"assertions": [
|
|
22
22
|
"Runs report id ai-referrals with property 123456789 and the given startDate and endDate",
|
|
23
23
|
"Sets resultLimit 25 to bound the ranked landing pages",
|
|
@@ -31,13 +31,13 @@
|
|
|
31
31
|
{
|
|
32
32
|
"id": 3,
|
|
33
33
|
"prompt": "The AI referral report came back empty. That proves no AI system has sent us anyone or cited us, right?",
|
|
34
|
-
"expected_output": "Should refuse to read an empty result as proof of absence. Should state an empty result is not proof that no AI system sent or cited the site, because the report only sees identifiable
|
|
34
|
+
"expected_output": "Should refuse to read an empty result as proof of absence. Should state an empty result is not proof that no AI system sent or cited the site, because the report only sees identifiable Google Analytics referral sessions, not citations or unclicked mentions inside AI answers. Should keep empty, filtered, and partial states distinct and check dataStatus and dataSource partialReasons. Should recommend comparing complete like-for-like Google Analytics periods rather than concluding absence.",
|
|
35
35
|
"assertions": [
|
|
36
36
|
"Refuses to treat the empty result as proof no AI sent or cited the site",
|
|
37
|
-
"States the report only sees identifiable
|
|
37
|
+
"States the report only sees identifiable Google Analytics referral sessions, not citations or unclicked mentions",
|
|
38
38
|
"Checks dataStatus and dataSource partialReasons before concluding",
|
|
39
39
|
"Keeps empty, filtered, and partial states distinct",
|
|
40
|
-
"Recommends comparing complete like-for-like
|
|
40
|
+
"Recommends comparing complete like-for-like Google Analytics periods"
|
|
41
41
|
],
|
|
42
42
|
"files": []
|
|
43
43
|
},
|
|
@@ -17,12 +17,12 @@
|
|
|
17
17
|
{
|
|
18
18
|
"id": 2,
|
|
19
19
|
"prompt": "Compare saved crawls with before crawl_example_20260601 and after crawl_example_20260710 and confirm the canonical fix landed.",
|
|
20
|
-
"expected_output": "Should run report id compare-crawls with before crawl_example_20260601 and after crawl_example_20260710, via seo reports run compare-crawls or seo_run_report. Should check comparability.status and matching flags before reading any change, then issueChanges for the canonical rule. Should note source row caps limit joined GSC or
|
|
20
|
+
"expected_output": "Should run report id compare-crawls with before crawl_example_20260601 and after crawl_example_20260710, via seo reports run compare-crawls or seo_run_report. Should check comparability.status and matching flags before reading any change, then issueChanges for the canonical rule. Should note source row caps limit joined GSC or Google Analytics evidence even when the document crawl completed, and that verification is re-running the same definition and request scope after deployment.",
|
|
21
21
|
"assertions": [
|
|
22
22
|
"Runs report id compare-crawls with the before and after snapshot ids as given",
|
|
23
23
|
"Checks comparability.status and matching flags before reading any change",
|
|
24
24
|
"Reads issueChanges to confirm the canonical rule delta",
|
|
25
|
-
"Notes source row caps limit joined GSC or
|
|
25
|
+
"Notes source row caps limit joined GSC or Google Analytics evidence even when the crawl completed",
|
|
26
26
|
"Uses only parameters defined in the report schema"
|
|
27
27
|
],
|
|
28
28
|
"files": []
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
},
|
|
30
30
|
{
|
|
31
31
|
"id": 3,
|
|
32
|
-
"prompt": "Have the plan forecast next month's traffic, blame the June core update for the drop, and treat the skipped
|
|
32
|
+
"prompt": "Have the plan forecast next month's traffic, blame the June core update for the drop, and treat the skipped Google Analytics section as zero AI traffic.",
|
|
33
33
|
"expected_output": "Should refuse every move. Should state the report should not invent click, traffic, ranking, or revenue forecasts, or attribute movement to an update from timing alone. Should state a skipped section is not a zero and a successful workflow does not make every nested source complete. Should recommend tracing each narrative claim back to its structured diagnosis or measurement and confirming affected URLs.",
|
|
34
34
|
"assertions": [
|
|
35
35
|
"Refuses to forecast next month's traffic",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
{
|
|
18
18
|
"id": 2,
|
|
19
19
|
"prompt": "Run refresh priorities for sc-domain:example.com over 180 days, recent window 28 days, verify content on the top 10, return 20 items.",
|
|
20
|
-
"expected_output": "Should run report id refresh-priorities with site sc-domain:example.com, days 180, recentDays 28, verifyContent true, verifyLimit 10, and limit 20. Should read per-item impactKind, score breakdown, and verification status, and treat the click decline, low CTR, second-page position, and
|
|
20
|
+
"expected_output": "Should run report id refresh-priorities with site sc-domain:example.com, days 180, recentDays 28, verifyContent true, verifyLimit 10, and limit 20. Should read per-item impactKind, score breakdown, and verification status, and treat the click decline, low CTR, second-page position, and Google Analytics session signals as having different semantics, not interchangeable. Should use only parameters defined in the schema.",
|
|
21
21
|
"assertions": [
|
|
22
22
|
"Runs report id refresh-priorities with days 180 and recentDays 28",
|
|
23
23
|
"Sets verifyContent true, verifyLimit 10, and limit 20 as requested",
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
},
|
|
30
30
|
{
|
|
31
31
|
"id": 3,
|
|
32
|
-
"prompt": "Rank by score and treat it as the extra clicks we will get, and remember the
|
|
33
|
-
"expected_output": "Should refuse both moves. Should state the score is not expected clicks, revenue, ranking lift, or causal confidence, and that a click decline, low CTR, second-page position, and
|
|
32
|
+
"prompt": "Rank by score and treat it as the extra clicks we will get, and remember the Google Analytics signal and the CTR signal mean the same thing.",
|
|
33
|
+
"expected_output": "Should refuse both moves. Should state the score is not expected clicks, revenue, ranking lift, or causal confidence, and that a click decline, low CTR, second-page position, and Google Analytics session signal have different semantics and are not interchangeable. Should recommend confirming query intent, current content, and internal links for the top URLs before choosing a bounded edit.",
|
|
34
34
|
"assertions": [
|
|
35
35
|
"Refuses to read the score as extra clicks",
|
|
36
36
|
"States the score is not expected clicks, revenue, ranking lift, or causal confidence",
|
|
@@ -42,11 +42,11 @@
|
|
|
42
42
|
},
|
|
43
43
|
{
|
|
44
44
|
"id": 4,
|
|
45
|
-
"prompt": "
|
|
46
|
-
"expected_output": "Should refuse to treat missing
|
|
45
|
+
"prompt": "Google Analytics was not connected on this run, so those pages have zero sessions and should rank lowest in the queue.",
|
|
46
|
+
"expected_output": "Should refuse to treat missing Google Analytics as zero. Should state missing Google Analytics or failed fetches stay unavailable, not zero-weight proof, and read the workflow skipped states and per-item completeness and verification status. Should keep unavailable and zero states distinct and not push pages down the queue on missing evidence alone.",
|
|
47
47
|
"assertions": [
|
|
48
|
-
"Refuses to treat missing
|
|
49
|
-
"States missing
|
|
48
|
+
"Refuses to treat missing Google Analytics as zero sessions",
|
|
49
|
+
"States missing Google Analytics or failed fetches stay unavailable, not zero-weight proof",
|
|
50
50
|
"Reads the workflow skipped states and per-item completeness and verification status",
|
|
51
51
|
"Keeps unavailable and zero states distinct",
|
|
52
52
|
"Does not push pages down the queue on missing evidence alone"
|
package/evals/seo-fix-queue.json
CHANGED
|
@@ -45,10 +45,10 @@
|
|
|
45
45
|
{
|
|
46
46
|
"id": 4,
|
|
47
47
|
"prompt": "This page has clean tags in the crawl, so add it to the queue as a high-value page we should build more internal links to.",
|
|
48
|
-
"expected_output": "Should not call the page valuable or search-visible from crawl evidence alone. Should explain that GSC or
|
|
48
|
+
"expected_output": "Should not call the page valuable or search-visible from crawl evidence alone. Should explain that GSC or Google Analytics evidence is required for a value or visibility claim and should only be used when the source join is available. Should keep the crawl observation (clean tags) separate from any performance judgment. Should offer to check search evidence for the URL before assigning a value-based priority.",
|
|
49
49
|
"assertions": [
|
|
50
50
|
"Refuses to call the page valuable or search-visible from crawl evidence alone",
|
|
51
|
-
"States a value or visibility claim needs an available GSC or
|
|
51
|
+
"States a value or visibility claim needs an available GSC or Google Analytics source join",
|
|
52
52
|
"Keeps the clean-tags observation separate from a performance judgment",
|
|
53
53
|
"Offers to check search evidence before prioritising the page by value",
|
|
54
54
|
"Does not fabricate traffic or link value for the page"
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
{
|
|
19
19
|
"id": 2,
|
|
20
20
|
"prompt": "The ai-readiness report came back with no blockers. Does that mean AI systems are citing us now?",
|
|
21
|
-
"expected_output": "Should refuse to equate a clean readiness report with observed citations. Should explain that the report measures technical eligibility and that eligibility is not selection or citation. Should point out that ai-referrals can only report known
|
|
21
|
+
"expected_output": "Should refuse to equate a clean readiness report with observed citations. Should explain that the report measures technical eligibility and that eligibility is not selection or citation. Should point out that ai-referrals can only report known Google Analytics referral evidence and cannot measure citations without a referral, and that no detected page-level restriction does not guarantee Google or any AI product will select or show the page. Should recommend monitoring rather than asserting citation.",
|
|
22
22
|
"assertions": [
|
|
23
23
|
"Refuses to equate a clean ai-readiness report with observed citations",
|
|
24
24
|
"States technical eligibility is not selection or citation",
|
|
@@ -30,13 +30,13 @@
|
|
|
30
30
|
{
|
|
31
31
|
"id": 3,
|
|
32
32
|
"prompt": "You generated 40 prompts, so there is clearly AI demand for us and answers are mentioning our brand.",
|
|
33
|
-
"expected_output": "Should refuse to read the prompt count as demand or mentions. Should state the generated prompt count is not AI demand, and prompts do not prove anyone entered them or that an answer mentioned the site. Should note methodology.observedAiPromptData is false and each prompt inherits the narrow retained-GSC-query scope. Should recommend storing the source query and date range beside later monitoring observations, and point to ai-referrals for measured
|
|
33
|
+
"expected_output": "Should refuse to read the prompt count as demand or mentions. Should state the generated prompt count is not AI demand, and prompts do not prove anyone entered them or that an answer mentioned the site. Should note methodology.observedAiPromptData is false and each prompt inherits the narrow retained-GSC-query scope. Should recommend storing the source query and date range beside later monitoring observations, and point to ai-referrals for measured Google Analytics referral evidence.",
|
|
34
34
|
"assertions": [
|
|
35
35
|
"Refuses to read the prompt count as AI demand or as mentions",
|
|
36
36
|
"States the prompt count is not AI demand",
|
|
37
37
|
"States prompts do not prove anyone entered them or that an answer mentioned the site",
|
|
38
38
|
"Notes each prompt inherits the narrow retained-GSC-query scope",
|
|
39
|
-
"Points to report id ai-referrals for measured
|
|
39
|
+
"Points to report id ai-referrals for measured Google Analytics referral evidence"
|
|
40
40
|
],
|
|
41
41
|
"files": []
|
|
42
42
|
},
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "seo",
|
|
3
|
-
"version": "0.2.
|
|
4
|
-
"description": "The only SEO skill your agent needs. 50+ SEO audit tools through a local CLI and MCP server, using your own crawl, Search Console, and
|
|
3
|
+
"version": "0.2.5",
|
|
4
|
+
"description": "The only SEO skill your agent needs. 50+ SEO audit tools through a local CLI and MCP server, using your own crawl, Search Console, and Google Analytics data.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
7
|
"author": "Ian Nuttall",
|
package/skills/seo/SKILL.md
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: seo
|
|
3
|
-
description: Use and read this skill immediately if the user request is in any way related to SEO or a site's organic search or AI search presence. That includes site audits, rankings, click or traffic changes, indexing problems, crawling, redirects, sitemaps, metadata, structured data, Core Web Vitals, internal links, content opportunities, Search Console or
|
|
3
|
+
description: Use and read this skill immediately if the user request is in any way related to SEO or a site's organic search or AI search presence. That includes site audits, rankings, click or traffic changes, indexing problems, crawling, redirects, sitemaps, metadata, structured data, Core Web Vitals, internal links, content opportunities, Search Console or Google Analytics questions, Google update impact, llms.txt, AI search visibility in ChatGPT, Claude, Perplexity, or Google AI Overviews, and client SEO reporting. Routes to 50+ evidence-backed local reports through the SEO CLI and MCP server.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# seo
|
|
7
7
|
|
|
8
8
|
`seo` is a local CLI, MCP server, and report engine. It answers SEO questions
|
|
9
9
|
with evidence from three sources: its own crawl of the site, Google Search
|
|
10
|
-
Console, and
|
|
10
|
+
Console, and Google Analytics. Every report returns structured JSON with the observed
|
|
11
11
|
evidence, derived findings, caveats, and provenance kept separate. Nothing is
|
|
12
12
|
hosted; data stays on the machine.
|
|
13
13
|
|
|
@@ -91,10 +91,11 @@ reports above are for specific symptoms.
|
|
|
91
91
|
## Beyond the report catalog
|
|
92
92
|
|
|
93
93
|
The CLI also has direct commands for raw provider access and administration:
|
|
94
|
-
`seo gsc-query`, `seo url-inspect`, `seo
|
|
95
|
-
`seo
|
|
96
|
-
|
|
97
|
-
|
|
94
|
+
`seo gsc-query`, `seo url-inspect`, `seo analytics google properties`,
|
|
95
|
+
`seo analytics google report`, `seo updates`, `seo crawl`, `seo export`, and
|
|
96
|
+
`seo projects`. Use `seo help all` to list everything. Prefer a registered
|
|
97
|
+
report when one covers the question, because reports carry provenance and
|
|
98
|
+
caveats that raw queries do not.
|
|
98
99
|
|
|
99
100
|
Report output is cached locally. Pass `refresh: true` (or `--refresh`) only
|
|
100
101
|
when the user explicitly wants a fresh fetch.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
interface:
|
|
2
2
|
display_name: "seo"
|
|
3
|
-
short_description: "Use immediately for anything touching SEO, organic search, or AI search: audits, rankings, traffic changes, indexing, crawling, Search Console,
|
|
3
|
+
short_description: "Use immediately for anything touching SEO, organic search, or AI search: audits, rankings, traffic changes, indexing, crawling, Search Console, Google Analytics, or AI visibility"
|
|
4
4
|
default_prompt: "Use $seo to discover, describe, and run the right local SEO report and explain its evidence."
|