COMPETITIVE INTELLIGENCE

Published on March 14, 2026

Track Your Competitors in AI Search Results via API

What you'll learn: How to use the Sellm API to monitor competitor mentions, rankings, and share of voice across ChatGPT, Claude, Perplexity, Gemini, Grok, and Copilot - and build automated competitive intelligence workflows.

When someone asks ChatGPT "What's the best analytics platform for e-commerce?" or Perplexity "Top product analytics tools for online stores," the AI doesn't just recommend one brand. It lists several - and the order, frequency, and sentiment of those mentions define each brand's competitive position in AI search. If your competitor is consistently ranked first across AI engines and you're buried at position four, that's a visibility gap you need to know about.

The Sellm API provides structured competitor data for every analysis run. This guide shows you how to extract that data, build a competitor tracking workflow, and turn raw API responses into actionable competitive intelligence.

How Competitor Data Works in the API

Every time Sellm runs an analysis, it sends your configured prompts to AI providers and parses the responses. The analysis extracts not only whether your brand was mentioned, but every other brand that appeared alongside it. This data surfaces in the API response from GET /v1/async-analysis/{'{'}analysisId{'}'}, which includes a top-level summary and a promptBreakdown array with per-prompt competitor details.

Summary: Aggregate KPIs

The GET /v1/async-analysis/{'{'}analysisId{'}'} endpoint returns the full analysis result once the status is succeeded. The summary object contains your brand's aggregate KPIs:

curl -s "https://sellm.io/api/v1/async-analysis/aa_01abc123" \
  -H "Authorization: Bearer sellm_your_api_key" | python3 -m json.tool

The response includes:

{
  "data": {
    "id": "aa_01abc123",
    "status": "succeeded",
    "prompt": "best analytics platform for e-commerce",
    "summary": {
      "sovPct": 29,
      "coveragePct": 72,
      "avgPos": 2.3,
      "sentiment": 0.76
    },
    "promptBreakdown": [
      {
        "prompt": "best analytics platform for e-commerce",
        "sovPct": 29,
        "coverage": 72,
        "avgPos": 2.3,
        "sentiment": 0.76,
        "volume": 50,
        "topCompetitors": ["mixpanel", "amplitude"],
        "details": {
          "brandHits": 36,
          "competitorHits": { "mixpanel": 42, "amplitude": 31, "heap": 18 },
          "positions": [2, 3, 1, 2, 3],
          "sentiments": [0.8, 0.7, 0.9, 0.75, 0.65]
        }
      }
    ],
    "providerBreakdown": {
      "sovByProvider": [
        { "provider": "ChatGPT", "sov": 33 },
        { "provider": "Claude", "sov": 25 },
        { "provider": "Perplexity", "sov": 29 }
      ],
      "coverageByProvider": [
        { "provider": "ChatGPT", "coverage": 80 },
        { "provider": "Claude", "coverage": 60 },
        { "provider": "Perplexity", "coverage": 75 }
      ],
      "sentimentByProvider": [
        { "provider": "ChatGPT", "sentiment": 0.82 },
        { "provider": "Claude", "sentiment": 0.70 },
        { "provider": "Perplexity", "sentiment": 0.76 }
      ]
    }
  }
}

This gives you an instant snapshot: Mixpanel has 42 mentions versus your 36, making it the top competitor. Amplitude trails you, and Heap appears less frequently but still shows up in over a third of responses.

Prompt-Level Breakdown: competitorHits

The promptBreakdown array drills down to individual prompts. Each entry includes a topCompetitors string array (the top 2 competitors by mention count) and a details.competitorHits object showing exact mention counts per brand:

{
  "promptBreakdown": [
    {
      "prompt": "best analytics platform for e-commerce",
      "sovPct": 22,
      "coverage": 80,
      "avgPos": 3.0,
      "sentiment": 0.72,
      "volume": 45,
      "topCompetitors": ["mixpanel", "amplitude"],
      "details": {
        "brandHits": 10,
        "competitorHits": { "mixpanel": 15, "amplitude": 12, "heap": 8 },
        "positions": [3, 2, 4, 3],
        "sentiments": [0.7, 0.75, 0.68, 0.74]
      }
    },
    {
      "prompt": "which analytics tool has the best e-commerce integrations",
      "sovPct": 35,
      "coverage": 90,
      "avgPos": 1.5,
      "sentiment": 0.84,
      "volume": 40,
      "topCompetitors": ["amplitude", "heap"],
      "details": {
        "brandHits": 14,
        "competitorHits": { "amplitude": 10, "heap": 9, "mixpanel": 7 },
        "positions": [1, 2, 1, 2],
        "sentiments": [0.85, 0.82, 0.88, 0.81]
      }
    }
  ]
}

This is where the real insights live. You can see exactly which prompts your competitors dominate and which ones you're winning. In the example above, Mixpanel outranks you on the general "best analytics" query, but you lead on the integrations-focused query. That tells you where your content strategy is working and where it needs attention.

Building a Competitor Tracking Workflow

Here's a step-by-step workflow that submits an analysis via the API, polls for results, extracts competitor data, and generates actionable reports. Save this as competitor_tracker.py:

Step 1: Submit an Analysis and Poll for Results

import requests
import json
import os
import time
from collections import defaultdict

API_KEY = os.environ["SELLM_API_KEY"]
BASE_URL = "https://sellm.io/api/v1"
HEADERS = {
    "Authorization": f"Bearer {API_KEY}",
    "Content-Type": "application/json",
}


def submit_analysis(prompt, providers=None, locations=None, replicates=3):
    """Submit an async analysis request."""
    body = {
        "prompt": prompt,
        "providers": providers or ["chatgpt", "claude", "perplexity"],
        "locations": ["US"],
        "replicates": replicates,
    }
    if locations:
        body["locations"] = locations
    resp = requests.post(f"{BASE_URL}/async-analysis", headers=HEADERS, json=body)
    resp.raise_for_status()
    return resp.json()["data"]


def poll_analysis(analysis_id, timeout=300, interval=5):
    """Poll until the analysis succeeds or fails."""
    deadline = time.time() + timeout
    while time.time() < deadline:
        resp = requests.get(
            f"{BASE_URL}/async-analysis/{analysis_id}", headers=HEADERS
        )
        resp.raise_for_status()
        data = resp.json()["data"]
        if data["status"] == "succeeded":
            return data
        if data["status"] == "failed":
            raise RuntimeError(f"Analysis {analysis_id} failed")
        time.sleep(interval)
    raise TimeoutError(f"Analysis {analysis_id} timed out after {timeout}s")

Step 2: Analyze Competitor Positions

def analyze_competitors(prompt_breakdown):
    """Build a competitor analysis from prompt-level data."""
    competitor_totals = defaultdict(int)

    for p in prompt_breakdown:
        hits = p.get("details", {}).get("competitorHits", {})
        for name, count in hits.items():
            competitor_totals[name] += count

    # Sort by total mentions descending
    results = [
        {"name": name, "totalMentions": count}
        for name, count in sorted(
            competitor_totals.items(), key=lambda x: x[1], reverse=True
        )
    ]
    return results


def find_competitor_strengths(prompt_breakdown, your_brand_key="your_brand"):
    """Find which prompts each competitor dominates."""
    competitor_wins = defaultdict(list)

    for p in prompt_breakdown:
        hits = p.get("details", {}).get("competitorHits", {})
        brand_hits = p.get("details", {}).get("brandHits", 0)

        for name, count in hits.items():
            if count > brand_hits:
                competitor_wins[name].append({
                    "prompt": p["prompt"],
                    "theirMentions": count,
                    "yourMentions": brand_hits,
                })

    return dict(competitor_wins)

Step 3: Generate a Competitive Report

def print_report(data, your_brand="Acme Analytics"):
    """Print a formatted competitive intelligence report."""
    summary = data["summary"]
    prompt_breakdown = data.get("promptBreakdown", [])

    print("=" * 60)
    print("COMPETITIVE INTELLIGENCE REPORT")
    print("=" * 60)

    # Your brand's position
    print(f"\nYour Brand: {your_brand}")
    print(f"  Share of Voice: {summary['sovPct']}%")
    print(f"  Coverage:       {summary['coveragePct']}%")
    print(f"  Avg Position:   {summary['avgPos']}")
    print(f"  Sentiment:      {summary['sentiment']}")

    # Competitor leaderboard
    competitors = analyze_competitors(prompt_breakdown)
    print(f"\n{'Competitor':<25} {'Total Mentions':<15}")
    print("-" * 40)
    for c in competitors:
        print(f"{c['name']:<25} {c['totalMentions']:<15}")

    # Prompts where competitors beat you
    strengths = find_competitor_strengths(prompt_breakdown)
    if strengths:
        print(f"\nCompetitors outperforming you:")
        for name, wins in strengths.items():
            print(f"  {name}: beats you on {len(wins)} prompt(s)")
            for w in wins[:3]:
                print(f"    - \"{w['prompt'][:60]}\"")
                print(f"      theirs: {w['theirMentions']} vs yours: {w['yourMentions']}")


if __name__ == "__main__":
    # Submit analysis for a competitive query
    result = submit_analysis("best analytics platform for e-commerce")
    analysis_id = result["id"]
    print(f"Submitted analysis: {analysis_id}")

    # Poll until complete
    data = poll_analysis(analysis_id)
    print(f"Analysis completed: {data['status']}")

    # Generate report
    print_report(data)

Run it with:

export SELLM_API_KEY="sellm_your_api_key"
python3 competitor_tracker.py

Example output:

============================================================
COMPETITIVE INTELLIGENCE REPORT
============================================================

Your Brand: Acme Analytics
  Share of Voice: 29%
  Coverage:       72%
  Avg Position:   2.3
  Sentiment:      0.76

Competitor                Total Mentions
----------------------------------------
mixpanel                  42
amplitude                 31
heap                      18

Competitors outperforming you:
  mixpanel: beats you on 1 prompt(s)
    - "best analytics platform for e-commerce"
      theirs: 15 vs yours: 10

Analyzing Competitor Trends Over Time

A single snapshot tells you where you stand today. But competitive intelligence becomes truly powerful when you track changes over time. Submit the same prompt on a regular schedule and compare the results across multiple analyses:

import csv
from datetime import datetime


def run_and_store(prompt, csv_path="competitor_trends.csv"):
    """Run an analysis and append competitor data to a CSV for trending."""
    result = submit_analysis(prompt)
    data = poll_analysis(result["id"])

    summary = data["summary"]
    prompt_breakdown = data.get("promptBreakdown", [])
    competitors = analyze_competitors(prompt_breakdown)

    # Build row
    row = {
        "date": datetime.utcnow().strftime("%Y-%m-%d"),
        "analysisId": data["id"],
        "yourSOV": summary["sovPct"],
    }
    for c in competitors[:5]:
        row[c["name"]] = c["totalMentions"]

    # Append to CSV
    file_exists = os.path.exists(csv_path)
    with open(csv_path, "a", newline="") as f:
        writer = csv.DictWriter(f, fieldnames=row.keys())
        if not file_exists:
            writer.writeheader()
        writer.writerow(row)

    return row


def print_trend_table(csv_path="competitor_trends.csv"):
    """Display SOV trends from stored CSV data."""
    with open(csv_path, "r") as f:
        reader = csv.DictReader(f)
        rows = list(reader)

    if not rows:
        print("No trend data yet.")
        return

    # Get all competitor columns
    meta_cols = {"date", "analysisId", "yourSOV"}
    competitor_cols = sorted(set(rows[0].keys()) - meta_cols)

    header = f"{'Date':<14} {'Your SOV':<10}"
    for col in competitor_cols:
        header += f"{col[:15]:<17}"
    print(header)
    print("-" * len(header))

    for row in rows:
        line = f"{row['date']:<14} {row['yourSOV']:<10}"
        for col in competitor_cols:
            line += f"{row.get(col, '-'):<17}"
        print(line)

Example trend output:

Date           Your SOV  amplitude        heap             mixpanel
---------------------------------------------------------------------
2026-01-27     24        28               15               40
2026-02-03     25        27               16               39
2026-02-10     27        26               17               38
2026-02-17     28        27               18               37
2026-02-24     29        31               18               42

In this example, your brand has gained 5 percentage points of SOV over five weeks while Mixpanel has fluctuated. That's the kind of trend you want to catch early - and the kind you'd never notice without systematic tracking.

Per-Provider Competitive Analysis

Different AI engines may favor different brands. The providerBreakdown object in the analysis response shows how your brand performs on each platform:

def compare_by_provider(data):
    """Show how your brand stacks up on each AI platform."""
    breakdown = data.get("providerBreakdown", {})
    sov_map = {p["provider"]: p["sov"] for p in breakdown.get("sovByProvider", [])}
    cov_map = {p["provider"]: p["coverage"] for p in breakdown.get("coverageByProvider", [])}
    sent_map = {p["provider"]: p["sentiment"] for p in breakdown.get("sentimentByProvider", [])}

    providers = sorted(sov_map.keys())
    print(f"\n{'Provider':<14} {'SOV %':<10} {'Coverage %':<12} {'Sentiment':<10}")
    print("-" * 46)
    for prov in providers:
        print(
            f"{prov:<14} {sov_map.get(prov, '-'):<10} "
            f"{cov_map.get(prov, '-'):<12} {sent_map.get(prov, '-'):<10}"
        )

If you discover that Mixpanel dominates ChatGPT while you lead in Claude, that's a signal to investigate what content ChatGPT's training data favors and adjust your strategy accordingly.

Setting Up Competitor Alerts

Automate notifications when the competitive landscape shifts. This Slack integration alerts you when a competitor's mentions surpass yours or when a new competitor enters the scene:

SLACK_WEBHOOK = os.environ.get("SLACK_WEBHOOK_URL")


def send_slack_alert(title, details):
    """Send a formatted alert to Slack."""
    if not SLACK_WEBHOOK:
        return
    payload = {
        "blocks": [
            {"type": "header", "text": {"type": "plain_text", "text": title}},
            {"type": "section", "text": {"type": "mrkdwn", "text": details}},
        ]
    }
    requests.post(SLACK_WEBHOOK, json=payload)


def check_competitive_alerts(current_data, previous_data, your_brand="Acme Analytics"):
    """Compare two analysis results and alert on competitive changes."""
    current_breakdown = current_data.get("promptBreakdown", [])
    previous_breakdown = previous_data.get("promptBreakdown", [])

    current_competitors = analyze_competitors(current_breakdown)
    previous_competitors = analyze_competitors(previous_breakdown)

    current_map = {c["name"]: c["totalMentions"] for c in current_competitors}
    previous_map = {c["name"]: c["totalMentions"] for c in previous_competitors}

    current_brand_hits = sum(
        p.get("details", {}).get("brandHits", 0) for p in current_breakdown
    )

    alerts = []

    # Check for competitors who overtook your brand
    for name, mentions in current_map.items():
        prev_mentions = previous_map.get(name, 0)
        if prev_mentions <= current_brand_hits and mentions > current_brand_hits:
            alerts.append(
                f"*{name}* overtook you in mentions: "
                f"{prev_mentions} -> {mentions} "
                f"(yours: {current_brand_hits})"
            )

    # Check for new competitors
    new_names = set(current_map) - set(previous_map)
    for name in new_names:
        alerts.append(
            f"New competitor detected: *{name}* "
            f"({current_map[name]} mentions)"
        )

    if alerts:
        send_slack_alert(
            "Competitive Intelligence Alert",
            "\n".join([f"- {a}" for a in alerts])
        )

Pricing

Competitor tracking uses the same Sellm API available on all plans. The competitive intelligence data (topCompetitors, competitorHits) is included in every analysis run at no extra cost:

Competitor data comes from the same analysis runs you already use for brand monitoring. There's no separate charge for competitive intelligence - if you're running prompts, you're already collecting competitor data.

Next Steps

  1. Create a Sellm account and configure prompts that include competitor-relevant queries
  2. Generate an API key in Project Settings
  3. Run the competitor tracker script above to see where you stand
  4. Set up a weekly cron job and Slack alerts for ongoing monitoring
  5. Use the trend data to correlate content changes with competitive position shifts

For the full API reference, including all competitor-related fields and filtering options, visit sellm.io/docs/api.

Know Where You Stand Against Competitors in AI Search

See which brands AI engines recommend alongside yours across ChatGPT, Claude, Perplexity, Gemini, Grok, and Copilot.

Get Started

Frequently Asked Questions

Do I need to configure competitors manually?

No. Sellm automatically detects every brand mentioned in AI responses. The topCompetitors and competitorHits fields are populated from what the AI engines actually say, not from a pre-defined list. You can optionally configure known competitors in project settings for more targeted tracking.

Can I track competitors across specific AI providers?

Yes. Use the providerBreakdown in the analysis response to see your metrics per platform. You can also specify which providers to include when submitting an analysis via the providers array.

How often does competitor data update?

Competitor data updates with every analysis run. On paid plans, scheduled runs happen weekly. You can also trigger manual runs (limited to 1 per 7 days) when you need fresh competitive data outside the regular schedule.

Is competitor tracking included in every plan?

Yes, competitor tracking is included in every API response at no extra cost.