> ## 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 Auction Insights → Battle Cards

> Pull auction insights from Google Ads to identify top competitors and generate AI-powered battle cards with Mave Agent.

### Scenario

Google Ads shows you who you compete against in every auction — impression share, overlap rate, outranking share, position above rate. But this data sits in a table nobody reads. You pull auction insights for your top campaigns, identify the biggest competitive threats, then send each competitor to Mave for deep research and battle card generation. The result is AI-generated battle cards backed by both auction data and web research.

### Architecture

```mermaid theme={"dark"}
flowchart LR
    A["Google Ads GAQL (auction_insights)"] --> B[Top competitors by overlap rate] --> C["POST /api/v1/mave/chat (per competitor)"] --> D[Battle cards with auction context]
```

### Code

<CodeGroup>
  ```python Python theme={"dark"}
  import os, requests, time
  from google.ads.googleads.client import GoogleAdsClient
  from collections import defaultdict

  MV = os.environ["MAVERA_API_KEY"]
  CUSTOMER_ID = os.environ["GOOGLE_ADS_CUSTOMER_ID"]

  client = GoogleAdsClient.load_from_env()
  ga_service = client.get_service("GoogleAdsService")

  query = """
      SELECT
          auction_insights.display_domain,
          metrics.auction_insight_search_impression_share,
          metrics.auction_insight_search_overlap_rate,
          metrics.auction_insight_search_outranking_share,
          metrics.auction_insight_search_position_above_rate,
          metrics.auction_insight_search_top_impression_percentage
      FROM auction_insights
      WHERE segments.date DURING LAST_30_DAYS
  """

  response = ga_service.search(customer_id=CUSTOMER_ID, query=query)

  competitors = defaultdict(lambda: {
      "impression_share": [], "overlap_rate": [], "outranking_share": [],
      "position_above_rate": [], "top_impression_pct": [],
  })

  for row in response:
      domain = row.auction_insights.display_domain
      m = row.metrics
      competitors[domain]["impression_share"].append(m.auction_insight_search_impression_share)
      competitors[domain]["overlap_rate"].append(m.auction_insight_search_overlap_rate)
      competitors[domain]["outranking_share"].append(m.auction_insight_search_outranking_share)
      competitors[domain]["position_above_rate"].append(m.auction_insight_search_position_above_rate)
      competitors[domain]["top_impression_pct"].append(m.auction_insight_search_top_impression_percentage)

  def avg(lst):
      return sum(lst) / len(lst) if lst else 0

  comp_summary = []
  for domain, metrics in competitors.items():
      if domain == "Your domain":
          continue
      comp_summary.append({
          "domain": domain,
          "impression_share": avg(metrics["impression_share"]),
          "overlap_rate": avg(metrics["overlap_rate"]),
          "outranking_share": avg(metrics["outranking_share"]),
          "position_above_rate": avg(metrics["position_above_rate"]),
          "top_impression_pct": avg(metrics["top_impression_pct"]),
      })

  comp_summary.sort(key=lambda c: c["overlap_rate"], reverse=True)
  top_competitors = comp_summary[:5]

  print(f"Top {len(top_competitors)} competitors by auction overlap:\n")
  for c in top_competitors:
      print(f"  {c['domain']}: overlap {c['overlap_rate']:.1%}, "
            f"outranking {c['outranking_share']:.1%}, "
            f"pos above {c['position_above_rate']:.1%}")

  for comp in top_competitors:
      prompt = f"""Generate a competitive battle card for {comp['domain']}.

  GOOGLE ADS AUCTION DATA (last 30 days):
  - Impression share: {comp['impression_share']:.1%}
  - Overlap rate with us: {comp['overlap_rate']:.1%} (how often we compete)
  - They outrank us: {comp['outranking_share']:.1%} of the time
  - They appear above us: {comp['position_above_rate']:.1%} of the time
  - Their top impression %: {comp['top_impression_pct']:.1%}

  Research this competitor and produce:
  1. Company overview (funding, size, positioning)
  2. Their strengths (what they do well)
  3. Their weaknesses (where we win)
  4. Pricing intelligence (if available)
  5. Common objections when competing against them
  6. Killer discovery questions for reps
  7. Landmine questions to watch for
  8. Why customers switch from them to us
  9. Recommended ad copy adjustments when competing in the same auction"""

      card = requests.post(
          "https://app.mavera.io/api/v1/mave/chat",
          headers={"Authorization": f"Bearer {MV}", "Content-Type": "application/json"},
          json={"message": prompt},
      ).json()

      print(f"\n{'='*60}")
      print(f"BATTLE CARD: {comp['domain']}")
      print(f"Overlap: {comp['overlap_rate']:.1%} | They outrank us: {comp['outranking_share']:.1%}")
      print(f"{'='*60}")
      print(card.get("content", "")[:1200])
      print(f"Sources: {len(card.get('sources', []))}")
      time.sleep(1)
  ```

  ```javascript JavaScript theme={"dark"}
  const DEV_TOKEN = process.env.GOOGLE_ADS_DEVELOPER_TOKEN;
  const ACCESS_TOKEN = process.env.GOOGLE_ADS_ACCESS_TOKEN;
  const CUSTOMER_ID = process.env.GOOGLE_ADS_CUSTOMER_ID;
  const MV = process.env.MAVERA_API_KEY;

  const gaql = `
    SELECT auction_insights.display_domain,
      metrics.auction_insight_search_impression_share,
      metrics.auction_insight_search_overlap_rate,
      metrics.auction_insight_search_outranking_share,
      metrics.auction_insight_search_position_above_rate,
      metrics.auction_insight_search_top_impression_percentage
    FROM auction_insights
    WHERE segments.date DURING LAST_30_DAYS`;

  const gaRes = await fetch(
    `https://googleads.googleapis.com/v23/customers/${CUSTOMER_ID}/googleAds:searchStream`,
    {
      method: "POST",
      headers: { Authorization: `Bearer ${ACCESS_TOKEN}`, "developer-token": DEV_TOKEN, "Content-Type": "application/json" },
      body: JSON.stringify({ query: gaql }),
    }
  ).then((r) => r.json());

  const competitors = {};
  for (const row of gaRes[0]?.results || []) {
    const domain = row.auctionInsights.displayDomain;
    if (!domain || domain === "Your domain") continue;
    competitors[domain] ??= { impressionShare: [], overlapRate: [], outrankingShare: [], posAboveRate: [], topImprPct: [] };
    const m = row.metrics;
    competitors[domain].impressionShare.push(parseFloat(m.auctionInsightSearchImpressionShare || "0"));
    competitors[domain].overlapRate.push(parseFloat(m.auctionInsightSearchOverlapRate || "0"));
    competitors[domain].outrankingShare.push(parseFloat(m.auctionInsightSearchOutrankingShare || "0"));
    competitors[domain].posAboveRate.push(parseFloat(m.auctionInsightSearchPositionAboveRate || "0"));
    competitors[domain].topImprPct.push(parseFloat(m.auctionInsightSearchTopImpressionPercentage || "0"));
  }

  const avg = (arr) => arr.length ? arr.reduce((s, v) => s + v, 0) / arr.length : 0;
  const compSummary = Object.entries(competitors)
    .map(([domain, m]) => ({
      domain, impressionShare: avg(m.impressionShare), overlapRate: avg(m.overlapRate),
      outrankingShare: avg(m.outrankingShare), posAboveRate: avg(m.posAboveRate), topImprPct: avg(m.topImprPct),
    }))
    .sort((a, b) => b.overlapRate - a.overlapRate)
    .slice(0, 5);

  for (const comp of compSummary) {
    const card = await fetch("https://app.mavera.io/api/v1/mave/chat", {
      method: "POST",
      headers: { Authorization: `Bearer ${MV}`, "Content-Type": "application/json" },
      body: JSON.stringify({
        message: `Generate a battle card for ${comp.domain}.\n\nAUCTION DATA:\n- Overlap: ${(comp.overlapRate * 100).toFixed(1)}%\n- They outrank us: ${(comp.outrankingShare * 100).toFixed(1)}%\n- Position above: ${(comp.posAboveRate * 100).toFixed(1)}%\n\nProduce: 1) Overview 2) Strengths 3) Weaknesses 4) Pricing 5) Objections 6) Killer questions 7) Landmines 8) Switch reasons 9) Ad copy adjustments`,
      }),
    }).then((r) => r.json());

    console.log(`\n${"=".repeat(60)}`);
    console.log(`BATTLE CARD: ${comp.domain} | Overlap: ${(comp.overlapRate * 100).toFixed(1)}%`);
    console.log(`${"=".repeat(60)}`);
    console.log((card.content || "").slice(0, 1200));
    console.log(`Sources: ${(card.sources || []).length}`);
    await new Promise((r) => setTimeout(r, 1000));
  }
  ```
</CodeGroup>

### Example Output

```text theme={"dark"}
Top 5 competitors by auction overlap:

  competitorx.com: overlap 78.2%, outranking 34.1%, pos above 28.5%
  rivaltool.io: overlap 65.4%, outranking 42.3%, pos above 38.1%
  alternativeapp.com: overlap 51.8%, outranking 22.7%, pos above 18.3%

============================================================
BATTLE CARD: competitorx.com
Overlap: 78.2% | They outrank us: 34.1%
============================================================

### Overview
CompetitorX — Series C ($65M raised), 300 employees. Positioning as an
"all-in-one revenue platform." Strong SMB traction, expanding into mid-market.

### Strengths
- Lower entry price ($79/seat vs our $149/seat)
- Faster self-serve onboarding (claim: 5 minutes to first value)
- Strong G2 presence (4.6 stars, 1,200+ reviews)

### Weaknesses
- No SSO/SCIM below Enterprise tier
- Reporting limited to pre-built dashboards (no custom SQL/API export)
- No SOC 2 Type II — only Type I
- Customer support: community forum only below $25K ACV

### Pricing
Starter: $79/seat/mo | Pro: $149/seat/mo | Enterprise: custom
No monthly option — annual only.

### Killer Questions
- "How does your team handle SSO requirements for compliance?"
- "Do you need to export data to your existing BI tools?"
- "What does your security review process look like?"

### Ad Copy Adjustments
When competing in the same auction:
- Lead with "SOC 2 Type II Certified" in headline
- Add "Free Trial — No Annual Lock-In" to differentiate
- Use sitelink: "See Our Security Certifications"

Sources: 5
```

### Error Handling

<AccordionGroup>
  <Accordion title="Auction insights require Search campaigns">Display and Video campaigns don't populate `auction_insights`. The report only covers Search and Shopping campaigns.</Accordion>
  <Accordion title="Domain-level aggregation">Auction insights report at the domain level, not per-ad. A competitor with multiple products under one domain shows as a single entry.</Accordion>
  <Accordion title="Mave rate limiting on batch requests">Generating 5 battle cards sequentially takes 30–60s. The code includes 1s delays. For 10+ competitors, parallelize with `asyncio.gather` (Python) or `Promise.all` (JS) with a concurrency limit.</Accordion>
</AccordionGroup>

***

<CardGroup cols={2}>
  <Card title="All Google Ads jobs" icon="rectangle-history" href="/integrations/google-ads">
    View all 7 Google Ads integration jobs
  </Card>

  <Card title="Mave Agent" icon="brain" href="/api-reference/mave">
    Full reference for POST /api/v1/mave/chat
  </Card>
</CardGroup>
