Run the additive migration pass from SKILL-MIGRATION-GUIDE: generate a root SKILL.md for every skill that lacked one, copied from its desktop/SKILL.md (or code/SKILL.md), with name set to the directory name and description + body preserved verbatim. - scripts/migrate_skill_root.py: the reusable, non-destructive migrator (dry-run default). - 61 new root SKILL.md (desktop source for most; code/SKILL.md for 61/62/92). - Untouched: 16/17/95 (already had root); desktop/ and code/ packaging left intact. - All 64 root SKILL.md validate: frontmatter <=1024, kebab name, description present. Still MANUAL (no SKILL.md source — commands/README only), need hand-authored root SKILL.md: 81-mac-optimizer, 90-reference-curator, 91-multi-agent-guide, 94-dintel-bootstrap. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
158 lines
6.8 KiB
Markdown
158 lines
6.8 KiB
Markdown
---
|
|
name: 21-seo-position-tracking
|
|
description: |
|
|
Keyword position tracking for keyword ranking monitoring.
|
|
Triggers: rank tracking, position monitoring, keyword rankings, visibility score, ranking report, 키워드 순위, 순위 추적.
|
|
---
|
|
|
|
# SEO Position Tracking
|
|
|
|
## Purpose
|
|
|
|
Monitor keyword ranking positions, detect significant changes, calculate visibility scores, and compare against competitors using our-seo-agent CLI or pre-fetched ranking data. Provides actionable alerts for ranking drops and segment-level performance breakdown.
|
|
|
|
## Core Capabilities
|
|
|
|
1. **Position Monitoring** - Retrieve current keyword ranking positions from our-seo-agent CLI or pre-fetched data
|
|
2. **Change Detection** - Detect significant position changes with configurable threshold alerts (severity: critical/high/medium/low)
|
|
3. **Visibility Scoring** - Calculate weighted visibility scores using CTR-curve model (position 1 = 30%, position 2 = 15%, etc.)
|
|
4. **Brand/Non-brand Segmentation** - Automatically classify keywords by brand relevance and search intent type
|
|
5. **Competitor Comparison** - Compare keyword overlap, position gaps, and visibility scores against competitors
|
|
|
|
## Data Source Selection
|
|
|
|
This skill can pull rank data from multiple backends. **Pick one per task** — don't fan out by default (cost + rate limits).
|
|
|
|
| Backend | Best for | Notes |
|
|
|---|---|---|
|
|
| **Ahrefs MCP** (`mcp__ahrefs__*`) | Default when an Ahrefs Rank Tracker project exists for the domain | `rank-tracker-overview`, `rank-tracker-serp-overview`, `rank-tracker-competitors-*`. Best historical view; data is what Ahrefs already polled. |
|
|
| **Semrush MCP** (`mcp__semrush__*`) | Default when no Ahrefs project; English/major market position scans | `tracking_research`, `organic_research`. `database="us"` default; `"kr"` for Korean. |
|
|
| **OurSEO CLI** (`our serp *`) | DataForSEO under the hood — full ranked-keywords pulls with volume, Korean-aware via `--location 2410` | Claude Code only (Bash). Commands: `our serp ranked-keywords`, `our serp domain-overview`, `our keywords volume`. |
|
|
| **OurSEO MCP** (`mcp__ourseo__check_serp`) | One-off rank spot-check for a single keyword/domain pair | Cheap; no historical view — pair with prior runs in MySQL / SQLite if tracking over time. |
|
|
| **DataForSEO MCP** (`mcp__dfs-mcp__*`) | Fallback when `our` CLI isn't running; historical rank overview | `dataforseo_labs_google_historical_rank_overview`, `dataforseo_labs_google_ranked_keywords`. |
|
|
| **GSC** (via `our research search-console` or Ahrefs `gsc-*`) | **First-party position data** — what Google actually rendered for the verified site | Only first-party source — use to validate or replace estimated positions. |
|
|
|
|
### How to pick
|
|
|
|
1. **User named a backend explicitly** → use it.
|
|
2. **User preference memory** — read `feedback_seo_tool_preferences.md`; honor the task-type default.
|
|
3. **Site is verified in GSC** AND task is single-site tracking → prefer **GSC** for ground truth, supplement with Semrush/Ahrefs for competitor delta.
|
|
4. **Ahrefs project exists for the domain** → prefer Ahrefs `rank-tracker-*`.
|
|
5. **Default**: Semrush MCP for new tracking jobs; **`our serp ranked-keywords`** for Korean batch.
|
|
6. **Still ambiguous + non-trivial** → ask once via `AskUserQuestion`.
|
|
|
|
### Backend call patterns
|
|
|
|
**Ahrefs MCP (when project exists):**
|
|
```
|
|
mcp__ahrefs__rank-tracker-overview(project_id="<id>")
|
|
mcp__ahrefs__rank-tracker-serp-overview(project_id="<id>")
|
|
mcp__ahrefs__rank-tracker-competitors-overview(project_id="<id>")
|
|
mcp__ahrefs__rank-tracker-competitors-stats(project_id="<id>")
|
|
```
|
|
|
|
**Semrush MCP (no Ahrefs project):**
|
|
```
|
|
mcp__semrush__tracking_research(query="<keyword>", database="us")
|
|
mcp__semrush__get_report_schema(report_id="...")
|
|
mcp__semrush__execute_report(report_id="...", params={...})
|
|
```
|
|
|
|
**OurSEO CLI (Korean batch):**
|
|
```bash
|
|
our serp ranked-keywords <domain> --location 2410 --limit 100 --format json
|
|
our serp domain-overview <domain> --location 2410 --format json
|
|
our keywords volume "<kw1>" "<kw2>" --location 2410 --language ko
|
|
our serp competitors <domain> --location 2410
|
|
```
|
|
|
|
**OurSEO MCP (spot-check):**
|
|
```
|
|
mcp__ourseo__check_serp(keyword="<keyword>", domain="<target.com>", country="kr")
|
|
```
|
|
|
|
**GSC (first-party validation):**
|
|
```bash
|
|
our research search-console queries --site sc-domain:<domain> --days 28
|
|
```
|
|
|
|
### Common parameters
|
|
|
|
| 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` |
|
|
|
|
Always record the chosen data source in the report **Overview** so future tracking runs can compare like-for-like.
|
|
|
|
## Workflow
|
|
|
|
### Phase 1: Data Collection
|
|
1. Fetch current ranked keywords: `our serp ranked-keywords <domain> --location 2410 --limit 100 --format json`
|
|
2. Get domain overview: `our serp domain-overview <domain> --location 2410 --format json`
|
|
3. Get search volumes for tracked keywords: `our keywords volume "<kw1>" "<kw2>" --location 2410`
|
|
4. Fetch competitor positions: `our serp ranked-keywords <competitor> --location 2410 --limit 100`
|
|
5. For historical comparison, use MCP: `mcp__dfs-mcp__dataforseo_labs_google_historical_rank_overview`
|
|
|
|
### Phase 2: Analysis
|
|
1. Detect position changes against previous period
|
|
2. Generate alerts for changes exceeding threshold
|
|
3. Calculate visibility score weighted by search volume and CTR curve
|
|
4. Segment keywords into brand/non-brand and by intent type
|
|
5. Compare positions against each competitor
|
|
|
|
### Phase 3: Reporting
|
|
1. Compile position distribution (top3/top10/top20/top50/top100)
|
|
2. Summarize changes (improved/declined/stable/new/lost)
|
|
3. List alerts sorted by severity and search volume
|
|
4. Generate segment-level breakdown
|
|
5. Save report to Notion SEO Audit Log database
|
|
|
|
## Output Format
|
|
|
|
```json
|
|
{
|
|
"target": "https://example.com",
|
|
"total_keywords": 250,
|
|
"visibility_score": 68.5,
|
|
"positions": {
|
|
"top3": 15,
|
|
"top10": 48,
|
|
"top20": 92,
|
|
"top50": 180,
|
|
"top100": 230
|
|
},
|
|
"changes": {
|
|
"improved": 45,
|
|
"declined": 30,
|
|
"stable": 155,
|
|
"new": 12,
|
|
"lost": 8
|
|
},
|
|
"alerts": [
|
|
{
|
|
"keyword": "example keyword",
|
|
"old_position": 5,
|
|
"new_position": 15,
|
|
"change": -10,
|
|
"volume": 5400,
|
|
"severity": "high"
|
|
}
|
|
],
|
|
"segments": {
|
|
"brand": {"keywords": 30, "avg_position": 2.1},
|
|
"non_brand": {"keywords": 220, "avg_position": 24.5}
|
|
}
|
|
}
|
|
```
|
|
|
|
## Notion Output (Required)
|
|
|
|
All tracking reports MUST be saved to OurDigital SEO Audit Log:
|
|
- **Database ID**: `2c8581e5-8a1e-8035-880b-e38cefc2f3ef`
|
|
- **Properties**: Issue (title), Site (url), Category (Position Tracking), Priority, Found Date, Audit ID
|
|
- **Language**: Korean with English technical terms
|
|
- **Audit ID Format**: RANK-YYYYMMDD-NNN
|