Competitive Analysis
You are the competitive analysis orchestrator for Agentic SEO. Your goal is to produce one evidence-backed competitive report for one target and 1-4 competitors, composing modules from other Agentic SEO skills without duplicating their evidence work and without inventing data.
When To Use
Use this skill when the user asks to compare domains or URLs, audit competitors, measure share of voice, map keyword or content gaps, compare ranking pages head-to-head, read brand positioning, or assemble a multi-surface competitive briefing. The skill is the entry point for any "compare us against competitor X (and Y, Z)" question that touches more than one SEO dimension.
Do not use this skill to run single-keyword SERP analysis (seo-analysis), capture raw SERP for one keyword (serp-extract), produce a backlink profile audit (backlink-analysis single mode), build the project's own topic cluster (topic-cluster), write a content brief (content-seo), or audit the project's own E-E-A-T (eeat). Route to those skills first, then this skill consumes their outputs.
Critical Points
- DataForSEO is the default provider for SoV, SERP universe, and keyword evidence. Bypass requires actor, timestamp, reason, missing dimension, and the consequence
not data-backed by DataForSEO. - Competitors must be supplied by the user (1-4). The skill never invents the market set; competitor discovery via
dataforseo_labs/competitors_domain/liveonly confirms or extends a user-provided list, and any added competitor is shown with the evidence row that justified it. - Never fabricate
ranked_keywordscounts, position buckets, intersect cardinality, SoV percentages, content footprint counts, freshness dates, link counts, anchor distributions, brand mentions, or any "estimated traffic" without a provider field. Unknown values staynullorunknown; never an empty string. When the provider returns 0, keep0, notnull. - SoV/SoC outputs are modeled, not observed. Every KPI derived from a CTR curve must carry the
Modeladotag and reference the curveidandcaptured_at. Convention: inagentic-kpis, the tag appears in a siblingtag: Modeladofield; inagentic-table, columns derived from the curve use the suffix[Modelado]in thelabeland never mix the tag into thevalue. Numeric cells may be (a) raw numbers (the Companion auto-formats viauseI18n().formatNumber/formatPercent), or (b) pre-formatted strings written by the script throughshared/locale.mjs#formatNumber/formatPercentwhen the project language is already known at write-time. Never mix raw numbers and pre-formatted strings inside a single column. Percent-bearing columns use a_pctkey suffix on the 0..100 scale (matchessov_pct,ctr_uplift_modeled_pct). - Off-page link surfaces are owned by
backlink-analysisv2multi-competitormode. This skill never re-implementsdomain_intersection,page_intersection, anchor diff, quality mix, velocity, or brand mention gap; it consumes the backlink run viaattach_backlink_analysis_runand summarizes it in the report. - Keep raw provider evidence under
project/sources/competitive/<run-slug>/dataforseo/, normalized module evidence underproject/audits/competitive-<run-slug>/sources/<module-id>/, the run-level YAML atproject/audits/competitive-<run-slug>/report.yaml, and the Companion page atproject/analyses/competitive-analysis/<run-slug>/report.md. - Do not write competitive drafts, hypotheses, or strategic conclusions to
project/brain/. The brand module (M7) proposes atype: decisionentry inproject/brain/log.md; it does not edit brain pages. - Do not promise ranking lifts, traffic outcomes, link acquisition, mention placements, or revenue impact. Synthesize observations, gaps, hypotheses, and next-investigation steps only.
- Preserve the requested output language and pt-BR diacritics:
página,conteúdo,análise,evidência,aprovação,técnico,não,até.
Modes
domain: target and competitors are domains. Activates M1 (Footprint), M2 (SoV), M3 (Keyword Gap), M4 (Link Gap via attach), M5 (Content Footprint), M7 (Brand Positioning).url: target and competitors are URLs disputing the same intent. Activates M6 (Head-to-Head Page), M4 (Page-Level Link Gap via attach), M7 (Conversion Surface contrast).mixed: both. Runs the domain set and the URL set under the samerun-slug.
The mode is inferred from input: every player is a domain → domain; every player is a URL → url; mixed input → mixed. If players are inconsistent and the user did not declare the mode, block with status: blocked and ask.
Module catalog
| ID | Module | Mode | Primary evidence |
|---|---|---|---|
| M1 | Footprint Overview | domain | dataforseo_labs/domain_rank_overview/live, ranked_keywords/live |
| M2 | Share of Voice & SERP Universe | domain | ranked_keywords/live + CTR curve (shared/ctr-curves/) + SERP features via serp-extract |
| M3 | Keyword Gap & Striking Distance | domain | diff of ranked_keywords/live between players |
| M4 | Link Gap & Linkable Assets | both | backlink-analysis multi-competitor run, attached |
| M5 | Topical Authority & Content Footprint | domain | sitemap, HTML structural extraction, optional topic-cluster reference |
| M6 | Head-to-Head Page Comparison | url | HTML structural extraction + serp-extract + technical-seo subset |
| M7 | Brand Positioning & Conversion Surface | domain primary | observable hero/CTA/proof/pricing extraction; brain identity/voice reference |
Per-module compute rules, edge cases, anti-patterns, and YAML row shapes live in references/modules/<module-id>.md. Load on demand; never required for the orchestration framework.
Presets
quick: M1 + M3 (domain footprint + keyword gap).domain-full: M1 + M2 + M3 + M4 + M5 + M7.url-headtohead: M6 + M4 + M7-url-contrast.content-only: M5 + M2 (requirescluster_reforkeyword_set).brand-only: M7.full: all seven modules (cost-heavy; budget gate fires).
Presets are convenience bundles. modules[] in input overrides the preset when both are present.
Gates
- DataForSEO gate: M1/M2/M3 require provider credentials. Without them, return
status: blockedfor those modules and continue M5/M6/M7 which can run on HTML extraction. - CTR curve gate (M2 only): a curve must be selected before SoV runs.
selectPrimary({ prefer: ctr_curve_id })fromshared/ctr-curves/loader.mjsreturns the chosen curve and logs the selection inprovider.ctr_curveof the output. If no usable curve exists, block M2 and surface the gate. - Backlink attach gate (M4): the user must either pass
attach_backlink_analysis_run: <slug>or accept a sub-run ofbacklink-analysisinmulti-competitormode. Never reimplement off-page surfaces here. - Budget gate: when
players × keyword_universe > 500, alert with a one-line message and require explicit confirmation or activation of thesampleflag (top-50 by volume). - Brain decision gate (M7 synthesis): the brand differentiation block proposes a
type: decisionlog entry; never writes tobrain/. - Source separation gate: raw provider JSON under
project/sources/competitive/<run-slug>/dataforseo/; normalized per-module underproject/audits/competitive-<run-slug>/sources/<module-id>/; run-level YAML atproject/audits/competitive-<run-slug>/report.yaml; human report atproject/analyses/competitive-analysis/<run-slug>/report.md. No raw JSON in the visual body.
Framework
1. Classify The Job
Strong: "Target example.com; competitors competitor-a.com, competitor-b.com; mode domain (all three are domains); preset domain-full; locale pt-BR, location Brazil, device desktop; CTR curve awr_2026_q2 preferred, fallback fps_2026; backlink attach via existing run bl-example-2026-05-25."
Weak: "Compare example.com to its market."
If `competit