Skip to content

Commit 167422c

Browse files
authored
Merge pull request #124 from petera2c/small-bug-fixes
Release 4.1.1 with row grouping leaf-row alignment.
2 parents 3ccd955 + 119da56 commit 167422c

56 files changed

Lines changed: 1957 additions & 118 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
---
2+
name: competitive-landscape
3+
description: Map SEO market leaders, winning content themes, keyword coverage, backlinks, and strategic gaps.
4+
---
5+
6+
# OpenSEO Competitive Landscape
7+
8+
## Goal
9+
10+
Answer: "Who is winning this SEO market, what content is working for them, and where are the openings?"
11+
12+
Use this when the user wants a market-level view across several competitors. For a deep dive on one domain, use `competitor-analysis`.
13+
14+
## Required inputs
15+
16+
- `projectId`
17+
- Topic, seed keywords, market/category, or user's domain
18+
- Optional known competitors
19+
- Optional location/language
20+
21+
## OpenSEO MCP tools
22+
23+
- `research_keywords`: discover representative market queries.
24+
- `get_keyword_metrics`: validate known query sets with volume, difficulty, intent, and trends.
25+
- `get_serp_results`: identify recurring ranking domains across target queries.
26+
- `find_serp_competitors`: compare domains competing across supplied keywords; use this before manual SERP counting when a keyword set is available.
27+
- `get_domain_overview`: size organic footprint for candidate leaders.
28+
- `get_search_console_performance`: when the user's own domain is in the comparison and Search Console is connected, anchor their position with first-party clicks/impressions/CTR rather than third-party estimates.
29+
- `get_ranked_keywords`: find exact ranking keywords, URLs, ranks, intents, and SERP result types for leaders.
30+
- `get_backlinks_overview`: compare backlink/referring-domain strength where relevant.
31+
- `search_local_businesses`, `get_local_serp_results`, and `get_google_business_questions`: use for local SEO markets where proximity, Maps rankings, business categories, reviews, or Google Q&A affect who is winning.
32+
33+
## Workflow
34+
35+
1. Define the market query set:
36+
- Use provided keywords, or call `research_keywords` to build 5-10 representative queries.
37+
- Include mixed intent: informational, commercial, comparison, and tool/software terms when applicable.
38+
- For local SEO, include neighborhood/city/service-area queries and identify the priority locations or coordinates.
39+
2. If the query set is already known, use `get_keyword_metrics` to validate relative demand and difficulty and `find_serp_competitors` to identify recurring domains at scale.
40+
3. For local SEO, call `search_local_businesses` and `get_local_serp_results` for the highest-priority location(s) before synthesizing winners. Use `get_serp_results` as a complement for organic pages, not as the only local evidence.
41+
4. Call `get_serp_results` for representative queries when live SERP composition, ranking URLs, or SERP features need inspection. Send at most 10 queries per call.
42+
5. Identify recurring domains and group them by type:
43+
- Direct product competitors
44+
- Publishers/media
45+
- Marketplaces/directories
46+
- Communities/forums
47+
- Documentation/resources
48+
6. For the strongest recurring domains, call `get_domain_overview`; default to the top 3-5 domains before expanding.
49+
7. For direct competitors and relevant publishers, call `get_ranked_keywords`.
50+
8. Use `get_backlinks_overview` when backlink authority appears important or the user asks why a domain is winning. Backlinks may be unavailable if the account has not enabled that data; continue with SERP/domain evidence if it fails.
51+
9. Synthesize patterns: content types, themes, SERP formats, local-pack signals, authority advantages, and underserved angles.
52+
53+
## Output format
54+
55+
Start with the market read:
56+
57+
- Market leaders
58+
- Most winnable opportunity area
59+
- Biggest barrier to ranking
60+
61+
Then include:
62+
63+
| Domain | Type | Why they matter | Organic footprint | Winning themes | Weakness/gap |
64+
| ------ | ---- | --------------- | ----------------- | -------------- | ------------ |
65+
66+
Add:
67+
68+
- Query set used
69+
- Content formats that are working
70+
- Keyword/theme gaps
71+
- Backlink or authority observations
72+
- Recommended next workflows: competitor analysis, keyword clustering, or content brief
73+
74+
## Guardrails
75+
76+
- Distinguish SEO competitors from business competitors.
77+
- Do not overstate exact traffic when OpenSEO returns estimates.
78+
- If using a small query set, call the result directional.
79+
- Do not assume a publisher is a product competitor; label domain types clearly.
80+
- For local markets, distinguish organic-page winners from Maps/local-pack winners.
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
---
2+
name: competitor-analysis
3+
description: "Analyze one competitor's organic footprint, ranking keywords, content themes, backlinks, and gaps."
4+
---
5+
6+
# OpenSEO Competitor Analysis
7+
8+
## Goal
9+
10+
Analyze one competitor deeply enough to decide what to learn from, avoid, counter-position against, or outrank.
11+
12+
Use this for a named competitor. For identifying the market leaders first, use `competitive-landscape`.
13+
14+
## Required inputs
15+
16+
- `projectId`
17+
- Competitor domain
18+
- User's domain when comparison is requested
19+
- Optional topic/category/location/language
20+
21+
## OpenSEO MCP tools
22+
23+
- `get_domain_overview`: baseline organic traffic and keyword count.
24+
- `get_search_console_performance`: when comparing to the user's own domain and Search Console is connected, use it as the first-party baseline (real clicks/impressions/CTR/position) instead of estimating the user's own performance from third-party data.
25+
- `get_ranked_keywords`: exact keyword, URL, rank, intent, traffic, CPC, and SERP-type rows for the competitor domain or page.
26+
- `get_backlinks_overview`: backlink/referring-domain profile.
27+
- `find_serp_competitors`: validate whether the named competitor is a real search competitor across the target keyword set.
28+
- `search_local_businesses`, `get_local_serp_results`, and `get_google_business_questions`: use for local SEO competitors when Maps/local-pack visibility, nearby businesses, categories, or Google Q&A matter.
29+
- `get_serp_results`: validate direct head-to-head SERPs for important keywords.
30+
- `research_keywords`: expand gaps or category terms when needed.
31+
32+
## Workflow
33+
34+
1. Call `get_domain_overview` for the competitor, passing provided location/language when supported.
35+
2. If comparing to the user, call `get_domain_overview` for the user's domain too — and if Search Console is connected, `get_search_console_performance` for the user's real baseline.
36+
3. Call `get_ranked_keywords` for the competitor. Use filters like `maxRank`, `minSearchVolume`, `excludeBrandTerms`, and `resultTypes` to keep rows relevant.
37+
4. If comparing to the user, call `get_ranked_keywords` for the user's domain/page too, or use `get_serp_results` for the shared terms when a lighter check is enough.
38+
5. For local SEO, use `search_local_businesses` and `get_local_serp_results` around the relevant business location(s) before drawing local-pack conclusions. Add `get_google_business_questions` only when Q&A evidence matters.
39+
6. Use `find_serp_competitors` when the competitor was supplied by the user but its search overlap is unclear.
40+
7. Group competitor keywords into themes:
41+
- Product/category terms
42+
- Alternatives/comparisons
43+
- Templates/tools/calculators
44+
- Educational guides
45+
- Branded demand
46+
- Local/neighborhood terms when relevant
47+
8. Call `get_backlinks_overview` for the competitor, especially if authority appears to explain rankings. Continue without backlink evidence if it is unavailable.
48+
9. Use `get_serp_results` for important shared or target keywords to compare positioning, passing provided location/language when supported.
49+
10. Produce an actionable plan:
50+
- What they are doing well
51+
- Where they are vulnerable
52+
- Which pages/keywords to pursue
53+
- What to avoid copying
54+
55+
## Output format
56+
57+
Start with:
58+
59+
- Competitor snapshot
60+
- Biggest lesson
61+
- Best opportunity to beat them
62+
63+
Then include:
64+
65+
| Area | Competitor pattern | Evidence | OpenSEO opportunity |
66+
| ---- | ------------------ | -------- | ------------------- |
67+
68+
Include sections for:
69+
70+
- Top keyword themes
71+
- Content/page types working for them
72+
- Backlink/authority notes
73+
- Head-to-head SERP observations
74+
- Priority actions for the user
75+
76+
## Guardrails
77+
78+
- Do not treat all competitor keywords as desirable. Filter for business fit.
79+
- Separate evidence from inference.
80+
- Do not infer competitor page/content-type patterns from keyword rows alone; use SERP or web evidence for page-level claims.
81+
- For local SEO, do not infer Maps/local-pack strength from national organic domain metrics alone; use local business and local SERP tools when the location is known or reasonably discoverable.
82+
- Do not recommend copying content; recommend a stronger angle or better answer to the same intent.
83+
- If the user's domain is unavailable, frame the analysis as competitor-only.
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
---
2+
name: keyword-clustering
3+
description: Cluster keywords by intent and map them to existing or proposed pages.
4+
---
5+
6+
# OpenSEO Keyword Clustering
7+
8+
## Goal
9+
10+
Group keywords into page-level clusters and decide which existing or new page should target each cluster. This is a keyword mapping workflow, not just a semantic grouping exercise.
11+
12+
## Required inputs
13+
14+
- `projectId`
15+
- A keyword list, saved keyword tag, seed topic, or target domain
16+
- Optional existing URLs/pages to map against
17+
18+
If keywords are not provided, use `list_saved_keywords` for saved sets, `research_keywords` for seed discovery, or `get_ranked_keywords` when the user starts from a target domain.
19+
20+
## OpenSEO MCP tools
21+
22+
- `list_saved_keywords`: fetch an existing keyword set, optionally filtered by tags.
23+
- `research_keywords`: expand a seed when the user starts from a topic.
24+
- `get_ranked_keywords`: gather exact ranking keywords and URLs when the user starts from a domain or page.
25+
- `get_search_console_performance`: when Search Console is connected, pull real queries with `dimensions: ["query","page"]` to map terms to the pages already earning impressions and to surface cannibalization (one query splitting clicks across multiple URLs).
26+
- `get_serp_results`: validate whether keywords belong on the same page by checking SERP overlap and intent.
27+
- `get_local_serp_results`: use for local SEO clusters when Maps/local-pack intent should affect page mapping.
28+
- `save_keywords`: optionally tag final clusters after user confirmation.
29+
30+
## Workflow
31+
32+
1. Gather the candidate keyword set.
33+
- Use `get_search_console_performance` (dimensions `["query","page"]`) when Search Console is connected to start from real queries and the pages already ranking for them.
34+
- Use `get_ranked_keywords` for domain/page-driven clustering.
35+
- Use `search_local_businesses` and `get_local_serp_results` when proximity, local packs, or Google Business results determine whether terms belong on location pages.
36+
2. Remove duplicates, irrelevant terms, and terms that clearly require a different product or audience.
37+
3. Build clusters around intent and page type:
38+
- Same SERP intent and similar ranking pages belong together.
39+
- Different intent, buyer stage, or SERP format should be split.
40+
- Similar words do not guarantee the same cluster.
41+
4. For important borderline terms, use a small `get_serp_results` batch to check overlap.
42+
5. Assign each cluster to:
43+
- Existing URL, if supplied and appropriate
44+
- New page recommendation, if no existing page fits
45+
- Do-not-target / later bucket, if weak or off-strategy
46+
6. Identify cannibalization risk when multiple pages would target the same intent. When Search Console is connected, confirm it from real data with `get_search_console_performance` (`dimensions: ["query","page"]`) — the same query sending impressions to multiple URLs.
47+
7. Ask before applying cluster tags with `save_keywords`.
48+
49+
## Output format
50+
51+
Start with a short mapping summary:
52+
53+
- Number of clusters
54+
- Pages to create
55+
- Existing pages to update
56+
- Cannibalization or consolidation issues
57+
58+
Then include:
59+
60+
| Cluster | Primary keyword | Secondary keywords | Intent | Target page | Priority | Notes |
61+
| ------- | --------------- | ------------------ | ------ | ----------- | -------- | ----- |
62+
63+
For each cluster, include a recommended page brief:
64+
65+
- Page type
66+
- Searcher problem
67+
- Required sections
68+
- Internal-link opportunities
69+
- Save/tag suggestion
70+
71+
## Guardrails
72+
73+
- Do not over-cluster tiny keyword sets. If there are fewer than 10 usable terms, produce a simple map.
74+
- Do not rely on lexical similarity alone. SERP intent wins.
75+
- Do not replace tags broadly without explicit confirmation.
76+
- If existing URL data is missing, label target pages as proposed.
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
---
2+
name: keyword-research
3+
description: "Discover keyword opportunities, evaluate metrics and SERPs, and save/tag promising terms."
4+
---
5+
6+
# OpenSEO Keyword Research
7+
8+
## Goal
9+
10+
Turn seed topics into a prioritized keyword opportunity set using OpenSEO MCP data. The output should help the user decide what to target, what to save, and what to research next.
11+
12+
## Required inputs
13+
14+
- `projectId`
15+
- One or more seed topics, products, pages, competitors, or audience problems
16+
- Optional market/location/language
17+
18+
If `projectId` is missing, use `list_projects` first. If the target market/location/language is unclear and would materially affect keyword metrics, ask the user; otherwise use the MCP tool defaults.
19+
20+
## OpenSEO MCP tools
21+
22+
- `research_keywords`: primary discovery tool. Use 1-5 seeds per call and prefer 150 results unless the user asks for exhaustive research.
23+
- `get_keyword_metrics`: hydrate up to 700 known keywords with volume, keyword difficulty (KD), search intent, CPC, and monthly trends in one call. Use it to score candidate or known terms — including the Search Console striking-distance queries from step 1.
24+
- `get_ranked_keywords`: pull exact ranking keyword rows when a target domain or page is part of the research brief.
25+
- `get_search_console_performance`: when Search Console is connected, start from the project's real first-party demand — queries already earning impressions and near-ranking ("striking distance") terms. Request a high `rowLimit` and filter average position 5-20 client-side, since the API sorts by clicks and can't filter by position. Then hydrate those striking-distance queries with `get_keyword_metrics` to attach difficulty and intent.
26+
- `get_serp_results`: inspect SERPs for the top candidate terms, especially when intent is ambiguous.
27+
- `search_local_businesses`, `get_local_serp_results`, and `get_google_business_questions`: use for local SEO topics when a business/location radius matters.
28+
- `list_saved_keywords`: avoid duplicating already-saved work or use existing tags as context.
29+
- `save_keywords`: save selected keywords only after explicit user confirmation.
30+
31+
## Workflow
32+
33+
1. Normalize seeds into a small set of distinct research angles. If Search Console is connected for the project, first pull `get_search_console_performance` (high `rowLimit`, default lookback), filter to striking-distance positions (~5–20) client-side, and hydrate those queries with `get_keyword_metrics` to attach KD and intent. That ranked, hydrated list is your fastest opportunity set — work it before broad discovery.
34+
2. If the request is local SEO, identify the business, location/coordinates or service area, and local categories. Use `search_local_businesses` and `get_local_serp_results` for the most important location/keyword set instead of relying only on national keyword/SERP data.
35+
3. Call `research_keywords` for exploratory seeds. Use bulk calls when possible.
36+
4. Use `get_keyword_metrics` to hydrate a fixed keyword list — or the striking-distance queries from step 1 — with volume, KD, and intent before prioritizing.
37+
5. Use `get_ranked_keywords` when the user provides a domain/page and wants opportunities based on current rankings, near-misses, or competitor-owned terms.
38+
6. Remove irrelevant, duplicate, branded-only, and off-intent terms.
39+
7. Prioritize by practical opportunity, not volume alone:
40+
- Strong match to the user's product/page/topic
41+
- Clear search intent
42+
- Reasonable difficulty
43+
- Useful volume/CPC signal
44+
- SERP where the user can plausibly compete
45+
- For local SEO, local-pack/Maps visibility and proximity fit
46+
8. Use `get_serp_results` for high-potential or ambiguous keywords when SERP intent would change the recommendation; keep the default check small.
47+
9. Present a shortlist and a longer opportunity table.
48+
10. Ask before saving keywords. When saving, suggest concise tags such as `topic:<topic>`, `intent:<intent>`, or `page:<slug>`.
49+
50+
## Output format
51+
52+
Start with the highest-signal recommendation:
53+
54+
- Best opportunity theme
55+
- Top keywords to target now
56+
- Keywords to save
57+
- Risks or SERP caveats
58+
59+
Then include a compact table:
60+
61+
| Keyword | Intent | Volume | KD | CPC | Priority | Notes |
62+
| ------- | ------ | -----: | --: | --: | -------- | ----- |
63+
64+
End with next actions, including whether to run keyword clustering, create a content brief, or save the chosen keywords.
65+
66+
## Guardrails
67+
68+
- Do not invent metrics. If OpenSEO does not return a value, write `unknown`.
69+
- Do not call `save_keywords` without explicit confirmation.
70+
- Prefer business-fit and intent-fit over chasing the largest volume term.

0 commit comments

Comments
 (0)