---
sharksapi_version: p-70c0770bf5
name: competitor-watch
description: Monthly AI-visibility / GEO competitor benchmark for up to 4 competitors — AI share of voice, mention rank, AI citations, Google AI Overview, web brand mentions and page citability — rendered as a competitor_watch dashboard widget with best/worst highlighting, month-over-month deltas and Estonian-language insights.
allowed-tools: [score_citability, get_social_mentions, read_dashboard, memory_search, memory_write, create_dashboard, update_dashboard, check_ai_overview]
version: 2.2.0
license: MIT
metadata:
  author: SharksAPI
  tags: [competitor-analysis, ai-visibility, geo, benchmarking, estonian]
  triggers: [analüüsi konkurente, competitor analysis, võrdle konkurentidega, compare competitors, konkurentide uuring, competitor benchmark, AI nähtavus konkurendid, kes on meie konkurendid]
---

# Competitor Watch

## When to use

User says things like: "analüüsi konkurente", "compare us with competitors", "competitor analysis", "võrdle konkurentidega", "AI nähtavus konkurentidega võrreldes", "kes on meie konkurendid", or "competitor benchmark".

## Language

Respond in Estonian by default. Use English only if the user writes in English.

## Two modes

- **First run** — steps 1–5 below: choose competitors, create the fixed prompt set, measure, add the widget.
- **Monthly refresh** (the normal case — most SharksAPI dashboards already carry a `competitor_watch` widget with a `schema_version` of `competitor-watch 2.x`) — see "Monthly refresh" at the end. Never create a second competitor_watch widget on a dashboard that has one; update it in place so the ▲/▼ deltas work.

## High-level flow

Collect AI-visibility and GEO-readiness data for the client's domain plus up to 4 competitor domains, then render a `competitor_watch` widget on the user's dashboard: a comparison table with two sections — **AI-vastused** (AI answers) and **GEO-valmidus** (GEO readiness) — with best/worst highlighting, ▲/▼ deltas against last month, and a "Peamised järeldused" insights list.

Organic rankings, paid ads and social followers are NOT part of this widget any more — rank trends live in the SEO positions chart, the rest in their own widgets.

## Step 1 — Identify domains

Ask the user for:
1. Their own domain (the "project" column).
2. Up to 4 competitor domains.
3. Target market / country code (default: EE).

Confirm the list before proceeding.

## Step 2 — AI-vastused (AI answers)

Two kinds of numbers: a prompt test you run yourself, and a deterministic Google AI Overview check.

### 2a. Fixed prompt set (share of voice)

1. `memory_search` for `competitor_watch.ai_prompts`. If it exists, use EXACTLY that prompt list — never change it between months, or the trend is meaningless.
2. If it does not exist, write 15 category prompts — no brand names — mixing Estonian and English, e.g. "soojuspump Tallinn hind", "parim õhk-vesi soojuspump Eestis", "best heat pump installer Estonia", "kuidas valida maakütte paigaldajat". Save them with `memory_write` (scope `global`, type `fact`, title `competitor_watch.ai_prompts`, content = numbered list + date).
3. Run every prompt on ChatGPT, Perplexity and Gemini (45 observations). Record per observation: brands mentioned in order, and which URLs were cited as sources.
4. Per domain compute:
   - `ai_sov_pct` — % of the 45 observations where the brand was named (0–100, integer).
   - `ai_mention_rank` — average position of the brand among the brands named, over observations where it was named (1 = named first). `null` if never named.
   - `ai_citations` — number of observations where a URL on that domain was cited as a source.
5. Put the test description in `ai_test`: `{"prompts": 15, "platforms": ["ChatGPT", "Perplexity", "Gemini"], "tested_at": "YYYY-MM-DD"}`.

If you can only reach some platforms (e.g. only Gemini with Google Search grounding, as the server-side runner does), measure on those, list exactly them in `ai_test.platforms`, set `ai_test.observations` to prompts × platforms actually run, and say so in the first insight. Never present a one-platform result as a three-platform one. If you cannot run the prompts at all, set the three fields to `null` and add the insight "AI share-of-voice test jäi tegemata — vajab promptide käivitamist."

### 2b. Google AI Overview

SharksAPI projects no longer use DataForSEO (dropped 09.09.2026), so `check_ai_overview` is normally unavailable — do not ask the user to connect it. Run the same 15 prompts in Google Search yourself (a browser you drive, anonymous / logged-out) as a fourth platform. Per prompt note whether an AI Overview was shown and which domains it cites. `ai_overview_cited` = prompts where the domain was cited, `ai_test.ai_overview_keywords` = prompts that showed an AI Overview, `ai_test.ai_overview_keywords_tested` = 15. Add "Google AI Overview" to `ai_test.platforms`.

```
Reference: plugins/sharksapi-marketing/references/ai_visibility.md
```

## Step 3 — GEO-valmidus (GEO readiness)

- **Brändi mainimisi veebis (30 p)** — `get_social_mentions(query=<brand name>, days=30)` per domain; `web_mentions_30d` = total count of `mentions[]`. Use the brand name as people write it (e.g. "Ait-Nord"), not the domain.
- **Tsiteeritavuse skoor** — `score_citability(urls=[homepage, main service page])` per domain; `citability_score` = `average_score`. Use the same two page types for every domain so the scores compare. Keep the per-page `recommendations` for the insights.

## Step 4 — Delta vs previous month

`read_dashboard(token)` and find the existing `competitor_watch` widget. For every entity copy its current numeric fields into a `previous` object on the new entity (keys: `ai_sov_pct`, `ai_mention_rank`, `ai_citations`, `ai_overview_cited`, `web_mentions_30d`, `citability_score`). Set top-level `previous_generated_at` to the old widget's `generated_at`. The renderer shows ▲/▼ deltas under each value; a lower `ai_mention_rank` counts as an improvement. Replace the old widget in place (`update_widgets` at its position) rather than adding a second one. A legacy widget (keys `ai_score`, `ai_mentions`, `seo_score` …) has no comparable numbers except `ai_citations` — copy that one and leave the rest of `previous` out.

## Step 5 — Assemble the widget

Assemble the `competitor_watch` widget payload and call `update_dashboard` (or `create_dashboard` if no dashboard exists yet):

```json
{
  "tool": "update_dashboard",
  "arguments": {
    "token": "{dashboard_token}",
    "add_widgets": [{
      "type": "competitor_watch",
      "title": "Competitor Watch — {market} {YYYY-MM}",
      "position": 0,
      "grid_cols": 12,
      "content": {
        "project": {
          "domain": "{client_domain}",
          "ai_sov_pct": 27,
          "ai_mention_rank": 1.8,
          "ai_citations": 4,
          "ai_overview_cited": 2,
          "web_mentions_30d": 14,
          "citability_score": 62,
          "previous": { "ai_sov_pct": 20, "ai_mention_rank": 2.4, "ai_citations": 3, "ai_overview_cited": 1, "web_mentions_30d": 9, "citability_score": 55 }
        },
        "competitors": [
          {
            "domain": "{comp1_domain}",
            "ai_sov_pct": 40,
            "ai_mention_rank": 1.3,
            "ai_citations": 7,
            "ai_overview_cited": 5,
            "web_mentions_30d": 31,
            "citability_score": 71,
            "previous": { "ai_sov_pct": 38, "ai_mention_rank": 1.5, "ai_citations": 6, "ai_overview_cited": 5, "web_mentions_30d": 22, "citability_score": 70 }
          }
        ],
        "generated_at": "{YYYY-MM-DD}",
        "previous_generated_at": "{YYYY-MM-DD of the replaced widget}",
        "market": "{EE}",
        "ai_test": { "prompts": 15, "platforms": ["ChatGPT", "Perplexity", "Gemini"], "tested_at": "{YYYY-MM-DD}", "ai_overview_keywords": 3, "ai_overview_keywords_tested": 15 },
        "insights": [
          "AI share of voice 27 % (+7 pp) — konkurent X on siiski 40 %; AI Overview tsiteerib meid 2/15 promptil.",
          "Keskmine mainimiskoht 1.8 (parem kui eelmisel kuul 2.4) — bränd nimetatakse enamasti teisena pärast X-i.",
          "Tsiteeritavuse skoor 62 — avalehel puudub vastus-esimesena lõik ja autor; teenuselehel puudub kuupäev.",
          "Veebimainimisi 14 (+5) — Reddit ja YouTube; konkurent Y 31."
        ]
      }
    }]
  }
}
```

**Notes:**
- Pass `null` for any metric that could not be collected — the renderer shows "N/A".
- The `insights` array should contain 3–5 Estonian-language bullet conclusions that talk about the change (delta), not only the absolute numbers.
- If creating a new dashboard, ask the user for a password first (required by `create_dashboard`).

```
Reference: plugins/sharksapi-marketing/references/sharksapi_a2a.md — Section "competitor_watch widget"
```

## Monthly refresh (existing widget)

Every SharksAPI client dashboard got a v2 `competitor_watch` widget on 09.09.2026 and each project memory holds a `competitor_watch.ai_prompts` entry with the 15 prompts, the competitor list and the citability page pairs. Refresh it once a month like this:

1. `read_dashboard(token)` → note the widget's `position`, `generated_at`, and every entity's current numbers (these become `previous`).
2. `memory_search("competitor_watch.ai_prompts")` → reuse the prompt list, competitors and citability URLs EXACTLY. Change a competitor only if the user asks; then drop its `previous`.
3. Re-run Step 2 (prompts on every platform you can reach, Google Search for AI Overview) and Step 3 (`score_citability` on the same page pairs, `get_social_mentions` per brand).
4. Build the full content object (Step 5 shape) with `previous` + `previous_generated_at` filled from step 1, `generated_at` = today, `schema_version: "competitor-watch 2.2.0"`, and 3–5 Estonian insights that talk about the change.
5. `update_dashboard(token, update_widgets=[{position, title: "Competitor Watch — AI & GEO {market} {YYYY-MM}", content}])` — `content` replaces the whole `source_ref`, so always send the complete object. Do not `add_widgets`.
6. `memory_write` a short `result` entry: date, headline numbers, what changed.

If the dashboard has no competitor_watch widget at all, fall back to the first-run flow.

## Edge cases

- **Only 1 competitor**: the table still renders with 2 columns (project + comp1); remaining comp columns are omitted.
- **AI prompt test not run**: populate ai_sov_pct / ai_mention_rank / ai_citations with null and add an insight: "AI share-of-voice test jäi tegemata — vajab promptide käivitamist." Still fill ai_overview_cited, web_mentions_30d and citability_score.
- **No browser to run Google Search** (server-side runner): leave `ai_overview_cited` null and add the insight "Google AI Overview jäi mõõtmata"; do not invent a value.
- **Web mentions all zero**: get_social_mentions reads Reddit + YouTube (plus LinkedIn/Facebook/Bluesky only when connected). Zero is a real value for small local brands — say so, do not invent numbers.
- **First month (no previous widget)**: omit `previous` and `previous_generated_at`; no deltas are shown.

## References

- `plugins/sharksapi-marketing/references/ai_visibility.md` — AI Visibility Reference (fixed prompt set, share of voice, mention rank, AI Overview check, citability score)
- `plugins/sharksapi-marketing/references/sharksapi_a2a.md` — SharksAPI A2A Protocol Reference (competitor_watch widget schema + tool call examples)
