← Все новости
27.10.2026 · Sirak Ghroyan - SEO, GEO, AEO

JavaScript в SEO и AEO: как устроен рендеринг страниц и почему контент пропадает из поиска после релиза

Экспертные SEO-статьи

Оставьте заявку на SEO продвижение

    Команда выкатывает обновлённый фронтенд на современном JavaScript-фреймворке. Тестировщики открывают сайт в браузере, переходят по разделам, проверяют корзину и закрывают задачу: визуально всё работает. Но через неделю в Google Search Console и Яндекс Вебмастере начинается просадка: карточки товаров переходят в статус Soft 404, часть разделов выпадает из индекса, внутренние ссылки перестают обнаруживаться, а в сниппетах вместо названий статей появляется общий заголовок шаблона.

    Причина почти всегда одна: человек в браузере и поисковый робот видят страницу в разных состояниях. Браузер пользователя выполняет клиентский код, ждёт ответа сервисов, реагирует на прокрутку и клики. Поисковый робот работает по жёсткому конвейеру: сначала он оценивает сырой HTTP-ответ сервера, затем в неинтерактивном режиме пропускает страницу через сервис рендеринга и отсекает всё, что требует действий пользователя или заблокировано правилами обхода.

    Грамотная работа с JavaScript в SEO — это не отказ от реактивных интерфейсов. Задача решается архитектурно: критические сигналы документа (код ответа сервера, директивы индексации, канонический адрес, заголовки, основной текст и ссылки ) должны быть доступны роботу без имитации действий человека и без противоречий между первичным HTML и финальным DOM.

    Ниже — разбор рендеринга JavaScript в Google и Яндексе, типовых ошибок фронтенда и чек-листа приёмки релизов для поиска и ответных ИИ-систем (AEO и GEO). Официальная документация поисковых систем сверена 27 октября 2026 года. Регламент приёмки и архитектурная матрица — мои авторские рекомендации; фрагменты кода и сценарии релизов приведены как условные примеры, а не данные клиентских проектов.

    Как поисковые системы обрабатывают JavaScript: три фазы и ловушка первичного HTML

    В документации Google Search Central обработка сайтов на JavaScript разделена на три этапа: сканирование (Crawling), рендеринг (Rendering) и индексирование (Indexing). Основы JavaScript SEO в Google Search Central.

    На первом этапе Googlebot отправляет HTTP-запрос к адресу страницы и скачивает исходный HTML-файл. Ещё до попадания страницы в очередь на выполнение скриптов робот проверяет HTTP-заголовки, файл robots.txt и базовые метатеги в первичном ответе сервера. Именно здесь срабатывает первая ловушка.

    Если в исходном HTML-шаблоне одностраничного приложения (SPA) по умолчанию прописан тег , а разработчики рассчитывают, что клиентский скрипт после загрузки данных заменит его на index, follow, схема не сработает. Согласно документации Google, при обнаружении noindex на этапе первичного разбора HTML робот пропускает фазу рендеринга и не запускает JavaScript. Скрипт, который должен был снять запрет, просто не получает управления.

    Если страница открыта для сканирования, наступает вторая фаза — рендеринг. Сервис Web Rendering Service (WRS) запускает страницу в безголовом браузере на базе актуального («вечнозелёного», evergreen) движка Chromium, выполняет JavaScript и строит итоговое дерево документа (Rendered DOM). Затем наступает третья фаза: поисковая система анализирует отрендеренный DOM, извлекает текст, заголовки, микроразметку и новые ссылки для очереди обхода.

    При этом WRS работает только с ресурсами, к которым разрешён доступ. Если в robots.txt закрыты директории со скриптами (/assets/*.js, /static/) или внутренние API-эндпоинты (/api/v1/products), через которые фронтенд запрашивает название, цену и описание товара, браузер посетителя загрузит страницу без проблем (пользователи не читают robots.txt). Но поисковый робот соблюдает запрет: он не скачает заблокированный скрипт или JSON-ответ, получит пустой шаблон и исключит страницу из индекса. Исправление проблем с JavaScript в поиске Google.

    Интересное на сайте:
    Лучшие SEO-агентства России: 10 компаний для бизнеса в 2026 году

    Где расходятся Google, Яндекс и боты ответных ИИ-систем (AEO и GEO)

    У Google, Яндекса и краулеров генеративных систем разные настройки ожидания, правила кеширования и требования к серверному ответу.

    Особенности Web Rendering Service в Google

    В документации по отладке JavaScript инженеры Google выделяют четыре технических ограничения WRS, о которых важно помнить при проектировании фронтенда:

    1. Только HTTP-запросы без постоянных сокетов. Googlebot получает данные по протоколу HTTP и не поддерживает загрузку основного контента через постоянные соединения вроде WebSockets или WebRTC. Если каталог подтягивает записи только через сокет-соединение без HTTP-фолбэка, для поисковика страница останется пустой.
    2. Агрессивное кеширование и content fingerprinting. Чтобы не перегружать серверы сайтов, WRS активно кеширует статические файлы и может игнорировать заголовки Cache-Control. Если после релиза команда обновила логику внутри app.js, не изменив его URL, робот может долго выполнять старую версию скрипта из кеша вместе с новым HTML. Рекомендация Google — использовать хеширование содержимого в именах файлов (content fingerprinting, например main.2bb85551.js), чтобы каждое изменение кода создавало новый адрес ресурса.
    3. Сплющивание Shadow DOM в Web Components. При обработке веб-компонентов WRS объединяет («сплющивает») Shadow DOM и Light DOM. Если компонент не использует элемент для вставки содержимого из Light DOM, текст и ссылки внутри него могут пропасть из финального дерева документа.
    4. Отсутствие состояния между запросами. Каждый URL обрабатывается изолированно: WRS не переносит localStorage, sessionStorage и пользовательские cookies между страницами. Если сайт показывает контент только после записи региона или подтверждения возраста в локальное хранилище, робот при каждом заходе будет видеть модальное окно вместо текста статьи или карточки товара. Исправление проблем с JavaScript в поиске Google.

    Инструменты Яндекса: рендеринг JavaScript и window.YandexRotorSettings

    В Яндексе управление обработкой клиентского кода вынесено в раздел Яндекс Вебмастера «Индексирование → Рендеринг страниц JavaScript (β)». По умолчанию действует режим «На усмотрение робота», когда алгоритмы сами решают, нужно ли выполнять скрипты. Однако в официальной справке Яндекса есть важное правило: если на сайте уже настроен серверный рендеринг (SSR) или пререндеринг и значимый контент отдаётся сразу в исходном HTML, выполнять дополнительный JS-рендеринг на стороне робота не требуется — его рекомендуется отключить в Вебмастере. Рендеринг страниц JavaScript в справке Яндекс Вебмастера.

    Если же сайт полагается на клиентский рендеринг и подгружает данные асинхронно с задержкой, робот Яндекса может снять слепок страницы раньше завершения запроса к API. Для таких случаев Яндекс поддерживает глобальный объект конфигурации window.YandexRotorSettings, который размещают в до события DOMContentLoaded:

    Как рендеринг влияет на AEO и GEO

    В обсуждениях оптимизации под ответные системы (AEO) и генеративный поиск (GEO) — терминов, не имеющих единого отраслевого стандарта, — техническую доставку контента часто упускают из виду. Между тем в документации Google Search Central по функциям ИИ (AI Overviews и AI Mode) зафиксировано: для попадания страницы в генеративные сводки не существует специальных ИИ-тегов или отдельной схемы индексации. Базовое требование одно — страница должна быть просканирована, проиндексирована в основном поиске Google и иметь право на показ со сниппетом. Функции ИИ и ваш сайт в Google Search Central.

    Интересное на сайте:
    Почему календарь веб-архива обманывает: разбор восстановления старого блога на 7 230 адресов

    На практике это создаёт двойной фильтр для сайтов с тяжёлым клиентским JavaScript:

    Пять типовых ошибок фронтенда, из-за которых страницы выпадают из индекса

    Разберём пять сбоев, которые чаще всего возникают при обновлении клиентской части сайта.

    1. Конфликт канонических и индексных сигналов между сырым HTML и DOM

    В одностраничных приложениях базовый HTML-файл часто содержит шаблонные метатеги главной страницы, а реальные , и подставляются клиентским роутером после инициализации JavaScript.</p> <p>Если в исходном HTML-шаблоне прописан на главную страницу, а клиентский скрипт добавляет второй тег с адресом текущей карточки товара (или перезаписывает его с задержкой), в документе возникают противоречивые сигналы. О том, как поисковик взвешивает конфликтующие подсказки и почему он может выбрать не тот адрес, который задумал владелец сайта, я подробно писал в материале о работе canonical в SEO. В первичном HTML-ответе конкретной страницы не должно быть чужого canonical или временного noindex.</p> <h3>2. Псевдоссылки и потеря внутреннего графа перелинковки</h3> <p>Разработчики нередко оформляют карточки товаров, пагинацию или ссылки на подразделы через элементы </p> <div>, <button> или без атрибута href. Для пользователя в браузере переход срабатывает мгновенно через History API.</p> <p>Для поискового робота такой элемент ссылкой не является. В руководстве Google по сканируемым ссылкам прямо указано: робот гарантированно извлекает и ставит в очередь обхода только те адреса, которые размечены тегом с валидным атрибутом href, содержащим разрешаемый URL документа. Конструкции с javascript:void(0), или атрибутами разрывают внутреннюю перелинковку: робот заходит в категорию, но не видит переходов в карточки товаров. Требования Google к сканируемым ссылкам.</p> <p>При этом реальные ссылки нужны именно для тех страниц, которые должны индексироваться (категории, карточки, посадочные срезы со спросом и последовательная пагинация). Служебные переключатели сортировки и технические комбинации параметров, наоборот, не стоит выводить как открытые ссылки в DOM — эту грань я разбирал в статье про фильтры каталога в SEO и AEO.</p> <h3>3. Клиентский Soft 404 на несуществующих адресах</h3> <p>В классической серверной архитектуре обращение к удалённому товару или несуществующему URL возвращает HTTP-статус 404 Not Found или 410 Gone. В клиентском SPA веб-сервер часто настроен так, чтобы на любой маршрут отдавать один и тот же файл index.html с кодом 200 OK. Затем в браузере запускается JavaScript, обращается к API, получает ответ «товар не найден» и рисует заглушку «Страница не существует».</p> <p>Для поисковой системы комбинация кода 200 OK при пустом или сообщающем об ошибке документе является классической ошибкой Soft 404. Робот тратит краулинговый бюджет на обход несуществующих адресов, а в Search Console копится список проблемных страниц. В документации Google описаны два решения: при серверном рендеринге отдавать честный HTTP-код 404/410 на уровне сервера, а при чисто клиентской маршрутизации — немедленно добавлять в тег или перенаправлять маршрут на страницу, отдающую серверный статус 404. Ошибки Soft 404 и способы их устранения в Google.</p> <h3>4. Отложенная загрузка (lazy-loading), завязанная на действия пользователя</h3> <p>Отложенная подгрузка блоков ниже первого экрана ускоряет работу сайта, но при неправильной реализации скрывает контент от индексации. В руководстве по lazy-loading Google предупреждает: во время рендеринга робот не прокручивает страницу и не кликает по элементам интерфейса. Настройка отложенной загрузки контента в Google Search Central.</p> <p>Если описание товара, таблица характеристик или отзывы подгружаются в DOM только после события window.onscroll или нажатия на вкладку «Характеристики», в отрендеренном DOM этих данных не окажется. Как сделать правильно:</p> <ul> <li>Для изображений и iframe ниже первого экрана используйте нативный атрибут loading=»lazy» или API IntersectionObserver — при рендеринге WRS автоматически увеличивает высоту виртуального окна просмотра (viewport), чтобы сработали стандартные наблюдатели видимости.</li> <li>Не применяйте lazy-loading к контенту первого экрана (заголовку, главному фото и основному описанию).</li> <li>Для вкладок и аккордеонов загружайте текст в HTML-разметку сразу и управляйте его видимостью через CSS, вместо того чтобы запрашивать текст с сервера только по клику мыши.</li> </ul> <h3>5. Обрыв рендеринга из-за неперехваченных ошибок в скриптах</h3> <p>Ошибка второстепенного виджета (онлайн-чата, геотаргетинга или рекомендательного блока) может остаться незамеченной в браузере тестировщика, если она возникает только в окружении без cookies. Но если неперехваченное исключение (Uncaught TypeError) прерывает выполнение основного бандла до отрисовки центрального блока страницы, робот получит пустой экран. Проверка логов консоли внутри инструмента проверки URL в Search Console помогает заметить ошибки выполнения скриптов, если они воспроизводятся во время прохода WRS.</p> <h2><span class="ez-toc-section" id="%D0%9A%D0%B0%D0%BA%D1%83%D1%8E_%D0%B0%D1%80%D1%85%D0%B8%D1%82%D0%B5%D0%BA%D1%82%D1%83%D1%80%D1%83_%D0%B2%D1%8B%D0%B1%D1%80%D0%B0%D1%82%D1%8C_SSR_SSG_%D0%B3%D0%B8%D0%B4%D1%80%D0%B0%D1%82%D0%B0%D1%86%D0%B8%D1%8F_%D0%B8%D0%BB%D0%B8_%D0%B4%D0%B8%D0%BD%D0%B0%D0%BC%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B8%D0%B9_%D1%80%D0%B5%D0%BD%D0%B4%D0%B5%D1%80%D0%B8%D0%BD%D0%B3"></span>Какую архитектуру выбрать: SSR, SSG, гидратация или динамический рендеринг<span class="ez-toc-section-end"></span></h2> <p>При запуске сайта или перестройке фронтенда выбор способа рендеринга определяет, насколько стабильно страницы будут входить в индекс.</p> <ol> <li><b>Статическая генерация (SSG, Static Site Generation)</b> — HTML-код каждой страницы собирается заранее на этапе сборки или по расписанию. Это самый надёжный вариант для разделов со стабильным контентом: статей блога, справочников, посадочных страниц услуг и документации. Поисковый робот и ИИ-краулер сразу получают готовый HTML без ожидания скриптов.</li> <li><b>Серверный рендеринг с гидратацией (SSR + Hydration)</b> — при запросе адреса сервер собирает полный HTML с актуальными данными (ценами, остатками, заголовками и метатегами), отправляет его клиенту, а затем в браузере «оживляет» интерактивные элементы через JavaScript. Это рабочий стандарт для интернет-магазинов, маркетплейсов и крупных порталов.</li> <li><b>Чистый клиентский рендеринг (CSR, Client-Side Rendering)</b> — сервер отдаёт только минимальный HTML-каркас, а весь контент строится в браузере. Такую схему разумно оставлять для закрытых личных кабинетов, панелей управления и внутренних инструментов, которым не нужно ранжироваться по информационным или товарным запросам.</li> </ol> <p>Отдельно стоит сказать о <b>динамическом рендеринге (Dynamic Rendering)</b> — схеме, при которой сервер определяет поискового робота по заголовку User-Agent и отдаёт ему предрендеренный статический слепок, а обычным посетителям отправляет клиентский SPA. В документации Google прямо подчёркнуто: динамический рендеринг является <b>временным обходным путём (workaround), а не рекомендуемым долгосрочным решением</b>. Он усложняет инфраструктуру и создаёт риск: если предрендеренный для бота HTML из-за сбоя кеша начнёт существенно отличаться от пользовательской версии, поисковая система может расценить расхождение как клоакинг. Инвестировать ресурсы лучше в полноценный SSR, SSG или гидратацию. Позиция Google по динамическому рендерингу.</p> <h2><span class="ez-toc-section" id="%D0%A0%D0%B5%D0%B3%D0%BB%D0%B0%D0%BC%D0%B5%D0%BD%D1%82_%D0%BF%D1%80%D0%B8%D1%91%D0%BC%D0%BA%D0%B8_%D1%84%D1%80%D0%BE%D0%BD%D1%82%D0%B5%D0%BD%D0%B4-%D1%80%D0%B5%D0%BB%D0%B8%D0%B7%D0%B0_6_%D0%BF%D1%80%D0%BE%D0%B2%D0%B5%D1%80%D0%BE%D0%BA_%D0%B4%D0%BE_%D0%B8_%D0%BF%D0%BE%D1%81%D0%BB%D0%B5_%D0%B2%D1%8B%D0%BA%D0%B0%D1%82%D0%BA%D0%B8"></span>Регламент приёмки фронтенд-релиза: 6 проверок до и после выкатки<span class="ez-toc-section-end"></span></h2> <p>Перед выкаткой и сразу после релиза я рекомендую проходить чек-лист из шести проверок.</p> <ol> <li><b>Сверка первичного HTML и отрендеренного DOM.</b> На тестовом стенде запросите страницу HTTP-клиентом без выполнения скриптов (curl) и сравните ответ с итоговым DOM после выполнения JavaScript. В сыром HTML не должно быть шаблонного noindex и чужого, а после рендеринга в DOM должны присутствовать уникальный<br /> <h1>, основной текст и внутренние ссылки .</li> <li><b>Проверка навигации без событий клика и скролла.</b> Убедитесь, что ссылки на категории, карточки и страницы пагинации (?page=2) присутствуют в DOM как теги , а характеристики товара не требуют нажатия на вкладку для появления в разметке.</li> <li><b>Тест несуществующего URL на Soft 404.</b> Обратитесь к несуществующему адресу (/catalog/non-existent-item-999). При SSR сервер обязан вернуть HTTP-статус 404 или 410. При CSR проверьте, что роутер сразу выставляет noindex или перенаправляет на страницу со статусом 404, а не оставляет код 200 OK с индексируемой заглушкой.</li> <li><b>Проверка доступности ресурсов в robots.txt и хеширования бандлов.</b> Убедитесь, что файлы .js, .css и публичные API-маршруты, формирующие контент страницы, открыты для обхода, а имена скриптов содержат хеш содержимого (content fingerprinting).</li> <li><b>Согласование настроек рендеринга в Яндекс Вебмастере.</b> Если проект переехал с CSR на полноценный SSR, отключите лишний рендеринг на стороне робота в разделе «Индексирование → Рендеринг страниц JavaScript» Яндекс Вебмастера. Если проект остаётся на асинхронном CSR, проверьте корректность работы window.YandexRotorSettings и сигнала IsLoaded = true.</li> <li><b>Пострелизный контроль через URL Inspection и Rich Results Test.</b> В первый день после выкатки проверьте по одному типовому URL каждого шаблона через инструмент проверки URL в Google Search Console («Проверить опубликованный URL → Просмотреть просканированную страницу»), сверяя итоговый HTML, скриншот и лог ошибок консоли JS.</li> </ol> <h2><span class="ez-toc-section" id="%D0%A1_%D1%87%D0%B5%D0%B3%D0%BE_%D0%BD%D0%B0%D1%87%D0%B0%D1%82%D1%8C_%D0%BD%D0%B0_%D1%81%D0%B2%D0%BE%D1%91%D0%BC_%D1%81%D0%B0%D0%B9%D1%82%D0%B5"></span>С чего начать на своём сайте<span class="ez-toc-section-end"></span></h2> <p>Если есть подозрение, что часть контента теряется на этапе выполнения JavaScript, возьмите три ключевых шаблона сайта и выполните диагностику в панелях вебмастера.</p> <p>Сначала откройте инструмент проверки URL в Google Search Console для живой страницы и проверьте код отрендеренного DOM: найдите поиском по коду текст со второго экрана, характеристики из вкладок и ссылки на соседние товары. Затем проверьте настройки рендеринга JavaScript и отчёт «Диагностика сайта» в Яндекс Вебмастере, а также отчёт индексирования на предмет ошибок Soft 404. Сопоставление этих данных помогает сузить круг гипотез — от блокировки ресурсов в robots.txt до клиентской маршрутизации или отложенной загрузки — и сформулировать предметное техническое задание для разработчиков по подтверждённым расхождениям.</p> <p>Источник: vc.ru</p> <div class="crp_related crp-grid"><ul><li><a href="https://seosha.ru/pochemu-kalendar-veb-arhiva-obmanyvaet-razbor-vosstanovleniya-starogo-bloga-na-7-230-adresov/" class="crp_link post-36138"><figure><img width="250" height="150" src="https://seosha.ru/wp-content/uploads/2026/10/1-6-250x150-optimized.jpg" class="crp_featured crp_thumb crp_thumbnail" alt="1-6" style="" title="Почему календарь веб-архива обманывает: разбор восстановления старого блога на 7 230 адресов" loading="lazy" decoding="async" /></figure><span class="crp_title">Почему календарь веб-архива обманывает: разбор…</span></a></li><li><a href="https://seosha.ru/seo-daydzhest-3-7-idey-za-nedelyu-19-25-oktyabrya-2026/" class="crp_link post-36081"><figure><img width="250" height="150" src="https://seosha.ru/wp-content/uploads/2026/10/1-1-250x150-optimized.jpg" class="crp_featured crp_thumb crp_thumbnail" alt="1-1" style="" title="SEO-дайджест №3: 7 идей за неделю 19–25 октября 2026" loading="lazy" decoding="async" /></figure><span class="crp_title">SEO-дайджест №3: 7 идей за неделю 19–25 октября 2026</span></a></li><li><a href="https://seosha.ru/seo-bez-magii-kak-ya-vystraivayu-rabotu-s-saytom/" class="crp_link post-36133"><figure><img width="250" height="150" src="https://seosha.ru/wp-content/uploads/2026/10/1-4-250x150-optimized.jpg" class="crp_featured crp_thumb crp_thumbnail" alt="1-4" style="" title="SEO без магии: как я выстраиваю работу с сайтом" loading="lazy" decoding="async" /></figure><span class="crp_title">SEO без магии: как я выстраиваю работу с сайтом</span></a></li><li><a href="https://seosha.ru/luchshie-seo-agentstva-rossii-10-kompaniy-dlya-biznesa-v-2026-godu/" class="crp_link post-36153"><figure><img width="250" height="150" src="https://seosha.ru/wp-content/uploads/2026/10/1-7-250x150-optimized.jpg" class="crp_featured crp_thumb crp_thumbnail" alt="1-7" style="" title="Лучшие SEO-агентства России: 10 компаний для бизнеса в 2026 году" loading="lazy" decoding="async" /></figure><span class="crp_title">Лучшие SEO-агентства России: 10 компаний для бизнеса…</span></a></li></ul><div class="crp_clear"></div></div> </div> </div> <footer> <a class="logo" href="https://seosha.ru/" style="display:flex;align-items:center;gap:8px;text-decoration:none"> <svg width="22" height="22" viewBox="0 0 34 34" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"> <circle cx="17" cy="17" r="14" fill="none" stroke="var(--accent)" stroke-width="2" opacity=".7"/> <circle cx="17" cy="17" r="8" fill="none" stroke="var(--purple)" stroke-width="2" opacity=".6"/> <line x1="12" y1="20" x2="12" y2="14" stroke="var(--accent)" stroke-width="1.5" stroke-linecap="round"/> <line x1="17" y1="20" x2="17" y2="11" stroke="var(--text)" stroke-width="1.5" stroke-linecap="round"/> <line x1="22" y1="20" x2="22" y2="16" stroke="var(--purple)" stroke-width="1.5" stroke-linecap="round"/> <circle cx="17" cy="17" r="2.5" fill="var(--accent)"/> </svg> <span style="font-family:'Space Grotesk',sans-serif;font-size:14px;font-weight:700;color:var(--text)">СЕОША<span style="color:var(--accent)">.</span></span> </a> <ul class="footer-links"><li><a target="_blank" rel="noopener noreferrer" href="https://t.me/nikitashabalin92">Telegram</a></li><li><a target="_blank" rel="noopener noreferrer" href="https://hh.ru/resume/f7b44674ff05250d320039ed1f515a6e4e464b">HH.ru</a></li><li><a target="_blank" rel="noopener noreferrer" href="https://vc.ru/seosha">VC.ru</a></li></ul> <div class="footer-copy">© 2026</div> </footer> <!-- Fancybox --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/ui@5.0/dist/fancybox/fancybox.css"/> <script src="https://cdn.jsdelivr.net/npm/@fancyapps/ui@5.0/dist/fancybox/fancybox.umd.js"></script> <script> document.addEventListener('DOMContentLoaded', function () { function shemkiFullImageUrl(img) { var srcset = img.getAttribute('srcset'); if (srcset) { var best = '', bestW = 0; srcset.split(',').forEach(function (part) { var m = part.trim().match(/^(\S+)\s+(\d+)w$/); if (m && Number(m[2]) >= bestW) { bestW = Number(m[2]); best = m[1]; } }); if (best) return best; } var src = img.getAttribute('data-src') || img.getAttribute('src') || img.src || ''; return src.replace(/-\d+x\d+(?=\.(?:jpe?g|png|gif|webp|avif)(?:\?|$))/i, ''); } function shemkiPerView() { var w = window.innerWidth || document.documentElement.clientWidth; if (w <= 640) return 1; if (w <= 900) return 2; return 3; } function shemkiInitGallerySlider(gallery) { if (!gallery || gallery.dataset.shemkiSlider === '1') return; var items = Array.prototype.slice.call(gallery.querySelectorAll(':scope > .gallery-item')); if (!items.length) return; gallery.dataset.shemkiSlider = '1'; gallery.classList.add('shemki-gallery-slider'); Array.prototype.slice.call(gallery.querySelectorAll(':scope > br')).forEach(function (br) { br.remove(); }); var viewport = document.createElement('div'); viewport.className = 'shemki-gallery-viewport'; var track = document.createElement('div'); track.className = 'shemki-gallery-track'; items.forEach(function (item) { track.appendChild(item); }); viewport.appendChild(track); gallery.insertBefore(viewport, gallery.firstChild); var prev = document.createElement('button'); prev.type = 'button'; prev.className = 'shemki-gallery-btn shemki-gallery-btn--prev'; prev.setAttribute('aria-label', 'Назад'); prev.innerHTML = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"></polyline></svg>'; var next = document.createElement('button'); next.type = 'button'; next.className = 'shemki-gallery-btn shemki-gallery-btn--next'; next.setAttribute('aria-label', 'Вперёд'); next.innerHTML = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"></polyline></svg>'; gallery.appendChild(prev); gallery.appendChild(next); var page = 0; var gap = 14; function update() { var pv = shemkiPerView(); items.forEach(function (item) { item.style.flex = '0 0 calc((100% - ' + ((pv - 1) * gap) + 'px) / ' + pv + ')'; }); var max = Math.max(0, items.length - pv); if (page > max) page = max; if (page < 0) page = 0; var offset = 0; if (page > 0 && items[page]) { offset = items[page].offsetLeft - track.offsetLeft; } track.style.transform = 'translateX(' + (-offset) + 'px)'; prev.disabled = page <= 0; next.disabled = page >= max; prev.style.display = items.length > pv ? '' : 'none'; next.style.display = items.length > pv ? '' : 'none'; } prev.addEventListener('click', function () { page -= 1; update(); }); next.addEventListener('click', function () { page += 1; update(); }); window.addEventListener('resize', update); update(); } function shemkiWrapBlockImages() { var content = document.querySelector('.entry-content'); if (!content) return; var kids = Array.prototype.slice.call(content.children); var run = []; function flush() { if (run.length < 3) { run = []; return; } var wrap = document.createElement('div'); wrap.className = 'gallery gallery-columns-3 shemki-from-blocks'; run[0].parentNode.insertBefore(wrap, run[0]); run.forEach(function (el) { el.classList.add('gallery-item'); wrap.appendChild(el); }); run = []; } kids.forEach(function (el) { if (el.classList && el.classList.contains('wp-block-image')) { run.push(el); } else { flush(); } }); flush(); } shemkiWrapBlockImages(); document.querySelectorAll('.entry-content .gallery').forEach(shemkiInitGallerySlider); var roots = document.querySelectorAll('.entry-content, .entry-thumb'); if (!roots.length) return; roots.forEach(function (root) { root.querySelectorAll('img').forEach(function (img) { var src = img.currentSrc || img.src; if (!src) return; var link = img.closest('a'); var galleryItem = img.closest('.gallery-item'); if (galleryItem && link) { var groupEl = img.closest('.gallery, .shemki-gallery-slider'); var group = (groupEl && groupEl.id) ? groupEl.id : 'gallery'; link.setAttribute('href', shemkiFullImageUrl(img)); link.setAttribute('data-fancybox', group); if (img.alt) link.setAttribute('data-caption', img.alt); return; } if (link) { var href = link.getAttribute('href') || ''; if (/\.(jpe?g|png|gif|webp|avif|svg)(\?|$)/i.test(href) || href === src || root.classList.contains('entry-thumb')) { link.setAttribute('data-fancybox', 'gallery'); if (img.alt) link.setAttribute('data-caption', img.alt); } return; } var a = document.createElement('a'); a.href = shemkiFullImageUrl(img); a.setAttribute('data-fancybox', 'gallery'); if (img.alt) a.setAttribute('data-caption', img.alt); img.parentNode.insertBefore(a, img); a.appendChild(img); }); }); if (typeof Fancybox !== 'undefined') { Fancybox.bind('[data-fancybox]', { animated: true, Toolbar: { display: { left: ['infobar'], middle: [], right: ['slideshow', 'download', 'thumbs', 'close'], }, }, }); } }); </script> <noscript> <div> <img src="https://mc.yandex.ru/watch/108385747" style="position:absolute; left:-9999px;" alt=""/> </div> </noscript> <script type="speculationrules"> {"prefetch":[{"source":"document","where":{"and":[{"href_matches":"/*"},{"not":{"href_matches":["/wp-*.php","/wp-admin/*","/wp-content/uploads/*","/wp-content/*","/wp-content/plugins/*","/wp-content/themes/shemki/*","/*\\?(.+)"]}},{"not":{"selector_matches":"a[rel~=\"nofollow\"]"}},{"not":{"selector_matches":".no-prefetch, .no-prefetch a"}}]},"eagerness":"conservative"}]} </script> <script>var pseudo_links = document.querySelectorAll(".pseudo-clearfy-link");for (var i=0;i<pseudo_links.length;i++ ) { pseudo_links[i].addEventListener("click", function(e){ window.open( e.target.getAttribute("data-uri") ); }); }</script><script id="wp-yandex-metrika_contact-form-7-js" src="https://seosha.ru/wp-content/plugins/wp-yandex-metrika/assets/contactFormSeven.min.js?ver=1793077677"></script> <script id="wp-hooks-js" src="https://seosha.ru/wp-includes/js/dist/hooks.min.js?ver=1783618572"></script> <script id="wp-i18n-js" src="https://seosha.ru/wp-includes/js/dist/i18n.min.js?ver=1783618572"></script> <script id="wp-i18n-js-after"> wp.i18n.setLocaleData( { 'text direction\u0004ltr': [ 'ltr' ] } ); //# sourceURL=wp-i18n-js-after </script> <script id="swv-js" src="https://seosha.ru/wp-content/plugins/contact-form-7/includes/swv/js/index.js?ver=1784043338"></script> <script id="contact-form-7-js-translations"> ( function( domain, translations ) { var localeData = translations.locale_data[ domain ] || translations.locale_data.messages; localeData[""].domain = domain; wp.i18n.setLocaleData( localeData, domain ); } )( "contact-form-7", {"translation-revision-date":"2026-07-09 09:06:29+0000","generator":"GlotPress\/4.0.3","domain":"messages","locale_data":{"messages":{"":{"domain":"messages","plural-forms":"nplurals=3; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : ((n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14)) ? 1 : 2);","lang":"ru"},"This contact form is placed in the wrong place.":["\u042d\u0442\u0430 \u043a\u043e\u043d\u0442\u0430\u043a\u0442\u043d\u0430\u044f \u0444\u043e\u0440\u043c\u0430 \u0440\u0430\u0437\u043c\u0435\u0449\u0435\u043d\u0430 \u0432 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u043c \u043c\u0435\u0441\u0442\u0435."],"Error:":["\u041e\u0448\u0438\u0431\u043a\u0430:"]}},"comment":{"reference":"includes\/js\/index.js"}} ); //# sourceURL=contact-form-7-js-translations </script> <script id="contact-form-7-js-before"> var wpcf7 = { "api": { "root": "https:\/\/seosha.ru\/wp-json\/", "namespace": "contact-form-7\/v1" } }; //# sourceURL=contact-form-7-js-before </script> <script id="contact-form-7-js" src="https://seosha.ru/wp-content/plugins/contact-form-7/includes/js/index.js?ver=1784043338"></script> <script id="fitvids-js" src="https://seosha.ru/wp-content/plugins/fitvids-for-wordpress/jquery.fitvids.js?ver=1782041844"></script> <script id="eztoc-scroll-scriptjs-js-extra"> var eztoc_smooth_local = {"scroll_offset":"30","add_request_uri":"","add_self_reference_link":""}; //# sourceURL=eztoc-scroll-scriptjs-js-extra </script> <script id="eztoc-scroll-scriptjs-js" src="https://seosha.ru/wp-content/plugins/easy-table-of-contents/assets/js/smooth_scroll.min.js?ver=1782041844"></script> <script id="eztoc-js-cookie-js" src="https://seosha.ru/wp-content/plugins/easy-table-of-contents/vendor/js-cookie/js.cookie.min.js?ver=1782041844"></script> <script id="eztoc-jquery-sticky-kit-js" src="https://seosha.ru/wp-content/plugins/easy-table-of-contents/vendor/sticky-kit/jquery.sticky-kit.min.js?ver=1782041844"></script> <script id="eztoc-js-js-extra"> var ezTOC = {"smooth_scroll":"1","scroll_offset":"30","fallbackIcon":"\u003Cspan class=\"\"\u003E\u003Cspan class=\"eztoc-hide\" style=\"display:none;\"\u003EToggle\u003C/span\u003E\u003Cspan class=\"ez-toc-icon-toggle-span\"\u003E\u003Csvg style=\"fill: #999;color:#999\" xmlns=\"http://www.w3.org/2000/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"\u003E\u003Cpath d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"\u003E\u003C/path\u003E\u003C/svg\u003E\u003Csvg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http://www.w3.org/2000/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"\u003E\u003Cpath d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"/\u003E\u003C/svg\u003E\u003C/span\u003E\u003C/span\u003E","chamomile_theme_is_on":""}; //# sourceURL=eztoc-js-js-extra </script> <script id="eztoc-js-js" src="https://seosha.ru/wp-content/plugins/easy-table-of-contents/assets/js/front.min.js?ver=1782041844"></script> <script id="shemki-theme-js-extra"> var shemkiTheme = {"captchaClientKey":"ysc1_ch2W1zufDMIevtcmaixI8DLfMBsl7ImaJCZKLUrQ096af51f"}; //# sourceURL=shemki-theme-js-extra </script> <script id="shemki-theme-js" src="https://seosha.ru/wp-content/themes/shemki/assets/js/theme.js?ver=1787155009"></script> <script id="shemki-smartcaptcha-js" src="https://smartcaptcha.yandexcloud.net/captcha.js?render=explicit"></script> <script type="text/javascript"> jQuery(document).ready(function () { jQuery('body').fitVids(); }); </script> <!--Start VDZ Yandex Metrika Plugin--> <!-- Yandex.Metrika counter --> <script type="text/javascript" > (function (d, w, c) { (w[c] = w[c] || []).push(function() { try { w.yaCounter70787425 = new Ya.Metrika({ id:70787425, clickmap:true, trackLinks:true, accurateTrackBounce:true, webvisor:true, trackHash:true, ecommerce:"dataLayer" }); } catch(e) { } }); var n = d.getElementsByTagName("script")[0], s = d.createElement("script"), f = function () { n.parentNode.insertBefore(s, n); }; s.type = "text/javascript"; s.async = true; s.src = "https://mc.yandex.ru/metrika/watch.js"; if (w.opera == "[object Opera]") { d.addEventListener("DOMContentLoaded", f, false); } else { f(); } })(document, window, "yandex_metrika_callbacks"); </script> <noscript><div><img src="https://mc.yandex.ru/watch/70787425" style="position:absolute; left:-9999px;" alt="" /></div></noscript> <!-- /Yandex.Metrika counter --> <!--End VDZ Yandex Metrika Plugin--> <script>!function(){var t=!1;try{var e=Object.defineProperty({},"passive",{get:function(){t=!0}});window.addEventListener("test",null,e)}catch(t){}return t}()||function(i){var o=!0,s=!1;EventTarget.prototype.addEventListener=function(t,e,n){var r="object"==typeof n,a=r?n.capture:n;n=r?n:{},"touchstart"!=t&&"scroll"!=t&&"wheel"!=t||(n.passive=void 0!==n.passive?n.passive:o),n.capture=void 0!==a?a:s,i.call(this,t,e,n)}}(EventTarget.prototype.addEventListener);</script></body> </html>