Les Google AI Overviews apparaissent désormais sur plus de 40% des requêtes informationnelles et citent des marques spécifiques. Si vos concurrents sont cités et que vous ne l'êtes pas, vous perdez du trafic que vous ne pouvez pas voir dans les outils SEO traditionnels. Ce tracker vérifie quotidiennement vos mots-clés cibles, enregistre le statut des citations et alerte lorsque des concurrents gagnent ou perdent des citations.
Prérequis
- Python 3.8+
- bibliothèque requests
- Une clé API Scavio depuis scavio.dev
- Mots-clés cibles et domaine à surveiller
Parcours
Étape 1: Analyser les mots-clés pour les citations AI Overview
Vérifier chaque mot-clé pour la présence d'AI Overview et le statut de citation de la marque.
import os, requests, json
from datetime import datetime
API_KEY = os.environ['SCAVIO_API_KEY']
SH = {'x-api-key': API_KEY, 'Content-Type': 'application/json'}
DOMAIN = 'yourbrand.com'
COMPETITORS = ['competitor1.com', 'competitor2.com']
KEYWORDS = [
'best project management tool',
'project management software comparison',
'agile vs waterfall tools',
'remote team project management',
'project management for startups',
]
def scan_citations(keyword):
data = requests.post('https://api.scavio.dev/api/v1/search',
headers=SH, json={'query': keyword, 'country_code': 'us'}).json()
aio = data.get('ai_overview', data.get('answer_box', {}))
aio_text = json.dumps(aio).lower() if aio else ''
result = {
'keyword': keyword,
'has_aio': bool(aio),
'brand_cited': DOMAIN.lower() in aio_text,
'competitors_cited': {c: c.lower() in aio_text for c in COMPETITORS}
}
return result
results = []
for kw in KEYWORDS:
r = scan_citations(kw)
results.append(r)
brand = 'CITED' if r['brand_cited'] else 'absent'
comps = sum(1 for v in r['competitors_cited'].values() if v)
print(f' [{brand:6}] {kw:45} | competitors: {comps}/{len(COMPETITORS)}')
print(f'\nCost: ${len(KEYWORDS) * 0.005:.3f}')Étape 2: Calculer les métriques de citation et les écarts
Calculer votre part de citation par rapport aux concurrents et identifier les écarts.
def citation_report(results):
total = len(results)
with_aio = sum(1 for r in results if r['has_aio'])
brand_cited = sum(1 for r in results if r['brand_cited'])
print(f'\n=== AI Citation Report - {DOMAIN} ===')
print(f' Keywords: {total}')
print(f' AI Overviews present: {with_aio} ({with_aio/total*100:.0f}%)')
print(f' Your brand cited: {brand_cited} ({brand_cited/with_aio*100:.0f}% of AIO)' if with_aio else ' No AI Overviews found')
# Competitor comparison
print(f'\n Citation Share:')
comp_counts = {c: sum(1 for r in results if r['competitors_cited'].get(c)) for c in COMPETITORS}
all_brands = {DOMAIN: brand_cited, **comp_counts}
for brand, count in sorted(all_brands.items(), key=lambda x: x[1], reverse=True):
bar = '#' * count
print(f' {brand:25} | {count:2} citations | {bar}')
# Gaps: keywords where competitors are cited but you are not
gaps = [r for r in results if r['has_aio'] and not r['brand_cited'] and any(r['competitors_cited'].values())]
if gaps:
print(f'\n Citation Gaps ({len(gaps)} keywords where competitors beat you):')
for g in gaps:
cited_comps = [c for c, v in g['competitors_cited'].items() if v]
print(f' "{g["keyword"]}" -> cited: {", ".join(cited_comps)}')
citation_report(results)Étape 3: Stocker l'historique et détecter les changements
Enregistrer les résultats quotidiens et alerter en cas de changement de statut de citation.
def track_changes(results, history_file='citation_history.json'):
try:
with open(history_file) as f:
history = json.load(f)
except FileNotFoundError:
history = []
today = {
'date': datetime.now().strftime('%Y-%m-%d'),
'total': len(results),
'aio_count': sum(1 for r in results if r['has_aio']),
'cited': sum(1 for r in results if r['brand_cited']),
'keywords': {r['keyword']: r['brand_cited'] for r in results}
}
changes = []
if history:
prev = history[-1]
prev_kws = prev.get('keywords', {})
for kw, cited in today['keywords'].items():
if kw in prev_kws and prev_kws[kw] != cited:
change = 'GAINED' if cited else 'LOST'
changes.append(f'{change}: "{kw}"')
history.append(today)
with open(history_file, 'w') as f:
json.dump(history, f, indent=2)
print(f'\n=== Citation Changes ===')
if changes:
for c in changes:
print(f' {c}')
else:
print(f' No changes since last scan.')
print(f' History: {len(history)} scans saved')
track_changes(results)Exemple Python
import os, requests, json
SH = {'x-api-key': os.environ['SCAVIO_API_KEY'], 'Content-Type': 'application/json'}
def check_cited(keyword, domain):
data = requests.post('https://api.scavio.dev/api/v1/search',
headers=SH, json={'query': keyword, 'country_code': 'us'}).json()
aio = data.get('ai_overview', {})
cited = domain.lower() in json.dumps(aio).lower() if aio else False
print(f'{"CITED" if cited else "absent":6} | {keyword}')
for kw in ['best search api', 'serp api comparison']:
check_cited(kw, 'scavio.dev')
print('Cost: $0.010')Exemple JavaScript
const SH = { 'x-api-key': process.env.SCAVIO_API_KEY, 'Content-Type': 'application/json' };
async function checkCited(keyword, domain) {
const data = await fetch('https://api.scavio.dev/api/v1/search', {
method: 'POST', headers: SH,
body: JSON.stringify({ query: keyword, country_code: 'us' })
}).then(r => r.json());
const aio = data.ai_overview || {};
const cited = JSON.stringify(aio).toLowerCase().includes(domain);
console.log(`${cited ? 'CITED' : 'absent'} | ${keyword}`);
}
await checkCited('best search api', 'scavio.dev');Sortie attendue
[CITED ] best project management tool | competitors: 1/2
[absent] project management software comparison | competitors: 2/2
[CITED ] agile vs waterfall tools | competitors: 0/2
[absent] remote team project management | competitors: 1/2
[absent] project management for startups | competitors: 0/2
Cost: $0.025
=== AI Citation Report - yourbrand.com ===
Keywords: 5
AI Overviews present: 4 (80%)
Your brand cited: 2 (50% of AIO)
Citation Gaps (1 keywords where competitors beat you):
"project management software comparison" -> cited: competitor1.com, competitor2.com