Workflow

GEO/AEO Metric Daily Report Workflow

Daily workflow that tracks AI Overview citations and generative engine optimization metrics for brand monitoring and competitive analysis.

Overview

Automated daily reporting on Generative Engine Optimization metrics. Track which keywords trigger AI Overviews, whether your brand is cited, and how competitor citation share changes over time.

Trigger

Daily cron at 07:00 UTC

Schedule

Daily at 07:00 UTC

Workflow Steps

1

Load keyword portfolio

Read target keywords grouped by category (brand, category, competitor). Each keyword has a target brand name to track citations for.

2

Query with AI Overview extraction

Search Google via Scavio with ai_overview enabled for each keyword. Extract the full AI Overview text and citation list.

3

Parse brand citations

Check AI Overview text for brand mentions and citation URLs. Track own brand, competitor brands, and new entrants.

4

Calculate share-of-voice

For each keyword category, calculate what percentage of AI Overviews cite the target brand vs competitors. Track daily deltas.

5

Generate and send report

Compile daily GEO/AEO report with citation counts, share-of-voice by category, and alerts for citation gains/losses. Send via email or Slack.

Python Implementation

Python
import requests, os, json
from datetime import date
from collections import defaultdict

H = {'x-api-key': os.environ['SCAVIO_API_KEY']}

def check_aeo_citation(keyword, brands):
    r = requests.post('https://api.scavio.dev/api/v1/search', headers=H,
        json={'platform': 'google', 'query': keyword, 'ai_overview': True},
        timeout=10).json()
    aio = r.get('ai_overview', {}) or {}
    aio_text = (aio.get('text', '') or '').lower()
    citations = aio.get('citations', [])
    brand_citations = {}
    for brand in brands:
        cited_in_text = brand.lower() in aio_text
        cited_in_links = any(brand.lower() in (c.get('domain', '') or '').lower() for c in citations)
        brand_citations[brand] = cited_in_text or cited_in_links
    return {
        'keyword': keyword,
        'has_aio': bool(r.get('ai_overview')),
        'brand_citations': brand_citations,
        'citation_count': len(citations),
    }

brands = ['OurBrand', 'CompetitorA', 'CompetitorB']
keywords = ['best crm software 2026', 'crm for startups', 'crm comparison 2026']
report = defaultdict(lambda: {'cited': 0, 'total': 0})

for kw in keywords:
    result = check_aeo_citation(kw, brands)
    if result['has_aio']:
        for brand, cited in result['brand_citations'].items():
            report[brand]['total'] += 1
            if cited:
                report[brand]['cited'] += 1
        status = ', '.join(b for b, c in result['brand_citations'].items() if c) or 'none'
        print(f"{kw}: {status}")

print(f"\n--- Share of Voice ({date.today()}) ---")
for brand, data in report.items():
    sov = data['cited'] / data['total'] * 100 if data['total'] > 0 else 0
    print(f"  {brand}: {sov:.0f}% ({data['cited']}/{data['total']})")

JavaScript Implementation

JavaScript
const H = {"x-api-key": process.env.SCAVIO_API_KEY, "Content-Type": "application/json"};

async function checkAeoCitation(keyword, brands) {
  const r = await fetch("https://api.scavio.dev/api/v1/search", {
    method: "POST", headers: H,
    body: JSON.stringify({platform: "google", query: keyword, ai_overview: true})
  }).then(r => r.json());
  const aio = r.ai_overview || {};
  const text = (aio.text || "").toLowerCase();
  const citations = aio.citations || [];
  const brandCitations = {};
  for (const brand of brands) {
    const inText = text.includes(brand.toLowerCase());
    const inLinks = citations.some(c => (c.domain || "").toLowerCase().includes(brand.toLowerCase()));
    brandCitations[brand] = inText || inLinks;
  }
  return {keyword, hasAio: Boolean(r.ai_overview), brandCitations, citationCount: citations.length};
}

(async () => {
  const brands = ["OurBrand", "CompetitorA", "CompetitorB"];
  const keywords = ["best crm software 2026", "crm for startups", "crm comparison 2026"];
  const report = {};
  brands.forEach(b => report[b] = {cited: 0, total: 0});

  for (const kw of keywords) {
    const result = await checkAeoCitation(kw, brands);
    if (result.hasAio) {
      for (const [brand, cited] of Object.entries(result.brandCitations)) {
        report[brand].total++;
        if (cited) report[brand].cited++;
      }
      const cited = Object.entries(result.brandCitations).filter(([,v]) => v).map(([k]) => k).join(", ") || "none";
      console.log(`${kw}: ${cited}`);
    }
  }
  console.log("\n--- Share of Voice ---");
  for (const [brand, data] of Object.entries(report)) {
    const sov = data.total > 0 ? (data.cited / data.total * 100).toFixed(0) : 0;
    console.log(`  ${brand}: ${sov}% (${data.cited}/${data.total})`);
  }
})();

Platforms Used

Google

Web search with knowledge graph, PAA, and AI overviews

Frequently Asked Questions

Automated daily reporting on Generative Engine Optimization metrics. Track which keywords trigger AI Overviews, whether your brand is cited, and how competitor citation share changes over time.

This workflow uses a daily cron at 07:00 utc. Daily at 07:00 UTC.

This workflow uses the following Scavio platforms: google. Each platform is called via the same unified API endpoint.

Yes. Scavio's free tier includes 250 credits per month with no credit card required. That is enough to test and validate this workflow before scaling it.

GEO/AEO Metric Daily Report Workflow

Daily workflow that tracks AI Overview citations and generative engine optimization metrics for brand monitoring and competitive analysis.