> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mavera.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Competitor News Monitoring

> Search for competitor mentions across news sources, aggregate by entity, and produce structured competitive intelligence via Mave

### Scenario

Your competitors appear in industry news daily — product launches, funding rounds, executive hires, partnerships. This job searches for competitor mentions across all news sources, aggregates them by competitor, then runs the corpus through Mave for structured competitive intelligence: what they're doing, how the market reacts, and what opportunities emerge for your brand.

**Flow:** NewsAPI `GET /everything?q={competitor}` → Aggregate by entity → Mavera `POST /mave/chat` → Competitive intelligence brief

### Code

<CodeGroup>
  ```python Python theme={"dark"}
  import os, requests, time
  from datetime import datetime, timedelta

  NA_KEY = os.environ["NEWSAPI_KEY"]
  NA_BASE = "https://newsapi.org/v2"
  NA_H = {"X-Api-Key": NA_KEY}
  MV = os.environ["MAVERA_API_KEY"]
  MV_BASE = "https://app.mavera.io/api/v1"
  MV_H = {"Authorization": f"Bearer {MV}", "Content-Type": "application/json"}

  COMPETITORS = ["Competitor A", "Competitor B", "Competitor C"]
  LOOKBACK_DAYS = 7
  from_date = (datetime.now() - timedelta(days=LOOKBACK_DAYS)).strftime("%Y-%m-%d")

  # 1. Search news for each competitor
  all_articles = {}
  for comp in COMPETITORS:
      r = requests.get(f"{NA_BASE}/everything", headers=NA_H, params={
          "q": f'"{comp}"', "from": from_date, "sortBy": "relevancy",
          "language": "en", "pageSize": 15,
      })
      if r.status_code == 429:
          print(f"Rate limited — skipping {comp}")
          continue
      r.raise_for_status()
      articles = r.json().get("articles", [])
      all_articles[comp] = articles
      print(f"{comp}: {len(articles)} articles")
      time.sleep(1)

  # 2. Build competitor corpus
  corpus_parts = []
  for comp, articles in all_articles.items():
      corpus_parts.append(f"\n## {comp} ({len(articles)} articles)")
      for a in articles:
          corpus_parts.append(
              f"- [{a.get('source',{}).get('name','')}] {a['title']}\n"
              f"  {a.get('description','')[:250]}\n"
              f"  Published: {a.get('publishedAt','')[:10]}"
          )
  corpus = "\n".join(corpus_parts)

  # 3. Mave synthesis
  analysis = requests.post(f"{MV_BASE}/mave/chat", headers=MV_H, json={
      "message": f"You are a competitive intelligence analyst. Analyze these news mentions from the past {LOOKBACK_DAYS} days.\n\n{corpus[:6000]}\n\n"
          "For EACH competitor provide:\n"
          "1. **Activity Summary** — What they shipped, announced, or changed\n"
          "2. **Media Sentiment** — Positive/negative/neutral tone across sources\n"
          "3. **Strategic Signal** — What this tells us about their direction\n"
          "4. **Our Opportunity** — Specific actions we should take in response\n\n"
          "End with a PRIORITY MATRIX: rank competitive threats by urgency (1-10) and impact (1-10)."
  }).json()

  print(f"\nCompetitive Intelligence Brief — {from_date} to today")
  print(f"{'='*60}")
  print(analysis.get("content", "")[:3000])
  ```

  ```javascript JavaScript theme={"dark"}
  const NA_KEY = process.env.NEWSAPI_KEY;
  const NA_BASE = "https://newsapi.org/v2";
  const NA_H = { "X-Api-Key": NA_KEY };
  const MV = process.env.MAVERA_API_KEY;
  const MV_BASE = "https://app.mavera.io/api/v1";
  const MV_H = { Authorization: `Bearer ${MV}`, "Content-Type": "application/json" };

  const COMPETITORS = ["Competitor A", "Competitor B", "Competitor C"];
  const LOOKBACK_DAYS = 7;
  const fromDate = new Date(Date.now() - LOOKBACK_DAYS * 86400000).toISOString().slice(0, 10);

  // 1. Search per competitor
  const allArticles = {};
  for (const comp of COMPETITORS) {
    const r = await fetch(
      `${NA_BASE}/everything?q=${encodeURIComponent(`"${comp}"`)}&from=${fromDate}&sortBy=relevancy&language=en&pageSize=15`,
      { headers: NA_H });
    if (r.status === 429) { console.log(`Rate limited — skipping ${comp}`); continue; }
    const data = await r.json();
    allArticles[comp] = data.articles || [];
    console.log(`${comp}: ${allArticles[comp].length} articles`);
    await new Promise(r => setTimeout(r, 1000));
  }

  // 2. Build corpus
  let corpus = "";
  for (const [comp, articles] of Object.entries(allArticles)) {
    corpus += `\n## ${comp} (${articles.length} articles)\n`;
    for (const a of articles)
      corpus += `- [${a.source?.name || ""}] ${a.title}\n  ${(a.description || "").slice(0, 250)}\n  Published: ${(a.publishedAt || "").slice(0, 10)}\n`;
  }

  // 3. Mave synthesis
  const analysis = await fetch(`${MV_BASE}/mave/chat`, { method: "POST", headers: MV_H,
    body: JSON.stringify({
      message: `Competitive intelligence analyst. Analyze news from past ${LOOKBACK_DAYS} days.\n\n${corpus.slice(0, 6000)}\n\nPer competitor: Activity Summary, Media Sentiment, Strategic Signal, Our Opportunity.\n\nEnd with PRIORITY MATRIX: urgency (1-10) × impact (1-10).`
    }),
  }).then(r => r.json());

  console.log(`\nCompetitive Intelligence Brief — ${fromDate} to today`);
  console.log("=".repeat(60));
  console.log((analysis.content || "").slice(0, 3000));
  ```
</CodeGroup>

### Example Output

```text theme={"dark"}
Competitor A: 12 articles
Competitor B: 8 articles
Competitor C: 3 articles

Competitive Intelligence Brief — 2026-03-10 to today
============================================================

## Competitor A — High Activity
**Activity:** Launched enterprise tier with SOC 2 compliance. Hired VP Sales
from Salesforce. Announced Slack integration.
**Sentiment:** Positive (75%) — TechCrunch, VentureBeat praised UX.
**Signal:** Moving upmarket aggressively. Enterprise play confirmed.
**Our Opportunity:** They'll lose SMB focus. Double down on SMB messaging
and self-serve onboarding.

PRIORITY MATRIX:
| Competitor | Urgency | Impact | Action |
|------------|---------|--------|--------|
| A          | 8       | 9      | Counter enterprise narrative |
| B          | 5       | 6      | Monitor pricing changes |
| C          | 3       | 4      | No immediate action |
```

### Error Handling

<AccordionGroup>
  <Accordion title="Quoted search precision">Wrap competitor names in double quotes (`"Competitor A"`) to avoid partial matches. For common names, add industry terms: `"Acme" AND "marketing platform"`.</Accordion>
  <Accordion title="Date range limits">Free tier searches back 1 month. Business tier goes back to 2019. Adjust `LOOKBACK_DAYS` accordingly.</Accordion>
  <Accordion title="Duplicate articles">NewsAPI may return syndicated copies. Deduplicate by title similarity before sending to Mave.</Accordion>
</AccordionGroup>
