feat(seo-skills): multi-backend Data Source Selection (#7)

Replaces single-vendor (Ahrefs-only) tool defaults with a per-task
backend menu across all 14 SEO skills. Each skill now lists every
capable MCP in allowed-tools and documents how to pick between
Semrush, Ahrefs, OurSEO Agent (CLI + MCP), DataForSEO, and GSC
in its SKILL.md Data Source Selection section.

Tool stubs (~40 new files) populated per skill with capability
deltas, call patterns, and explicit "not for this skill when"
callouts so the menu is self-correcting.

Skills affected: 19-keyword-strategy, 20-serp-analysis,
21-position-tracking, 22-link-building, 23-content-strategy,
24-ecommerce, 25-kpi-framework, 26-international, 27-ai-visibility,
28-knowledge-graph, 31-competitor-intel, 32-crawl-budget,
33-migration-planner, 34-reporting-dashboard.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Andrew Yim
2026-05-14 03:15:32 +09:00
committed by GitHub
parent 1ca84f67ed
commit e527fb4b0f
71 changed files with 2647 additions and 258 deletions

View File

@@ -21,11 +21,41 @@ Expand seed keywords, classify search intent, cluster topics, and identify compe
4. **Topic Clustering** - Group keywords into semantic clusters
5. **Gap Analysis** - Find competitor keywords missing from target site
## MCP Tool Usage
## Data Source Selection
### SEO Data (DataForSEO)
This skill can pull keyword data from multiple backends. **Pick one per task** — don't fan out to every backend by default (cost + rate limits).
**Primary — our-seo-agent CLI:**
| Backend | Best for | Notes |
|---|---|---|
| **Semrush MCP** (`mcp__semrush__*`) | Default for keyword volume, related/matching terms, organic competitor pulls | Call pattern: `keyword_research``get_report_schema``execute_report`. `database="us"` default; `"kr"` for Korean market. |
| **Ahrefs MCP** (`mcp__ahrefs__*`) | Ahrefs DR/UR weighting; first-party `gsc-keywords` (only Ahrefs integrates GSC inside its MCP) | `keywords-explorer-overview`, `-matching-terms`, `-related-terms`, `-search-suggestions`, `-volume-by-country`, `gsc-keywords`. |
| **OurSEO Agent CLI** (`our keywords *`) | DataForSEO under the hood — cheapest per call, batch-friendly, Korean-aware via `--location 2410` | Claude Code only (needs Bash). Wrap calls: `our keywords volume`, `ideas`, `for-site`, `intent`, `difficulty`. |
| **OurSEO Agent MCP** (`mcp__ourseo__*`) | Claude Desktop equivalent for crawl-derived keywords + Knowledge Graph entity expansion | `search_knowledge_graph` for entity seeding; `crawl_website` to extract on-page keyword inventory from the target site itself. |
| **DataForSEO MCP** (`mcp__dfs-mcp__*`) | Direct fallback when `our` CLI isn't available | Same data as `our keywords *`. |
| **GSC** (via `our research search-console` or Ahrefs `gsc-*`) | First-party queries the site actually ranks for — ground truth, not estimates | Use to validate/prune Semrush or Ahrefs lists with real impressions/CTR. |
### How to pick
Apply these in order; stop at the first match:
1. **User named a backend explicitly** in the prompt → use it.
2. **User preference memory** — read `feedback_seo_tool_preferences.md`; honor the task-type default there.
3. **Task needs a capability only one backend has** (e.g., `gsc-keywords` first-party data, or `mcp__ourseo__search_knowledge_graph` entity expansion) → use that backend.
4. **Default by market**:
- English-market or unspecified → **Semrush MCP** with `database="us"`.
- Korean market → **OurSEO CLI** `our keywords <subcmd> --location 2410 --language ko` (Claude Code), or **Semrush MCP** with `database="kr"` (Claude Desktop).
5. **Still ambiguous on a non-trivial task** → ask once via `AskUserQuestion` listing the top 23 candidates.
### Backend call patterns
**Semrush MCP (default):**
```
mcp__semrush__keyword_research(query="<seed>", database="us")
mcp__semrush__get_report_schema(report_id="...")
mcp__semrush__execute_report(report_id="...", params={...})
```
**OurSEO CLI (Korean default, Claude Code):**
```bash
our keywords volume "<keyword>" --location 2410 --language ko
our keywords ideas "<keyword>" --location 2410 --limit 50
@@ -34,48 +64,50 @@ our keywords intent "<kw1>" "<kw2>" "<kw3>"
our keywords difficulty "<kw1>" "<kw2>"
```
**Interactive fallback — DataForSEO MCP:**
**Ahrefs MCP (when user requests, or for GSC first-party):**
```
mcp__dfs-mcp__dataforseo_labs_google_keyword_overview
mcp__dfs-mcp__dataforseo_labs_google_keyword_ideas
mcp__dfs-mcp__dataforseo_labs_google_keyword_suggestions
mcp__dfs-mcp__dataforseo_labs_search_intent
mcp__dfs-mcp__dataforseo_labs_bulk_keyword_difficulty
mcp__dfs-mcp__kw_data_google_ads_search_volume
mcp__dfs-mcp__dataforseo_labs_google_keywords_for_site
mcp__ahrefs__keywords-explorer-overview(keyword="<seed>", country="us")
mcp__ahrefs__keywords-explorer-matching-terms(keyword="<seed>", country="us")
mcp__ahrefs__keywords-explorer-volume-by-country(keyword="<seed>")
mcp__ahrefs__gsc-keywords(...)
```
### Common Parameters
- **location_code**: 2410 (Korea), 2840 (US), 2392 (Japan)
- **language_code**: ko, en, ja
**OurSEO Agent MCP (Claude Desktop, KG/entity expansion):**
```
mcp__ourseo__search_knowledge_graph(query="<brand or entity>")
mcp__ourseo__crawl_website(url="<target>", max_pages=50)
```
### Web Search for Naver Discovery
```
WebSearch: Naver autocomplete and trend discovery
```
### Common parameters across backends
| Concept | Semrush | Ahrefs | DataForSEO / `our` CLI |
|---|---|---|---|
| Korean market | `database="kr"` | `country="kr"` | `--location 2410` |
| US market | `database="us"` | `country="us"` | `--location 2840` |
| Japan | `database="jp"` | `country="jp"` | `--location 2392` |
| Language | (database-bound) | (country-bound) | `--language ko`/`en`/`ja` |
## Workflow
### 1. Seed Keyword Expansion
1. Input seed keyword (Korean or English)
2. Fetch search volume via `our keywords volume "<seed>" --location 2410 --language ko`
3. Expand with `our keywords ideas "<seed>" --location 2410 --limit 50`
4. Get autocomplete suggestions via MCP: `mcp__dfs-mcp__dataforseo_labs_google_keyword_suggestions`
5. Apply Korean suffix expansion if Korean market
6. Deduplicate and merge results
1. Determine backend via **Data Source Selection** above.
2. Fetch search volume for the seed.
3. Expand via the chosen backend's "related" / "ideas" / "matching-terms" endpoint.
4. Apply Korean suffix expansion if Korean market (regardless of backend).
5. Deduplicate and merge.
### 2. Intent Classification & Clustering
1. Classify each keyword by search intent
2. Group keywords into topic clusters
3. Identify pillar topics and supporting terms
4. Calculate cluster-level metrics (total volume, avg KD)
1. Classify each keyword by search intent (informational / navigational / commercial / transactional).
2. Group keywords into topic clusters.
3. Identify pillar topics and supporting terms.
4. Calculate cluster-level metrics (total volume, avg KD).
### 3. Gap Analysis
1. Pull organic keywords for target: `our keywords for-site <target.com> --location 2410 --limit 100`
2. Pull organic keywords for competitors: `our keywords for-site <competitor.com> --location 2410 --limit 100`
3. Identify keywords present in competitors but missing from target
4. Score opportunities by volume/difficulty ratio
5. Prioritize by intent alignment with business goals
1. Pull organic keywords for target via chosen backend.
2. Pull organic keywords for competitors (parallel).
3. Identify keywords present in competitors but missing from target.
4. Score opportunities by volume/difficulty ratio.
5. Prioritize by intent alignment with business goals.
## Output Format
@@ -83,26 +115,30 @@ WebSearch: Naver autocomplete and trend discovery
## Keyword Strategy Report: [seed keyword]
### Overview
- Data source: [Semrush | Ahrefs | OurSEO CLI | OurSEO MCP | GSC]
- Market: [database/location code]
- Total keywords discovered: [count]
- Topic clusters: [count]
- Total search volume: [sum]
### Top Clusters
| Cluster | Keywords | Total Volume | Avg KD |
|---------|----------|-------------|--------|
|---|---|---|---|
| ... | ... | ... | ... |
### Top Opportunities
| Keyword | Volume | KD | Intent | Cluster |
|---------|--------|-----|--------|---------|
|---|---|---|---|---|
| ... | ... | ... | ... | ... |
### Keyword Gaps (vs competitors)
| Keyword | Volume | Competitor Position | Opportunity Score |
|---------|--------|-------------------|-------------------|
|---|---|---|---|
| ... | ... | ... | ... |
```
Always record the chosen data source in the **Overview** so future audits can compare apples to apples.
## Notion Output (Required)
All audit reports MUST be saved to OurDigital SEO Audit Log:

View File

@@ -2,8 +2,17 @@ name: seo-keyword-strategy
description: |
Keyword strategy and research for SEO campaigns. Triggers: keyword research, keyword analysis, keyword gap, search volume, keyword clustering, intent classification.
# Allowed tools list every backend the skill can pull keyword data from.
# Per-task selection happens in SKILL.md > Data Source Selection — NOT here.
allowed-tools:
- mcp__ahrefs__*
# SEO data backends
- mcp__semrush__* # default for keyword/SERP/organic
- mcp__ahrefs__* # Ahrefs (Claude Desktop namespace)
- mcp__claude_ai_Ahrefs__* # Ahrefs (Claude.ai namespace) — same backend
- mcp__ourseo__* # OurSEO Agent MCP (KG, crawl-derived keywords)
- mcp__dfs-mcp__* # DataForSEO MCP fallback
- Bash # `our keywords *` CLI (Claude Code only)
# Output / supplementary
- mcp__notion__*
- WebSearch
- WebFetch

View File

@@ -1,15 +1,54 @@
# Ahrefs
# Ahrefs MCP
> TODO: Document tool usage for this skill
Use Ahrefs when the user explicitly asks for Ahrefs data, when DR/UR weighting matters, or when the task needs `gsc-keywords` (Ahrefs is the only SEO MCP that exposes a Google Search Console integration directly).
## Available Commands
Namespace: `mcp__ahrefs__*` (Claude Desktop) / `mcp__claude_ai_Ahrefs__*` (Claude.ai). Same backend.
- [ ] List commands
## Keyword endpoints
## Configuration
- `keywords-explorer-overview` — volume, CPC, KD, parent topic
- `keywords-explorer-matching-terms` — phrase-match expansion
- `keywords-explorer-related-terms` — related ideas
- `keywords-explorer-search-suggestions` — autocomplete-style suggestions
- `keywords-explorer-volume-by-country` — country breakdown for one keyword
- `keywords-explorer-volume-history` — historical search volume
- [ ] Add configuration details
## GSC integration (Ahrefs-only)
- `gsc-keywords` — keywords the user's verified site actually ranks for (impressions, clicks, CTR, position)
- `gsc-keyword-history` — historical performance of a query
GSC endpoints require the Ahrefs project to be connected to the GSC property. Confirm with the user that the project exists in their Ahrefs workspace before relying on these.
## Common parameters
- `country``us`, `kr`, `jp`, etc. (lowercase ISO-2)
- `keyword` — the seed term
- `limit` — usually 30100
## Examples
- [ ] Add usage examples
**Quick overview:**
```
mcp__ahrefs__keywords-explorer-overview(keyword="enterprise CRM", country="us")
```
**Related terms in Korean:**
```
mcp__ahrefs__keywords-explorer-related-terms(keyword="신라호텔", country="kr", limit=50)
```
**GSC first-party queries:**
```
mcp__ahrefs__gsc-keywords(project_id="<ahrefs project id>", limit=100)
```
## When NOT to use Ahrefs for this skill
- Default keyword volume / matching terms — Semrush is the project default; only switch on explicit request.
- Bulk Korean expansion — `our keywords ideas --location 2410` is usually cheaper.
- Entity / Knowledge Graph seeding — `mcp__ourseo__search_knowledge_graph`.
## Reference
Always check `mcp__ahrefs__doc` once per session before first call — it documents current parameter shapes and may have changed.

View File

@@ -0,0 +1,58 @@
# Google Search Console (GSC)
GSC is the only **first-party** data source on this list — what the user's verified site actually rendered impressions / clicks for in Google. Estimates from Semrush, Ahrefs, and DataForSEO are modelled; GSC is observed.
Two entry points to GSC for this skill:
1. **`our research search-console` CLI** — OurSEO Agent's GSC integration (recommended; cached).
2. **Ahrefs `gsc-keywords`** — only if the site is connected as an Ahrefs project AND the user is already in Ahrefs context.
## CLI commands (`our research search-console`)
See `our research search-console --help` for the current command surface. Typical patterns:
```bash
# Queries the site actually ranks for, last 28 days
our research search-console queries --site sc-domain:example.com --days 28
# Top pages by impressions
our research search-console pages --site sc-domain:example.com --days 28
# Query/page combinations
our research search-console combined --site sc-domain:example.com --days 28
```
The `sc-domain:` prefix is required for Domain-verified properties. URL-prefix properties use the plain URL (`https://example.com/`). See gotcha note: `our-claude-skills/custom-skills/15-seo-search-console/code/gotcha/gsc-cli-integration.md`.
## Ahrefs GSC tools
When the user is already working in Ahrefs:
```
mcp__ahrefs__gsc-keywords(project_id="<ahrefs project id>", limit=100)
mcp__ahrefs__gsc-keyword-history(project_id="...", keyword="...")
mcp__ahrefs__gsc-pages(project_id="...")
mcp__ahrefs__gsc-performance-history(project_id="...")
mcp__ahrefs__gsc-ctr-by-position(project_id="...")
```
Requires the Ahrefs project to be connected to the GSC property. Confirm with the user before assuming the link exists.
## When to bring GSC into keyword work
- **Validation step**: after generating a keyword list from Semrush / Ahrefs / DataForSEO, intersect with GSC queries to see which are already driving impressions.
- **Pruning**: drop keywords from the list that have zero GSC impressions over the last 90 days for a mature site (signals the site doesn't compete on them despite the model's volume estimate).
- **Cannibalization detection**: GSC `query × page` lets you find queries where multiple URLs share impressions.
- **Anonymous-query analysis**: `mcp__ahrefs__gsc-anonymous-queries` surfaces queries Google hides from the standard report — sometimes reveals brand variants.
## Configuration
| Variable | Purpose |
|---|---|
| `SEO_AGENT_GSC_SERVICE_ACCOUNT` | Path to the GSC service-account JSON for the OurSEO CLI |
| `GSC_CACHE_TTL` | GSC cache TTL in seconds (default 3600) |
## When NOT to use GSC for this skill
- Discovery of keywords the site does **not** yet rank for — GSC by definition only shows queries that already triggered impressions. Use Semrush / Ahrefs / DataForSEO for net-new discovery.
- Competitive keyword pulls — GSC is single-site.

View File

@@ -0,0 +1,74 @@
# OurSEO Agent (CLI + MCP)
The OurSEO Agent (`~/Project/our-seo-agent`) covers two distinct paths for this skill:
1. **CLI**`our keywords *` (Claude Code, via Bash). DataForSEO under the hood. Cheapest per call, batch-friendly, Korean-aware.
2. **MCP**`mcp__ourseo__*` (Claude Desktop). Lighter surface: crawl, audit, Knowledge Graph entity expansion.
Pick the path that matches your current Claude environment.
## CLI commands (Claude Code, primary for Korean market)
```bash
# Volume + difficulty + intent
our keywords volume "<keyword>" --location 2410 --language ko
our keywords difficulty "<kw1>" "<kw2>" --location 2410
our keywords intent "<kw1>" "<kw2>" "<kw3>"
# Expansion
our keywords ideas "<seed>" --location 2410 --limit 50
our keywords for-site <competitor.com> --location 2410 --limit 100
# Naver (Korean engines)
our research naver keywords volume "<keyword>"
our research naver keywords ideas "<keyword>" --limit 30
# Cross-engine compare (where supported)
our research keywords compare "<keyword>" --engines naver
```
| Location code | Market |
|---|---|
| `2410` | Korea |
| `2840` | United States |
| `2392` | Japan |
| Language code | Language |
|---|---|
| `ko` | Korean |
| `en` | English |
| `ja` | Japanese |
Cache (avoid duplicate calls): `our research cache list --engine <name>` / `our research cache clear --older-than 30d`.
## MCP tools (Claude Desktop)
| Tool | Purpose for keyword work |
|---|---|
| `mcp__ourseo__search_knowledge_graph` | Resolve a brand / entity to Knowledge Graph IDs — useful as a *seeding* step for keyword expansion around the entity. |
| `mcp__ourseo__crawl_website` | Crawl the target site and pull on-page keyword inventory (title/h1/meta) — ground truth for what the site already targets. |
| `mcp__ourseo__audit_page` | Single-page SEO audit; not a keyword tool per se, but useful for validating that high-value keywords are actually present on the page. |
| `mcp__ourseo__check_serp` | Check SERP position for a keyword/domain pair — bridge to position tracking. |
| `mcp__ourseo__find_similar_pages` | Semantic similarity over a prior crawl — supports topic clustering. |
The OurSEO MCP does **not** expose DataForSEO keyword volume directly. For volume + KD + ideas in Claude Desktop, use Semrush MCP (`mcp__semrush__*`) or DataForSEO MCP (`mcp__dfs-mcp__*`).
## Configuration
The CLI reads from `~/Project/our-seo-agent/config/config.yaml` and these env vars:
| Variable | Purpose |
|---|---|
| `DATAFORSEO_USERNAME` / `DATAFORSEO_PASSWORD` | DataForSEO auth |
| `NAVER_CLIENT_ID` / `NAVER_CLIENT_SECRET` | Naver Open API + Search Ad |
| `GOOGLE_KG_API_KEY` | Knowledge Graph Search API |
See the project `CLAUDE.md` for full env-var reference. Credentials live in 1Password — fetch with `op://Development/<item>/credential`.
## When to choose OurSEO over Semrush / Ahrefs
- Korean-market batch work (Naver + Google together).
- Crawl-derived keyword inventory (what the site itself targets, not estimates).
- Knowledge Graph entity seeding.
- Cost-sensitive bulk volume lookups.
- Cross-engine comparison (Naver + DataForSEO via `our research keywords compare`).

View File

@@ -0,0 +1,57 @@
# Semrush MCP
Default keyword-research backend per SKILL.md > Data Source Selection.
## Call pattern
The Semrush MCP follows a three-step discovery → schema → execute pattern (see Semrush MCP server instructions):
1. **Discovery** — pick the right toolkit for the task:
- `mcp__semrush__keyword_research` — keyword overview, related, volume, intent, KD
- `mcp__semrush__organic_research` — domain/URL organic keywords + competitors
- `mcp__semrush__overview_research` — domain/URL overview (traffic, ranking dist.)
- `mcp__semrush__url_research` — single-URL deep dive
2. **`mcp__semrush__get_report_schema(report_id=...)`** — fetch the param spec for the chosen report.
3. **`mcp__semrush__execute_report(report_id=..., params={...})`** — run it.
Default `database="us"` when the user does not specify a market. Use `display_limit=30-50` for exploratory queries.
## Available reports (keyword-research toolkit)
- Keyword overview (volume, CPC, competition, KD, trend)
- Related keywords
- Matching phrases (broad / phrase / exact match)
- Keyword difficulty (single + bulk)
- Search intent
- Keyword historical volume
## Configuration
| Parameter | Value |
|---|---|
| Default database | `us` |
| Korean market database | `kr` |
| Japan market database | `jp` |
| Auth | Semrush API key on the MCP server side (no local config) |
## Examples
**English keyword volume:**
```
mcp__semrush__keyword_research(query="enterprise CRM software", database="us")
→ pick report_id from response
mcp__semrush__get_report_schema(report_id="phrase_this")
mcp__semrush__execute_report(report_id="phrase_this", params={"phrase": "enterprise CRM software", "database": "us"})
```
**Korean expansion:**
```
mcp__semrush__keyword_research(query="신라호텔", database="kr")
mcp__semrush__execute_report(report_id="phrase_related", params={"phrase": "신라호텔", "database": "kr", "display_limit": 50})
```
## When NOT to use Semrush
- Task needs **GSC first-party query data** — use Ahrefs `gsc-keywords` or `our research search-console` instead.
- Task needs **Knowledge Graph entity expansion** — use `mcp__ourseo__search_knowledge_graph`.
- Task needs **bulk cheap calls at Korean scale**`our keywords *` CLI (DataForSEO) is usually cheaper.