
С середины лета я раз в несколько недель задаю нейросетям с веб-поиском одни и те же вопросы про франшизы и производство одежды и записываю, на какие страницы они ссылаются. Вопросы такие, какие задаёт человек перед покупкой: «за сколько окупается франшиза производства мерча», «как проверить франшизу, чтобы не нарваться на развод», «какой DTF-принтер выбрать для старта». Параллельно все эти месяцы я писал статьи о нашем производстве на открытые площадки, где публикуются сторонние авторы, и вёл блог компании.
На постоянной выборке из 61 вопроса, в которых наша компания не названа, доля ответов, где процитирована хотя бы одна наша страница, выросла за три месяца с 3 до 51 %. Сейчас это называют GEO-оптимизацией, то есть работой на то, чтобы попадать в ответы генеративного поиска, и я хотел проверить, работает ли она вообще, на своих данных. Ниже код замера, таблицы из прогона 13 ноября 2026 года и четыре места, где замер врёт или врал раньше. Без них эти 51 % ничего не стоят.
Что именно я спрашиваю и у кого
Скрипт берёт список вопросов и по очереди отправляет каждый в несколько поверхностей. Под «поверхностью» я понимаю конкретную модель с конкретным поиском, а не продукт целиком: потребительские приложения ChatGPT или Алисы ведут себя иначе, у них своя память и свои системные промпты, и опросить их через API нельзя.
Поверхность
Как вызывается
С какого числа в замере
Claude
Anthropic API, встроенный инструмент web_search
19.07
«ChatGPT»
gpt-4o-mini через шлюз OpenRouter, плагин web
15.08
«Gemini»
gemini-2.5-flash через тот же шлюз и плагин
15.08
Perplexity
sonar-pro через шлюз
15.08
Генеративный поиск Яндекса
Yandex Cloud, Search API, метод gen/search
15.08
GigaChat
собственный API, ссылок не отдаёт вообще
05.10
Кавычки у ChatGPT и Gemini стоят не просто так, к ним я вернусь в разделе про ошибки.
Вызов через шлюз выглядит так:
resp = await http.post( "https://openrouter.ai/api/v1/chat/completions", headers={"Authorization": f"Bearer {key}"}, json={ "model": model, "messages": [{"role": "user", "content": prompt}], "plugins": [{"id": "web", "max_results": 5}], "max_tokens": MAX_TOKENS.get(surface, 1200), }, timeout=60.0,)message = resp.json()["choices"][0]["message"]cited = [a["url_citation"]["url"] for a in message.get("annotations") or [] if a.get("type") == "url_citation"]
Лимит токенов у каждой поверхности свой. Рассуждающая модель тратит его на размышление ещё до ответа, и при общем лимите в 1200 токенов gemini-2.5-flash иногда возвращала пустой текст без единой аннотации. В базе такой ответ выглядел как «нас не нашли», хотя ответа не было вообще.
Каждое наблюдение получает одну из шести меток. Порядок проверок важен: если в ответе есть и каталог франшиз, и живой конкурент, побеждает конкурент.
def classify(text: str, urls: list[str]) -> str: domains = {domain(u) for u in urls} if domains & OUR_DOMAINS: return "cited" # наша страница среди источников if "наше название" in text.lower(): return "mentioned" # названы текстом, но без ссылки if domains & COMPETITOR_DOMAINS: return "competitor_only" if domains & CATALOG_DOMAINS: return "aggregator_only" # запрос держит каталог франшиз return "not_observed"
За 20 дней замеров с 19 июля по 11 ноября накопилось 3 129 наблюдений по 92 вопросам. Без ошибок и без GigaChat, у которого нечего считать, остаётся 2 649 ответов с 21 693 ссылками на 1 849 доменов.
Почему смотреть надо на 61 вопрос, а не на все 92
Простой подсчёт по месяцам даёт красивую лестницу: в июле наших страниц в ответах ноль, в ноябре больше половины. Верить ей нельзя по двум причинам. Во-первых, 8 вопросов из 92 содержат название компании («отзывы о франшизе такой-то»), и по ним цитирование собственного сайта ничего не доказывает. Во-вторых, набор вопросов менялся: одни я добавлял, другие переписывал, и в июле замер вообще шёл через одну поверхность.
Поэтому я оставил только то, что было во всех замерах одновременно: четыре поверхности, у которых ряд полный (ChatGPT, Gemini, Perplexity, Яндекс), и шесть дат, когда работали все четыре. Вопросом панели становится только тот, у которого есть ответ от каждой поверхности на каждую дату.
SURF = ["chatgpt", "gemini", "perplexity", "yandex_alice"]DATES = ["2026-08-17", "2026-09-02", "2026-09-08", "2026-10-05", "2026-10-29", "2026-11-11"]have = defaultdict(set)for surface, label, urls, day, prompt in rows: if surface in SURF and day in DATES and not is_branded(prompt): have[prompt].add((surface, day))panel = {p for p, cells in have.items() if len(cells) == len(SURF) * len(DATES)}# len(panel) == 61, на каждую дату ровно 244 ответа
Наша страница здесь бывает двух видов: статья, которую я опубликовал на сторонней площадке (сверка по точному адресу с таблицей публикаций), и сайт или блог компании (сверка по домену).
Дата замера
Наша статья на площадке
Наш сайт или блог
Хоть что-то наше
Доля каталогов среди доменов
17.08
3 %
0 %
3 %
20 %
02.09
20 %
16 %
32 %
19 %
08.09
20 %
13 %
29 %
17 %
05.10
25 %
8 %
31 %
16 %
29.10
26 %
39 %
48 %
14 %
11.11
30 %
38 %
51 %
14 %
Если разложить по поверхностям первый и последний замер, картина неравномерная. У ChatGPT было 0 ответов из 61 с нашей страницей, стало 37. У Gemini было 0, стало 36, у Perplexity 6 и 37. Яндекс сдвинулся слабее всех: с 2 до 14.
Две вещи в этой таблице меня удивили. Статьи на площадках подтягивались в ответы ровно, по несколько процентных пунктов в месяц, а блог стоял почти на нуле до октября и за три недели между 5 и 29 октября прыгнул с 8 до 39 %. Чаще всего в ответы попадают две его статьи: про то, как открыть цех брендирования, и про то, что на самом деле покупаешь в франшизе печати. Почему именно в эти три недели, я не знаю, и гадать не буду.
Вторая вещь касается того, какие площадки работают. Всего за четыре месяца в ответах встретилось 2 857 адресов с площадок, где публикуются сторонние авторы, и 666 из них оказались моими статьями, причём распределены они очень неровно. На spark.ru из 318 цитирований 262 приходятся на наши тексты: по этим вопросам нейросети фактически цитируют на этой площадке только нас. Дальше идут news.pressfeed.ru (118), sostav.ru (95), tenchat.ru и hf.ru (по 56). С Хабра за всё время процитировано 8 наших адресов.
Кого нейросети цитируют, когда нас там нет
Рост нашей доли не означает, что ответы стали однообразными. Источники в этой нише сильно размазаны: 1 849 доменов на 2 649 ответов, десять самых частых собирают меньше четверти всех появлений (23,5 %), а 727 доменов встретились ровно один раз.
Домен
В какой доле ответов
topfranchise.ru
25,4 %
businessmens.ru
22,3 %
hf.ru
21,1 %
sostav.ru
15,3 %
franshiza.ru
14,5 %
spark.ru
12,0 %
beboss.ru
11,2 %
vc.ru
10,6 %
Каталоги франшиз в начале лета были главным источником, и формально они им остались: два первых места по-прежнему за ними. Но их доля среди всех процитированных доменов по месяцам шла вниз ровной линией: 26 % в июле, 19 % в августе, 16 %, 12 % и 9 % в ноябре. Я ожидал, что освободившееся место займут площадки со сторонними авторами вообще, но это не так. Их доля среди доменов выросла с 8 % в июле до 14 % в ноябре, а если убрать из подсчёта мои статьи, получится 8 % в июле и 7 % в ноябре. Весь прирост дали мои тексты, чужие на тех же площадках цитируются не чаще, чем летом.
Поверхности сильно различаются по аппетиту к источникам. Perplexity приводит в среднем 18,9 ссылки на 14,9 домена в одном ответе, Яндекс обходится 3,3 ссылки, Claude даёт 8,8 ссылки, но всего 5,4 уникальных: одна и та же страница приходит в нескольких цитатах, привязанных к разным кускам ответа. Для замера это важно: если считать «ссылки», а не «уникальные адреса», у Claude получится вдвое больше источников, чем есть на самом деле.
Четыре места, где замер врёт или врал раньше
«ChatGPT» и «Gemini» здесь одна и та же поверхность
Первое, что бросилось в глаза при сравнении: у gpt-4o-mini и gemini-2.5-flash ровно по 5,0 ссылки в каждом ответе. Не в среднем, а в каждом из 1 090 ответов. Мера Жаккара по двадцати самым частым доменам у этой пары 0,90 (19 общих из 20), тогда как у любой другой пары поверхностей от 0,18 до 0,67.
Документация шлюза говорит, что плагин web использует родной поиск провайдера, если модель его поддерживает, а иначе отдаёт запрос внешнему поисковику Exa, и по умолчанию берёт 5 результатов. Пять результатов я сам и прописал в max_results. Данные показывают, что родной поиск ни у одной из этих двух моделей не включился: обе получали одни и те же пять страниц от одного поисковика и только писали поверх них разный текст. Комментарий в моём же коде утверждает обратное: «каждая через свой живой веб-поиск».
Значит, рост с 0 до 37 у ChatGPT и с 0 до 36 у Gemini это один результат, посчитанный дважды. Честнее говорить о трёх независимых источниках ссылок, а не о четырёх: поиск плагина, Perplexity и Яндекс. Вывод о росте от этого не исчезает, потому что Perplexity со своим поиском показал то же движение (с 6 до 37), но вес у него теперь другой.
Проверить это у себя можно за минуту:
from collections import Counterfor s in ("chatgpt", "gemini", "perplexity"): n = Counter(len(json.loads(u)) for surf, u in rows if surf == s) print(s, n.most_common(3))# chatgpt [(5, 593)]# gemini [(5, 497)]# perplexity [(15, 79), (14, 65), (24, 56)]
Если распределение схлопнулось в одно число, равное вашему max_results, родного поиска у модели нет.
Ряд, который обрывается молча
Claude был первой поверхностью замера и единственной с июля, поэтому на него я рассчитывал больше всего. В итоге у него 213 ошибок из 718 наблюдений, и все пришлись на три даты. 31 августа ключ API перестал проходить проверку (401), а с 29 октября доступ к API закрыт совсем. Каждый раз скрипт честно писал строку с меткой error и шёл дальше, ни разу не остановившись. Если считать долю от всех строк, а не от успешных ответов, Claude в эти даты выглядит как поверхность, которая внезапно перестала нас цитировать, хотя он просто не ответил.
С Perplexity и Gemini 24 августа случилось то же самое по другой причине: на счёте шлюза кончились деньги, и примерно половина вопросов получила 402 Payment Required. Поэтому 24 августа нет в панели.
Все доли в этой статье посчитаны только от ответов без ошибок, а Claude из панели исключён целиком: у него нет ни одного полного ряда после августа.
Один замер ничего не значит
Я сравнил каждую пару соседних замеров для одного и того же вопроса и одной поверхности. Набор процитированных доменов совпадает по мере Жаккара в среднем на 0,34-0,44 в зависимости от поверхности. Проще говоря, от замера к замеру больше половины источников меняется. Метка («процитированы», «только каталог», «ничего») сменилась в 16 % пар у Claude, в 25 % у Perplexity и в 33 % у Gemini.
Отсюда практическое правило: разница в десять процентных пунктов между двумя соседними датами лежит в пределах шума. Рост с 3 до 51 % за шесть замеров шумом быть не может, а скачок с 29 до 31 % между 8 сентября и 5 октября может.
Корреляция, а не эксперимент
К 17 августа у меня было 95 опубликованных статей на сторонних площадках, к 11 ноября 312. Блог за то же время тоже вырос. Контрольной группы нет: я не держал половину вопросов «без статей», чтобы сравнить. Поэтому из таблицы следует только то, что одновременно с ростом числа текстов выросла их доля в ответах, а не то, что одно вызвало другое. Убедительнее всего здесь выглядит spark.ru: на вопросы, под которые я туда писал, нейросети стали ссылаться именно на эти статьи. Но и это совпадение по теме, а не доказательство.
Есть и встречное соображение. Вопросы для замера и статьи для площадок составлялись в одном проекте, одними людьми. Даже если стараться не подгонять одно под другое, лексика у них общая, и поисковику проще сопоставить вопрос с текстом того же автора. Насколько этот эффект большой, я измерить не могу.
Чего я не учёл
Я не проверял, что ответ говорит со ссылкой на нашу страницу. Цитата бывает и в абзаце «будьте осторожны с такими предложениями». Метка cited фиксирует только факт ссылки.
Местоположение не задавалось нигде, кроме Яндекса, где регион передаётся явно. Для остальных поверхностей ответ шёл из того региона, куда шлюз отправил запрос.
Шесть дат на панели это мало для любых интервалов, поэтому их здесь нет. Следующий замер по графику 28 ноября. Если доля удержится выше 45 % и при этом поиск плагина, Perplexity и Яндекс будут двигаться в одну сторону, можно будет говорить о тренде увереннее.
Таблица наблюдений, на которой построена статья, собиралась с 19 июля по 11 ноября 2026 года, 3 129 строк, 92 вопроса, шесть поверхностей. Сводки, таблицы и проверка ссылок в этой статье получены прогоном скрипта анализа 13 ноября 2026 года.
Источник: habr.com