Почему надо это читать?
Спроси ChatGPT или Claude: «топовые продакт-менеджеры, делающие AI-продукты в России». Или спроси про ведущих экспертов в своей нише. С высокой вероятностью тебя в ответе не будет.
Я спросил, и меня в списке не было, зато были люди, которых я знаю лично, и подборка выглядела странно: кто-то давно ушёл из индустрии, кто-то уехал и делает AI-продукты за пределами РФ. При этом я руковожу продуктовым направлением в Т-Банке, делаю LLM-агентов для автоматизации саппорта, выступаю на конфах, но модель об этом ничего не знала, потому что выбирает она по данным, которые видит, а меня в этих данных просто не было.
Когда полез разбираться, выяснилось, что LLM знают информацию о людях из 2 типов источников: структурированные базы (Wikidata, Google Knowledge Graph, etc) и проиндексированные тексты, то есть страницы, которые модели нашли и сумели прочитать. Я отсутствовал в обоих, затревожился и за вечер это пофиксил. Думаю такая проблема есть не только у меня, поэтому и собрал пошаговый гайд из того, что сделал.
Дисклеймер:
Я писал этот гайд для таких же хлебушков как я, поэтому местами объясняю подробно, чтобы разобрался любой человек без глубокого IT-бэкграунда. Если вы из тех, кому проще делать чем читать лонгриды, то можно форкнуть мой репозиторий github.com/levinishnikov/personal-site, поменять имя и ссылки на свои, задеплоить и начать сразу с шага 3, за часок управитесь.
Тема при этом супер новая и горячая, всё ниже это мой личный опыт, так что если знаете, как сделать лучше или что я не учёл, залетайте в комментарии.
Начинаем!
Большие языковые модели знают только то, что в них вложили на этапе обучения (pre-train + alignment), и то, что они смогли вытащить (заретривить) из интернета. Если перевести на практический язык и говорить про конкретных людей, то, как я уже писал выше, модель берёт информацию из двух источников: из текстов, которые сумела прочитать, и из баз знаний вроде Wikidata. Дальше гайд разделён на понятные шаги, которые лучше выполнять последовательно, потому что каждый убирает одну преграду между тобой и моделью. Если что-то будет непонятно, не переживай, дальше про каждый шаг расскажу подробнее, а пока саммари:
Шаг 1. Сделать сайт читаемым (SSR). React-сайт отдаёт боту пустую страницу, потому что весь текст рисует JavaScript, а агенты его не запускают. Надо перенести сборку страницы на сервер, чтобы текст лежал в HTML.
Шаг 2. Пригласить агентов. На читаемый сайт модели всё равно заходят с осторожностью и могут пройти мимо. Надо добавить robots.txt чтобы разрешает краулить сайт, а llms.txt, JSON-LD и sitemap коротко объяснят, кто ты и как устроена навигация.
Шаг 3. Запуск завтра. Без твоего участия агенты новый домен найдут через пол года. Если не хочется ждать, то надо зарегистрироваться в 3 консолях, отдать им sitemap.
Шаг 4. Стать json-ом в Wikidata. Единсвенный шаг, который попадает в веса модели. Запись из Wikidata уходит в Google Knowledge Graph и дальше в обучающие датасеты крупных лаб.
Шаг 5. Настроить связи между профилями. Проставь взаимные ссылки между профилями и сайтом, чтобы LLM воспринимала тебя как одного человека.
Теперь подробнее про каждый шаг:
Шаг 1 Сделать сайт читаемым (SSR)
⏱ ~3-4 часа (или 15 минут на форк репозитория)
Надо создать свой персональный сайт. Кто-то скажет, зачем? у меня и так есть аккаунт в десяти социальных сетях, но на самом деле она часто не работает по трем прчинам:
Агент часто физически не может прочитать твои соцсети. LinkedIn прячет профили за логином, Twitter (X) режет краулеры etc. Сайт на своём домене открыт любой модели и в в любой момент.
Только на своём сайте факт о тебе записывается машиночитаемо и как надо конкретно тебе. Через JSON-LD (про это ниже) ты говоришь моделям прямым текстом: вот должность, вот работодатель, вот мой профиль и вот в чем я хорош. В дургих соц сетях ты вписываешся в чужой темплейт, который могут распарсить не так как тебя надо.
Сайт это якорь, который собирает все соц сети в один профиль. Wikidata ссылается на него, все профили ведут на него, и разрозненные аккаунты сшиваются в одну сущность.
Поэтому если у вас в 2026 нет one-pagerа про себя, то самое время его сделать. Благо инструментов очень много от Lovable до Сlaude Code. У меня уже был персональный сайт был, но был от полностью на React, вот что с этим не так:
Когда человек открывает сайт в браузере, происходит многоступенчатый процесс. Браузер скачивает HTML-файл с сервера, потом скачивает JavaScript, потом этот JavaScript выполняется и рисует содержимое страницы. Человек видит готовый результат и даже не задумывается, что текст появился только после того, как отработал код, а LLM-краулер (бот, который обходит интернет для сборо данных для самых разных моделей) работает проще: он приходит на URL, забирает HTML, который сервер отдаёт в первую секунду, и уходит, то есть он в принципе не выполняет JavaScript.
А у React-приложений в этом первоначальном HTML лежит пустой <div id="root"></div> и ссылка на JS-файл. Весь текст появляется только после выполнения этого файла.
Проверить свой ваш сайт (если такой есть) можно за 3 секунды: открой его в браузере и нажми Ctrl+U (Cmd+Option+U на Mac). Откроется исходный код. Если ты видишь свой текст и заголовки, бот тоже это видит. Если видишь пустой div и ссылки на .js-файлы, для бота твоей страницы не существует.
Решение: server-side rendering
Идея SSR в том, что сервер сам собирает готовую страницу и отдаёт полный HTML с текстом сразу. Бот получает весь контент в момент запроса, индексирует его и уходит
Стек: FastAPI (Python) + PostgreSQL + Jinja2 + Railway
my-site/ ├── backend/ │ ├── config.py │ ├── main.py │ ├── models.py │ ├── seo.py │ ├── site.env │ └── templates/ │ ├── _head.html │ ├── index.html │ ├── posts.html │ └── post.html └── static/ ├── styles.css ├── robots.txt └── llms.txt
Ловушка с JS-анимациями (хех!)
Даже с SSR осталась скрытая ловушка-джакушкера. На главной llmceo.com крутилась JS-анимация, где цифра размера команды листалась от 0 до 250, для людей выглядело эффектно, но некоторые продвинутые краулеры у OpenAI и Google используют headless-браузеры (настоящий Chrome без экрана, который открывает страницу и выполняет JavaScript). Эти браузеры делают «снимок» страницы через долю секунды после загрузки, когда анимация ещё на первом кадре. В моём случае на снимке цифра была 0, и в данных модели я мог попадать как «I lead 0 people».
Правило: всё, что ты хочешь донести до машины, должно быть обычным текстом в HTML, без зависимости от JavaScript.
<!-- Плохо --> I lead <span class="counter" data-target="250">250</span> people <!-- Хорошо --> I lead 250 people
Шаг 2. Пригласить агентов
⏱ ~30 минут (5 минут на правку в форкнутом репозитории)
После того как сайт начал отдавать контент в HTML, нужно было решить следующий слой задач: явно сказать LLM-агентам, что они здесь желанные гости, объяснить кто я в структурированном виде и дать карту всех страниц.
2.1. robots.txt ( 5 минут)
Файл robots.txt лежит в корне каждого сайта по адресу сайт.com/robots.txt. Это первое, что проверяет любой добросовестный LLM-агент перед тем, как читать содержимое. Он заходит туда автоматически и смотрит, есть ли разрешение.
В 2023-2024 крупные издатели (New York Times, Reddit) массово заблокировали AI-краулеров в robots.txt. После этого OpenAI и Anthropic выставили своим ботам осторожные дефолты: если разрешение неоднозначное, лучше пропустить сайт. Формально достаточной строки User-agent: * / Allow: / на практике может не хватить, потому что GPTBot, ClaudeBot, PerplexityBot ищут явное упоминание своего имени.
Поэтому надо перечислить каждого агента конкретно, чтобы дать однозначный сигнал:
User-agent: OAI-SearchBot User-agent: ChatGPT-User User-agent: Claude-SearchBot User-agent: Claude-User User-agent: PerplexityBot User-agent: Perplexity-User User-agent: Googlebot User-agent: Bingbot User-agent: Applebot User-agent: YandexBot User-agent: GPTBot User-agent: ClaudeBot User-agent: Google-Extended Allow: / User-agent: * Allow: / Sitemap: https://llmceo.com/sitemap.xml
User-agent здесь имя бота, Allow: / разрешение читать все страницы, Sitemap ссылка на карту сайта.
2.2. llms.txt ( 2 минуты)
Если robots.txt говорит боту «можно заходить», то llms.txt даёт AI-агенту моментальный контекст о тебе. Формат относительно новый, гарантии поддержки у него нет, но всё больше AI-агентов проверяют этот файл при обходе, при затратах в 2 минуты пропускать это шажок смысла нет.
# Даниэль Левинишников Head of product в Т-Банке. 250+ человек в команде. Фокусируюсь на автоматизации поддержки за счет внедрения LLM-агентов В свободное время пишу про AI, LLM-агентов и управление продуктом в тегеграм канале: t.me/tldrdaniel ## Ссылки - Главная: https://llmceo.com/ - Посты: https://llmceo.com/posts
2.3. JSON-LD ( 15 минут)
Обычно самый недооценённый инструмент в списке.
JSON-LD это невидимый для людей блок данных внутри кода страницы, написанный на языке Schema.org. Международный стандарт, который понимают Google, Bing, Яндекс и большинство LLM. Когда на сайте текстом написано «Даниэль Левинишников, Head of Products в Т-Банке», бот читает это как обычную строку и может понять смысл, а может и нет, потому что результат зависит от контекста, от парсинга, от обучения модели. JSON-LD снимает эту неопределённость: он передаёт машине структурированный факт с конкретным именем, должностью, работодателем и списком профилей, крч модели вообще не надо додумывать.
Google использует JSON-LD для построения Knowledge Graph, базы знаний, из которой берутся карточки справа от результатов поиска. LLM-ки при обучении получают эти структурированные данные. Разница между «упоминание в тексте» и «запись в графе знаний» определяет уровень уверенности, с которой модель может тебя цитировать.
Вот что я вставил в _head.html на llmceo.com:
<script type="application/ld+json"> { "@context": "https://schema.org", "@graph": [ { "@type": "WebSite", "@id": "https://llmceo.com/#website", "name": "Даниэль Левинишников", "url": "https://llmceo.com/" }, { "@type": "Person", "@id": "https://llmceo.com/#owner", "name": "Даниэль Левинишников", "jobTitle": "Head of Products", "worksFor": { "@type": "Organization", "name": "Т-Банк", "url": "https://tbank.ru" }, "url": "https://llmceo.com/", "sameAs": [ "https://www.linkedin.com/in/levinishnikov", "https://github.com/levinishnikov", "https://t.me/llmceo" ] } ] } </script>
Ключевое поле здесь sameAs. Оно перечисляет профили на других платформах и говорит: GitHub, LinkedIn и Telegram-канал принадлежат тому же человеку, что и llmceo.com.
LLM-агенты используют это для объединения сигналов, и все страницы становятся узлами одного графа, связанного с одной сущностью. Поле @type: "Person" сообщает, что запись описывает человека. worksFor связывает меня с записью о Т-Банке, а @id это внутренний идентификатор, через который другие блоки на сайте ссылаются на эту запись.
Еще на сайте у меня есть посты, которые автоматически подгружаются в момент публикации в тг, поэтому на каждой странице поста я добавил блок Article с привязкой к Person через @id, чтобы модель понимала, что статью написал тот же человек, который описан на главной:
{ "@type": "Article", "headline": "Заголовок поста", "author": {"@id": "https://llmceo.com/#owner"}, "datePublished": "2026-05-29", "url": "https://llmceo.com/posts/slug" }
2.4. Sitemap (10 минут)
Файл sitemap.xml это список всех страниц сайта с датами последнего обновления. Лежит по адресу llmceo.com/sitemap.xml, и боты проверяют его автоматически, особенно если путь указан в robots.txt. Без sitemap бот приходит на главную и должен сам догадываться, где остальные страницы, идя по ссылкам и угадывая структуру URL. Если на какую-то страницу нет прямой ссылки с главной, агент её просто не найдёт. Если есть sitemap модель получает точный перечень всех URL с датами изменений и знает, что обходить и когда возвращаться.
Я генерирую sitemap динамически из базы данных, чтобы каждый новый пост автоматически появлялся в карте:
@app.get("/sitemap.xml") def sitemap(db: Session = Depends(database.get_db)): posts = get_all_published_posts(db) xml = '<?xml version="1.0" encoding="UTF-8"?>\n' xml += '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n' for post in posts: xml += f""" <url> <loc>https://llmceo.com/posts/{post.slug}</loc> <lastmod>{post.publish_date}</lastmod> </url>\n""" xml += '</urlset>' return Response(xml, media_type="application/xml")
Шаг 3. Регистрация в поисковиках и мониторинг ( ~40 минут)
Зачем регистрироваться вручную
Поисковые боты рано или поздно найдут любой сайт в интернете. Для нового домена без входящих ссылок «рано или поздно» это месяцы, потому что агентам нужно обойти миллиарды страниц при ограниченном краулинг-бюджете, и неизвестный сайт стоит (а у меня такой) стоит в конце очереди. Регистрация в поисковых консолях запускает таймер: ты говоришь поисковику «вот мой сайт, вот sitemap, начинай обход прямо сейчас».
Консоли также единственный способ увидеть свой сайт глазами поисковика. Если есть ошибки в HTML или невалидный sitemap, ты узнаешь об этом только оттуда. Что делать в порядке убывания полезности:
3.1 Google Search Console (15 минут)
GSC это бесплатный инструмент Google для владельцев сайтов. Показывает, какие страницы проиндексированы, по каким запросам тебя находят, есть ли ошибки.
Я зашёл на search.google.com/search-console, нажал Add property и ввёл llmceo.com. Google попросил подтвердить владение через DNS verification: он дал текстовую строку (TXT-запись), которую нужно добавить в настройки домена у регистратора.
Коротко про DNS_) DNS это система, которая переводит название сайта в IP-адрес сервера. Настройки хранятся у того, кто продал тебе домен (в моём случае Namecheap). TXT-запись это текстовая заметка в DNS, которая ни на что технически не влияет, но позволяет Google убедиться, что ты контролируешь этот домен.
Что я делал:
- Зашёл в Namecheap,
- Открыл Advanced DNS,
- нажал Add Record.
- Выбрал Type: TXT,
- Host: @ (корневой домен, то есть сам llmceo.com),
- вставил строку от Google. Подождал 20 минут, пока DNS обновится,
- вернулся в GSC, нажал Verify.
- После подтверждения зашёл в раздел Sitemaps и ввёл https://llmceo.com/sitemap.xml.
Теперь Google знает, где лежит карта сайта, и начинает обход. УРА!
3.2 Bing Webmaster Tools (5 минут)
Bing важен, потому что ChatGPT использует именно его поисковый движок, когда ищет свежую информацию. Если тебя нет в индексе Bing, тебя нет в ответах ChatGPT на актуальные запросы.
Зашёл на bing.com/webmasters, нажал Import from Google Search Console. Bing забрал верификацию и sitemap из GSC за одно нажатие (получил ошибку, хихи)
Поэтому скачал файл BingSiteAuth.xml из Bing, положил в static/, задеплоил, в результате Bing проверил наличие файла и подтвердил владение доменом
Яндекс.Вебмастер (10 минут)
Для русскоязычного контента Яндекс остаётся критичным. YandexGPT и другие русскоязычные модели опираются на его индекс.
Зашёл на webmaster.yandex.ru, добавил сайт, скачал HTML-файл верификации (маленький файл, который Яндекс просит положить на сервер для подтверждения владения), положил в static/yandex_XXXX.html, задеплоил, нажал «Проверить», после верификации добавил sitemap.
Мониторинг ботов (10 минут)
Без мониторинга невозможно понять, работает ли процесс и начали ли агенты попадать на твой сайт. Каждый бот при заходе на сайт отправляет в заголовке запроса свой User-Agent, строку со своим именем. Googlebot отправляет Googlebot, ClaudeBot отправляет ClaudeBot. Вот код, который перехватывает каждый запрос к llmceo.com, проверяет User-Agent и пишет в лог строку вида [BOT] 2026-05-28 14:32:07 | Google | /.
from datetime import datetime import logging logging.basicConfig(level=logging.INFO, format="%(message)s") logger = logging.getLogger("bot") KNOWN_BOTS = { "Googlebot": "Google", "Bingbot": "Bing", "YandexBot": "Yandex", "PerplexityBot": "Perplexity", "OAI-SearchBot": "OpenAI", "GPTBot": "GPTBot", "ClaudeBot": "Claude", } @app.middleware("http") async def log_bots(request: Request, call_next): ua = request.headers.get("user-agent", "") for token, name in KNOWN_BOTS.items(): if token.lower() in ua.lower(): ts = datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S") logger.info(f"[BOT] {ts} | {name} | {request.url.path}") break return await call_next(request)
Шаг 4. Попасть в базу знаний LLM
⏱ ~30 минут (при наличии внешнего источника)
Почему Wikidata топ?
Всё, что описано выше, решает задачу индексируемых текстов: сайт стал читаемым, боты его находят, но это пока «тексты в интернете», которые модель может прочитать, а может проигнорировать, поэтому добавляем структурированные базы знаний!
Wikidata, открытая база данных от Wikimedia Foundation (тех же людей, что делают Википедию), хранит факты в машиночитаемом формате. Когда в Википедии написано «Барак Обама — 44-й президент США», в Wikidata это записано как объект Q76, свойство P39 (занимаемая должность) = Q11696 (Президент США), с датами начала и конца полномочий.
Цепочка работает так: данные из Wikidata попадают в Google Knowledge Graph (база знаний, из которой формируются карточки справа от результатов поиска), а Knowledge Graph попадает в трейн датасеты большинства LLM, то есть запись в Wikidata означает, что ты становишься сущностью в графе знаний, и для модели это более высокий уровень уверенности при генерации ответа.
При этом в Wikidata нельзя просто зарегистрироваться и написать о себе. Нужен минимум 1 независимый источник, подтверждающий твоё существование: статья в СМИ, интервью, страница спикера на конференции, etc
У меня были конференции и публикации, поэтому прошло легко. Если источника нет, его нужно сначала получить (лол!")
4.1 Создание записи ( 20 минут)
После регистрации на wikidata.org идёшь в Special:NewItem и заполняешь:
Label EN:
Daniel LevinishnikovLabel RU:
Даниэль ЛевинишниковDescription EN:
Head of Products at T-Bank, AI technology executiveDescription RU:
руководитель AI-продуктов в Т-Банке
Wikidata работает через statements, утверждения в формате «свойство → значение». Каждое свойство имеет код (P-номер), каждое значение либо текст, либо ссылка на другую сущность (Q-номер). Эти пары потом становятся фактами в Knowledge Graph. Нажимаешь + add statement и добавляешь:
Property | Value | Что это значит |
|---|---|---|
|
| этот объект человек |
|
| пол: мужской |
|
| гражданство: Казахстан |
|
| род занятий: product manager |
| Т-Банк | работодатель |
| официальный сайт | |
| levinishnikov | GitHub-аккаунт |
| levinishnikov | LinkedIn-аккаунт |
На statement P856 нужно нажать add reference, выбрать property P854 и вставить ссылку на внешний источник. Reference это доказательство и без него модераторы Wikidata могут удалить запись. После сохранения ты получаешь ID вида Q12345678, уникальный идентификатор в глобальном графе знаний. Что само по себе круто
Замкнуть петлю: Wikidata и сайт (2 минуты)
Запись в Wikidata ссылается на llmceo.com. Теперь нужно, чтобы llmceo.com ссылался обратно. Google видит двустороннюю связь и повышает уверенность, что сайт и запись описывают одного человека. Для этого добавил в Wikidata QID в массив sameAs в JSON-LD:
"sameAs": [ "https://www.wikidata.org/wiki/Q12345678", "https://www.linkedin.com/in/levinishnikov", "https://github.com/levinishnikov" ]
Шаг 5. Перекрёстные ссылки (10 минут)
Проблема: машина не знает, что все твои профили это ты.
Представь, что машина видит 3 карточки: «Daniel Levinishnikov» на GitHub, «Даниэль Левинишников» в Telegram, «Product Director в Alibaba Group» на LinkedIn. Имя везде написано по-разному, площадки разные. Для машины это с равным успехом и один человек, и 3 случайных однофамильца, и она не угадает. А если тебя зовут не Даниэль Левинишников, а Артём Ким, которых тысячи с похожими фамилиями и одинаковыми профилями, шансов угадать у неё нет вообще.
Решение: связать профили перекрёстными ссылками друг на друга.
Модель делает вывод: если страница А ссылается на страницу Б, а Б ссылается обратно на А, значит они про одного человека. Поэтому когда ты ставишь ссылку с сайта на каждый профиль и с каждого профиля обратно на сайт получается замкнутая петля, и агент перестаёт сомневаться. Чем больше таких взаимных связей между профилями и сайтом, тем увереннее модель объединяет всё про тебя в интернете в одну сущность
Дальше распишу, где именно на каждой площадке вставить связи.
На llmceo.com:
<a href="https://github.com/levinishnikov" rel="noopener noreferrer me">GitHub</a> <a href="https://linkedin.com/in/levinishnikov" rel="noopener noreferrer me">LinkedIn</a> <a href="https://t.me/llmceo" rel="noopener noreferrer me">Telegram</a>
В каждой соц-сети (извините, что гит теперь соц сеть) обратная ссылка, например я сделал так:
Платформа | Где найти | Что вписал |
|---|---|---|
GitHub | Settings → Edit profile → Website | |
Контактная информация → Сайт | ||
Telegram | Настройки → Bio |
После этого каждая платформа ссылается на llmceo.com, llmceo.com ссылается обратно через rel="me", JSON-LD перечисляет все профили в sameAs, Wikidata подтвеждает, граф замкнулся
Репозиторий для форка
Весь llmceo.com собран в открытом репозитории, который я навайбкодил через Claude Code и выложил специально для форка. Внутри SSR-сайт на FastAPI, готовые robots.txt и llms.txt, JSON-LD на всех страницах, динамический sitemap, middleware для логирования ботов и гайд по Wikidata. Меняете имя, ссылки и факты на свои, деплоите на Railway и за За вечер становитесь читаемыми для моделей.
Форкайте: github.com/levinishnikov/personal-site
На этом пока все!
Если сделали все по гайду, делитись сайтиками и пишите, сколько времени заняло и когда поймали ллм-агента!!!
