Мониторинг видимости в нейросетях

Как отслеживать, попадает ли ваш контент в ответы AI-поисковиков: инструменты, ручное тестирование, метрики видимости.

Вы оптимизировали контент для AI-поисковиков — но как узнать, работает ли это? В классическом SEO всё просто: позиция в Google, клики из Search Console, трафик из Яндекс.Метрики. Для AI-поиска таких готовых инструментов пока мало. Но способы отследить видимость есть — от ручного тестирования до API-мониторинга.

Представьте, что вы выступили на конференции, но не знаете, заметил ли кто-то ваше выступление. Мониторинг видимости — это способ узнать, «слышат» ли AI-поисковики ваш контент и используют ли его в своих ответах.

Суть в двух словах

Мониторинг AI-видимости отвечает на три вопроса:

  1. Цитирует ли AI ваш сайт? — попадает ли ваш домен в ответы Perplexity, ChatGPT, YandexGPT
  2. По каким запросам? — на какие вопросы AI ссылается на вас
  3. Как часто? — растёт ли видимость со временем

Способы мониторинга:

  • Ручной — задаёте вопросы в AI-поисковиках и проверяете ссылки
  • API — автоматизируете проверку через Perplexity API
  • Специализированные инструменты — Otterly.AI, Nightwatch и аналоги
  • Лог-анализ — отслеживаете визиты AI-краулеров в серверных логах
ПромптPerplexity
Лучшие инструменты для мониторинга AI-видимости сайта
Ответ модели

Для мониторинга видимости контента в AI-поисковиках используют:

  1. Otterly.AI — отслеживает цитирования в ChatGPT, Perplexity, Google AI Overviews. Показывает позицию вашего домена среди источников [1].
  2. Perplexity API — позволяет автоматизировать проверку цитирований программно [2].
  3. Manual testing — регулярное тестирование запросов в AI-поисковиках.
  4. Server log analysis — анализ запросов от GPTBot, PerplexityBot, ClaudeBot [3].

[1] otterly.ai [2] docs.perplexity.ai [3] cloudflare.com/radar

ПромптChatGPT
Как проверить, цитирует ли ChatGPT мой сайт? Домен — example.com, тема — промптинг.
Ответ модели

Пошаговый способ проверки:

  1. Откройте ChatGPT и включите поиск (иконка глобуса)
  2. Задайте 10-15 вопросов по вашей теме: «что такое chain of thought», «лучшие техники промптинга 2026»
  3. Проверьте, появляется ли example.com в источниках ответа
  4. Зафиксируйте: запрос, наличие цитирования, позицию среди источников
  5. Повторяйте раз в неделю для отслеживания динамики

Автоматизация: используйте OpenAI API с параметром web_search для программной проверки.

Почему стандартные SEO-инструменты не работают

Google Search Console показывает позиции в обычной выдаче, но не в AI Overviews. Яндекс.Вебмастер не отображает цитирования в YandexGPT. У Perplexity и ChatGPT нет аналога Search Console.

Доступность аналитики по AI-платформам
Google Search Console (обычный поиск)95%
Google (AI Overviews — данные частичные)30%
Perplexity (данные через API)45%
ChatGPT (нет аналитики для паблишеров)10%
YandexGPT (данные частичные)20%

Метод 1: Ручное тестирование

Самый простой и бесплатный способ. Подходит для начала.

Используйте режим инкогнито при ручном тестировании. AI-поисковики могут персонализировать ответы на основе истории. Инкогнито даёт более объективные результаты.

Метод 2: Анализ серверных логов

AI-краулеры оставляют следы в логах вашего веб-сервера. Это косвенный, но полезный сигнал.

Какие боты искать

User-AgentПлатформа
GPTBotOpenAI (ChatGPT)
ChatGPT-UserChatGPT при поиске в реальном времени
PerplexityBotPerplexity AI
ClaudeBotAnthropic (Claude)
Google-ExtendedGoogle AI
Applebot-ExtendedApple AI
cohere-aiCohere

Если бот заходит на вашу страницу — значит, AI-система знает о ней. Это не гарантирует цитирование, но без индексации цитирование невозможно.

Метод 3: API-мониторинг через Perplexity

Perplexity API — единственное API, которое возвращает список цитирований (citations) в ответе. Это делает его основным инструментом для автоматизации.

Плюсы

  • Автоматическая проверка сотен запросов
  • Perplexity возвращает полный список citations
  • Можно настроить ежедневный мониторинг
  • Легко интегрировать в дашборд или CI

Минусы

  • Платный API (оплата за запрос)
  • Покрывает только Perplexity, не ChatGPT/Google
  • Ответы могут различаться от запроса к запросу
  • Нет исторических данных — нужно собирать самостоятельно

Метод 4: Специализированные инструменты

Otterly.AI

Отслеживает видимость в ChatGPT, Perplexity, Google AI Overviews. Показывает, по каким запросам вы цитируетесь, и позицию среди источников. Платный, от $49/мес.

Nightwatch

SEO-инструмент, который добавил отслеживание AI Overviews. Показывает, попадает ли ваш домен в AI-ответы Google.

Semrush / Ahrefs

Крупные SEO-платформы начали добавлять метрики AI-видимости, но пока в бета-режиме.

Ключевые метрики AI-видимости

Метрики AI-видимости и их значение
Citation Rate (доля запросов с цитированием)100%
Citation Position (средняя позиция среди источников)85%
AI Traffic (переходы из AI-поисковиков)90%
Crawl Frequency (частота визитов AI-ботов)60%
Query Coverage (% целевых запросов покрыто)95%

Citation Rate

Формула: процитированных запросов / всего проверенных запросов * 100%

Целевые значения:

  • < 10% — контент не оптимизирован для AI
  • 10-30% — базовый уровень, есть потенциал роста
  • 30-50% — хорошая AI-видимость
  • > 50% — отличный результат

AI Traffic

Отслеживайте переходы из AI-поисковиков через UTM-метки или реферер-анализ:

  • perplexity.ai — трафик из Perplexity
  • chatgpt.com — трафик из ChatGPT
  • google.com (с пометкой AI) — пока сложно отделить от обычного Google
Без техники
Единственная метрика — позиция в Google. Нет данных о AI-видимости. Решения принимаются вслепую.
С техникой
Дашборд с метриками: Citation Rate 34%, AI Traffic 1200 визитов/мес, Crawl Frequency 500 запросов/день. Понятно, что работает и что улучшать.
AI-ответы нестабильны: один и тот же запрос может давать разные ответы с разными источниками. Не паникуйте, если в одной проверке вас процитировали, а в следующей — нет. Отслеживайте тренды за недели и месяцы, а не отдельные проверки.

Техническая реализация мониторинга

Автоматический мониторинг через Perplexity API

import httpx
import asyncio
import json
from datetime import datetime
from dataclasses import dataclass, asdict

@dataclass
class CitationCheck:
    query: str
    timestamp: str
    cited: bool
    position: int | None
    total_sources: int
    all_citations: list[str]

async def check_citation(
    query: str,
    domain: str,
    api_key: str,
) -> CitationCheck:
    """Проверяет цитирование домена в ответе Perplexity."""
    async with httpx.AsyncClient() as client:
        resp = await client.post(
            "https://api.perplexity.ai/chat/completions",
            headers={
                "Authorization": f"Bearer {api_key}",
                "Content-Type": "application/json",
            },
            json={
                "model": "sonar",
                "messages": [
                    {"role": "user", "content": query}
                ],
            },
            timeout=30,
        )

    data = resp.json()
    citations = data.get("citations", [])

    position = None
    for i, url in enumerate(citations):
        if domain in url:
            position = i
            break

    return CitationCheck(
        query=query,
        timestamp=datetime.now().isoformat(),
        cited=position is not None,
        position=position,
        total_sources=len(citations),
        all_citations=citations,
    )

async def run_monitoring(
    queries: list[str],
    domain: str,
    api_key: str,
    output_file: str = "citations.jsonl",
):
    """Запускает мониторинг для списка запросов."""
    tasks = [
        check_citation(q, domain, api_key)
        for q in queries
    ]
    results = await asyncio.gather(*tasks)

    # Сохраняем в JSONL
    with open(output_file, "a") as f:
        for r in results:
            f.write(json.dumps(asdict(r), ensure_ascii=False) + "\n")

    # Статистика
    cited = sum(1 for r in results if r.cited)
    rate = cited / len(results) * 100

    print(f"Citation Rate: {rate:.1f}% ({cited}/{len(results)})")

    for r in results:
        status = f"[pos {r.position}]" if r.cited else "[---]"
        print(f"  {status} {r.query}")

    return results

queries = [
    "что такое GEO оптимизация",
    "как оптимизировать контент для AI поисковиков",
    "schema.org для нейросетей",
    "E-E-A-T для AI поиска",
    "perplexity оптимизация контента",
]

asyncio.run(
    run_monitoring(queries, "example.com", "pplx-xxx")
)

Анализ AI-краулеров в Nginx-логах

import re
from collections import Counter, defaultdict
from datetime import datetime

AI_BOT_PATTERNS = {
    "GPTBot": r"GPTBot",
    "ChatGPT-User": r"ChatGPT-User",
    "PerplexityBot": r"PerplexityBot",
    "ClaudeBot": r"ClaudeBot",
    "Google-Extended": r"Google-Extended",
    "Applebot-Extended": r"Applebot-Extended",
    "Bytespider": r"Bytespider",
    "cohere-ai": r"cohere-ai",
}

LOG_PATTERN = re.compile(
    r'(?P<ip>\S+) \S+ \S+ \[(?P<time>[^\]]+)\] '
    r'"(?P<method>\S+) (?P<path>\S+) \S+" '
    r'(?P<status>\d+) (?P<size>\d+) '
    r'"(?P<referer>[^"]*)" "(?P<ua>[^"]*)"'
)

def analyze_ai_traffic(log_path: str) -> dict:
    """Анализирует AI-бот трафик из Nginx-логов."""
    bot_pages = defaultdict(Counter)  # bot -> {page: count}
    bot_daily = defaultdict(Counter)  # bot -> {date: count}

    with open(log_path) as f:
        for line in f:
            match = LOG_PATTERN.match(line)
            if not match:
                continue

            ua = match.group("ua")
            path = match.group("path")
            status = match.group("status")

            # Только успешные запросы
            if not status.startswith("2"):
                continue

            for bot_name, pattern in AI_BOT_PATTERNS.items():
                if re.search(pattern, ua, re.IGNORECASE):
                    bot_pages[bot_name][path] += 1

                    # Парсим дату
                    time_str = match.group("time")
                    date = datetime.strptime(
                        time_str.split(":")[0], "%d/%b/%Y"
                    ).strftime("%Y-%m-%d")
                    bot_daily[bot_name][date] += 1
                    break

    return {
        "pages_by_bot": {
            bot: dict(pages.most_common(20))
            for bot, pages in bot_pages.items()
        },
        "daily_by_bot": {
            bot: dict(sorted(daily.items()))
            for bot, daily in bot_daily.items()
        },
        "total_by_bot": {
            bot: sum(pages.values())
            for bot, pages in bot_pages.items()
        },
    }

stats = analyze_ai_traffic("/var/log/nginx/access.log")

print("=== AI Bot Traffic ===")
for bot, total in sorted(
    stats["total_by_bot"].items(), key=lambda x: -x[1]
):
    print(f"{bot}: {total} запросов")
    top_pages = stats["pages_by_bot"][bot]
    for page, count in list(top_pages.items())[:5]:
        print(f"  {page}: {count}")

Дашборд мониторинга (Nuxt server route)

// server/api/geo/visibility.get.ts
import { defineEventHandler, getQuery } from 'h3'

interface VisibilityData {
  date: string
  citationRate: number
  aiTraffic: number
  crawlFrequency: number
  topQueries: { query: string; cited: boolean }[]
}

export default defineEventHandler(async (event) => {
  const query = getQuery(event)
  const days = Number(query.days) || 30

  // В реальном проекте данные берутся из БД
  // Здесь — пример структуры ответа

  const data: VisibilityData = {
    date: new Date().toISOString(),
    citationRate: 34.5,
    aiTraffic: 1247,
    crawlFrequency: 523,
    topQueries: [
      { query: 'что такое GEO', cited: true },
      { query: 'оптимизация для AI поисковиков', cited: true },
      { query: 'schema.org для AI', cited: false },
      { query: 'E-E-A-T нейропоиск', cited: true },
    ],
  }

  return data
})

Cron-задача для регулярного мониторинга


import asyncio
import json
from datetime import datetime
from pathlib import Path

from monitor import run_monitoring

DOMAIN = "example.com"
API_KEY = "pplx-xxx"  # Из переменных окружения
OUTPUT_DIR = Path("/opt/geo-monitor/data")

QUERIES = [
    "что такое GEO оптимизация",
    "как AI поисковики выбирают источники",
    "schema.org для нейросетей",
    "E-E-A-T для AI поиска",
    "мониторинг видимости в AI",
    "оптимизация для perplexity",
    "chatgpt search оптимизация",
    "GEO кейсы до после",
]

async def main():
    today = datetime.now().strftime("%Y-%m-%d")
    output_file = OUTPUT_DIR / f"citations-{today}.jsonl"

    results = await run_monitoring(
        QUERIES, DOMAIN, API_KEY, str(output_file)
    )

    # Суммарный отчёт
    cited = sum(1 for r in results if r.cited)
    report = {
        "date": today,
        "citation_rate": cited / len(results) * 100,
        "cited_count": cited,
        "total_queries": len(results),
    }

    report_file = OUTPUT_DIR / "daily-reports.jsonl"
    with open(report_file, "a") as f:
        f.write(json.dumps(report) + "\n")

asyncio.run(main())
Не запускайте мониторинг слишком часто. Perplexity API стоит денег, а результаты меняются незначительно в пределах дня. Оптимальная частота — раз в день для ключевых запросов, раз в неделю для расширенного списка.
Стоимость мониторинга AI-видимости (примерная, за месяц)
Ручное тестирование (30 мин/нед)0%
Perplexity API (100 запр/день)15%
Otterly.AI (базовый)49%
Nightwatch + AI Overviews79%
Custom решение (разработка)30%

Проверьте себя

Проверьте себя

1. Какой AI-поисковик через API возвращает список цитирований (citations) в ответе?

2. Что такое Citation Rate?

3. Почему одного ручного тестирования недостаточно для мониторинга AI-видимости?