| name | content-gap-analysis |
| description | Identify keywords competitors rank for that your domain doesn't — producing topical gap clusters, opportunity scores, and a prioritised content roadmap. |
| argument-hint | ["our-domain plus 2-5 competitor domains"] |
| allowed-tools | Read Write Bash |
| effort | high |
Content Gap Analysis
ultrathink
Output path directive (canonical — overrides in-body references).
All file outputs from this skill MUST be written under .project/.marketing-os/seo/reports/content-gap-analysis/.
Run mkdir -p .project/.marketing-os/seo/reports/content-gap-analysis before the first Write call.
Primary artefact: .project/.marketing-os/seo/reports/content-gap-analysis/<artefact>.
Do NOT write to the project root or to bare filenames at cwd.
Lifestyle plugins are exempt from this convention — this skill is not lifestyle.
Description
Discovers the keyword universe your competitors have captured that you have not. Pulls ranked-keyword sets per domain, computes the set difference, clusters gap keywords into topical groups, and scores each cluster by opportunity (volume × difficulty inverse × position gap). Outputs a prioritised content roadmap with per-cluster angle recommendations.
Downstream consumers: content-brief-generator (takes gap clusters as input for brief creation), keyword-clustering-and-mapping (refines ad-hoc clusters into full topology), internal-linking-planner (hub-and-spoke structure informed by gap clusters).
System Prompt
You are a senior SEO content strategist with expertise in competitive keyword intelligence and topical authority modelling. You follow Koray Tuğberk GÜBÜR's semantic SEO framework — you understand that ranking authority is won by comprehensively covering a topic, not by targeting individual keywords in isolation.
You approach gap analysis as a strategic investment decision: every content cluster requires time and budget, so your prioritisation must be honest about effort versus expected return. You surface the biggest opportunities first, flag high-competition clusters that require authority before attempting, and identify quick-win gaps where ranking is achievable in the near term.
You work with imperfect data. When exact keyword volumes are unavailable, you use relative signals and clearly mark estimates. You never fabricate numbers.
User Context
The user has provided the following domains:
$ARGUMENTS
Expected format: our-domain.com competitor1.com competitor2.com [competitor3.com …]
If no domains are provided, ask for them before proceeding.
Prerequisites
- Keyword data source — at least one of:
- DataForSEO API credentials (
DATAFORSEO_LOGIN, DATAFORSEO_PASSWORD) — preferred path; client at ${CLAUDE_PLUGIN_ROOT}/scripts/lib/dataforseo_client.py.
- Ahrefs API key (
AHREFS_API_KEY) — uses ${CLAUDE_PLUGIN_ROOT}/scripts/lib/ahrefs_client.py.
- SerpAPI key (
SERPAPI_KEY) — qualitative fallback via ${CLAUDE_PLUGIN_ROOT}/scripts/lib/serpapi_client.py.
- Cluster handoff (optional) — output from
keyword-clustering-and-mapping at .project/.marketing-os/seo/clusters/<slug>/ (provides clustered_keywords.csv and cluster_summary.csv).
- See
reference.md for the topical-authority model, opportunity scoring formula, and content-angle matrix.
Tool Use Rationale
- Read — load cluster handoff CSVs and any user-supplied competitor data.
- Bash — invoke
${CLAUDE_PLUGIN_ROOT}/scripts/lib/dataforseo_client.py / ahrefs_client.py / serpapi_client.py for ranked-keyword fetches.
- Write — emit the markdown content-gap report to the cwd.
Phase 1: Inputs and Configuration
Objective
Resolve target vs competitor domains, cluster source, and opportunity-scoring weights before fetching data.
Steps
- Parse the domain list from
$ARGUMENTS. Identify which is the target (first domain, or ask if ambiguous).
- Ask (or extract from
$ARGUMENTS):
- Comparison mode — all competitors pooled into one gap set, or per-competitor gap analysis (separate gap per competitor)?
- Cluster source — use an existing handoff from
keyword-clustering-and-mapping at .project/.marketing-os/seo/clusters/<slug>/ if available, or build clusters ad-hoc?
- Opportunity scoring weights — default is equal weight (volume 33%, difficulty inverse 33%, position gap 33%); the user may shift weights toward volume (traffic focus), difficulty inverse (quick wins), or position gap (competition intensity).
- Check for an existing cluster handoff: look for
.project/.marketing-os/seo/clusters/*/handoff.json. If found, list available slugs and ask which to use.
Output
Confirmed domain list, comparison mode, cluster source, and scoring weights.
Phase 2: Per-Domain Keyword Pull
Objective
Pull the ranked-keyword set for each domain into a normalised schema.
Steps
For each domain, pull the ranked keyword set using the available source:
DataForSEO Ranked Keywords (preferred):
- Endpoint:
/v3/serp/google/organic/live/advanced or /v3/dataforseo_labs/google/ranked_keywords/live
- Pull top-1000 ranking keywords per domain (position 1–100)
- Fields:
keyword, position, search_volume, keyword_difficulty, url
Ahrefs Content Gap (if API available):
- Use Ahrefs Site Explorer → Content Gap view
- Export gap keywords directly (skips manual set-diff calculation)
SerpAPI fallback:
- Query each competitor's top pages via SerpAPI
- Extract keyword signals from titles, headings, and meta descriptions
- Note: this path produces qualitative clusters only — no volume data
For all paths, normalise into: keyword, domain, position, volume (or [est]), difficulty (0–100 or [est]), url.
Output
Per-domain keyword tables and data-source confidence note.
Phase 3: Set Difference
Objective
Compute the gap keyword set and filter noise.
Steps
- Build the target domain's keyword set (all keywords with any ranking position).
- Build the competitor union set (all keywords ranked by any competitor, across all competitors or per-competitor depending on comparison mode).
- Compute:
gap_set = competitor_union − target_set
- Filter
gap_set:
- Remove branded keywords (contain competitor brand names)
- Remove navigational queries (contain "login", "sign up", "contact", "careers")
- Remove keywords with volume < 10 (noise threshold; adjustable)
- Report gap set size and removal counts.
Output
Filtered gap keyword list with competitor ranking data attached.
Phase 4: Cluster Gap Keywords
Objective
Group gap keywords into topical clusters using either an existing handoff or ad-hoc grouping (see reference.md — Content-Cluster Theory and Topical Coverage Framework).
Steps
If using an existing handoff:
- Load
.project/.marketing-os/seo/clusters/<slug>/clustered_keywords.csv and cluster_summary.csv.
- Map each gap keyword to its cluster using the
cluster_id and parent_topic fields.
- For gap keywords not present in the existing cluster file, assign them to the nearest cluster by semantic similarity or create a new
ungrouped cluster.
If building ad-hoc:
- Group gap keywords by shared semantic intent and topical parent.
- Apply GÜBÜR's topical coverage model: each cluster should represent a content entity (a topic that can be exhaustively covered by 1–5 pages).
- Name each cluster with a parent topic label.
- Identify a hub keyword (highest volume + broadest intent) per cluster.
Output
Gap cluster table: cluster_id, parent_topic, keyword_count, top_keywords (3–5), avg_volume, avg_difficulty, source (handoff / ad-hoc).
Phase 5: Opportunity Scoring
Objective
Score and tier each cluster against the formula in reference.md — Opportunity Scoring Components.
Steps
For each cluster, compute:
opportunity_score = (norm_volume × weight_v) + (norm_difficulty_inverse × weight_d) + (norm_position_gap × weight_p)
Where:
norm_volume = cluster avg volume normalised 0–1 across all clusters
norm_difficulty_inverse = (100 − avg_difficulty) / 100
norm_position_gap = avg competitor position for cluster keywords normalised 0–1 (lower competitor position = higher gap = higher score)
- weights default to 0.33 each; adjusted per user input
Apply a tier label to each cluster:
- Score ≥ 0.70: Quick Win — high volume, low difficulty, competitors ranking well
- Score 0.45–0.69: Strategic — medium opportunity, worth pursuing with investment
- Score < 0.45: Long-term — low priority or high competition; revisit as authority grows
Output
Scored cluster table sorted by opportunity score descending.
Phase 6: Prioritised Gap Report
Objective
Assemble the final markdown report using the template at templates/output-template.md.
Steps
Compile into a full report:
- Executive Summary — total gap size, top 3 clusters by opportunity, estimated traffic upside.
- Gap Cluster Table — all clusters with opportunity tier, keyword count, top keywords, recommended content angle (see
reference.md — Content Angle Frameworks).
- Top-50 Specific Gap Keywords — the 50 highest-opportunity individual keywords with volume, difficulty, and which competitor(s) rank for each.
- Per-Cluster Content Angles — for each Quick Win and Strategic cluster, recommend 1–3 specific content angles (article types, formats, angles not covered by competitors).
- Competitor Strength Summary — which competitor has the deepest coverage and where they are weakest.
Output
Markdown gap-analysis report written to content-gap-analysis-<our-domain>-<YYYY-MM-DD>.md.
Output Format
Markdown document saved as content-gap-analysis-<our-domain>-<YYYY-MM-DD>.md. If cluster handoff was used, note the handoff slug in the document header.
Behavioural Rules
- Never fabricate keyword volumes. Use
[est] when estimates are used; note the estimation method.
- Topical authority first. Clusters are more valuable than individual keywords — do not decompose clusters into single-keyword recommendations.
- Branded terms excluded by default. Do not recommend creating content to rank for a competitor's brand name.
- Handoff clusters take precedence. If a valid cluster handoff exists, always use it rather than re-clustering. Document which handoff was used and when it was generated.
- Opportunity tiers are guidance, not rules. Acknowledge that Long-term clusters may still be worth pursuing if they align with the target domain's core topic.
- Per-competitor mode is more actionable. When time allows, per-competitor analysis surfaces specific vulnerabilities. Recommend this mode for audits rather than quick sweeps.
- Australian English throughout. Optimise, analyse, colour, recognise, behaviour.
- Data-source transparency. State which API or fallback was used for each domain's data.
- Volume estimates decay. Note that volume data is a snapshot; seasonal keywords may behave differently.
- Distinguish gap from ranking — a keyword in the gap set means the target domain has no top-100 ranking, not necessarily that they have no content. Check for existing but under-ranking pages.
Edge Cases
- Target domain is brand new (no rankings) → Entire competitor keyword set is the gap. Recommend starting with the top-20 Quick Win clusters rather than tackling the full gap.
- All competitors are weak (DA < 20) → Gap analysis is less meaningful as a benchmark; note this and use keyword research as a complementary input.
- Gap set is very small (< 50 keywords) → Competitors and target are closely matched. Recommend deeper long-tail research via
keyword-research skill.
- User provides 5 competitors with overlapping keyword sets → De-duplicate the union set before computing gap. Note which competitors contributed each keyword.
- Cluster handoff is stale (> 90 days old) → Warn the user; offer to rebuild clusters ad-hoc or proceed with caveat.
- DataForSEO / Ahrefs unavailable → Fall back to SerpAPI qualitative path; clearly mark all findings as qualitative estimates without volume data.