Skip to content

Landscape view

The landscape view is where competitor intelligence comes together into one screen: every keyword across all your confirmed competitors, classified by gap type and scored by severity, in a single sortable, filterable surface. It’s the macro view that the per-competitor gap analysis rolls up into. Because it’s a derived table, understanding how and when it’s built matters as much as reading it.

  • One or more confirmed, crawled competitors (see Adding competitors).
  • A project ID — the rebuild endpoint is scoped per project.

The landscape lives in the keyword_landscape table, which is a materialized view — a precomputed snapshot derived from your competitor crawl data and rankings, not a live join. You never edit it directly. Every row represents one keyword’s standing across your competitive set, carrying the same gap_type and gap_severity you see in per-competitor gap analysis, aggregated to the project level.

Because it’s materialised, it’s fast to query and stable to read, but it reflects the data as of the last rebuild. If you’ve just crawled a new competitor or re-synced rankings, the landscape won’t show those changes until you rebuild it.

The landscape uses the same two dimensions as gap analysis. Gap type classifies each keyword on the precedence ladder — missing > weak > competitive > dominant > opportunity > uncontested — where the most actionable label wins when a keyword could fit more than one bucket:

TypeMeaning
MissingA competitor ranks top 20; you don’t rank
WeakYou rank past position 20; a competitor ranks better
CompetitiveYou and a competitor both rank top 20, close together
DominantYou rank significantly better than competitors
OpportunityYou rank well but a competitor is closing in
UncontestedYou rank; no competitor appears in the top 100

Gap severity is a 0-to-1 float — higher is more urgent — blending competitor position advantage, estimated search volume, and commercial intent. Filter to Missing and Weak, then sort by severity descending, and the top of the list is your highest-leverage work.

The landscape is rebuilt on demand. In the UI, click Refresh landscape; under the hood this calls:

GET /api/landscape/materialize?projectId=<id>

The operation is idempotent — re-running it overwrites the existing rows with freshly computed data rather than appending, so you can rebuild as often as you like without creating duplicates or drift. Rebuild after adding or confirming a competitor, after a competitor recrawl, or after a fresh rankings sync, so the landscape reflects current reality.

Historical landscape snapshots are not retained; the table always represents the latest rebuild. If you need a point-in-time record, export the view before rebuilding.

Rebuild whenever the inputs change: a new confirmed competitor, a completed recrawl (remember competitors recrawl at most once per 7 days), or a new rankings sync. There’s no harm in rebuilding more often than necessary — idempotency guarantees a clean overwrite every time.