Обсудить задачу

Как сторонние скрипты незаметно убивают скорость сайта

Чат-виджет, аналитика, тепловая карта и рекламный пиксель - это сторонние скрипты, код с чужого домена, который выполняется по своему расписанию, не согласованному с остальным сайтом. Каждый такой скрипт занимает основной поток браузера и часть сетевой полосы, поэтому сайт с идеально оптимизированным собственным кодом всё равно может показывать плохой LCP и INP из-за одного лишнего виджета. Дальше - через какие именно механизмы сторонние скрипты снижают скорость сайта, и как загружать их так, чтобы они не решали за вас, каким будет опыт пользователя.

По данным обзора Web Almanac 2024 от HTTP Archive, медианная страница из топ-1000 сайтов подключает 66 сторонних запросов, а из топ-миллиона - 27. Почти треть всех сторонних запросов на сайтах приходится на рекламу, аналитику и сервисы согласия на обработку данных. В том же отчёте, в разделе о производительности, отдельно выделены скрипты категории “User Behavior” - это тепловые карты и запись сессий вроде Hotjar и Smartlook: страницы с такими скриптами показывают хороший INP только в 37% случаев на мобильных устройствах, тогда как страницы со скриптами CDN и хостинга - в 50%, а с сервисами согласия - в 53%.

В проектах аудита сайтов мы регулярно видим одну и ту же картину: разработчик оптимизирует изображения и код, PageSpeed растёт, а через месяц маркетинг подключает новый чат или виджет опроса - и показатель падает обратно без единой правки в основном коде. Дальше разберём, что именно ломается на уровне браузера, и как выстроить процесс, чтобы сторонний код не откатывал скорость сайта после каждого нового инструмента.

Для бизнеса это не абстракция. Каждый лишний виджет - это реальные секунды до того, как пользователь сможет нажать кнопку или начать читать текст, а на платном трафике это деньги, потраченные на клики, которые не долетают до конверсии из-за тормозящего интерфейса.

Сторонний скрипт: JavaScript-код, который загружается с домена, не принадлежащего вашему сайту, и выполняется вне контроля вашей команды разработки - чат-виджеты, счётчики аналитики, тег-менеджеры, рекламные пиксели, инструменты A/B-тестирования и загрузчики шрифтов.

Почему сторонние скрипты сильнее всего замедляют сайт

Собственный код сайта разработчик может профилировать, разбить на части и загрузить в нужный момент. Сторонний код - чёрный ящик: неизвестно, что внутри, когда он инициализируется и сколько раз пересчитывает DOM.

Браузер обрабатывает сторонний <script> так же, как любой другой: скачивает файл, разбирает его (parse) и выполняет (execute) в основном потоке - том же самом потоке, где происходит вёрстка страницы и обработка кликов пользователя. Пока идёт разбор и выполнение чужого кода, браузер физически не может отрисовать следующий кадр или ответить на действие пользователя.

Разница с первоначальным кодом сайта - в масштабе управления. У сайта обычно один разработчик и один код-ревью на изменение. Сторонние скрипты подключают несколько отделов независимо друг от друга: маркетинг ставит пиксель, поддержка - чат, продакт - инструмент опросов, и никто не видит совокупный эффект, пока не запустит профилировщик.

Синхронный скрипт в начале страницы ломает LCP

Largest Contentful Paint (LCP): время до отрисовки самого крупного видимого элемента на экране - обычно это hero-изображение или заголовок; порог для хорошего результата - 2,5 секунды.

Если сторонний <script> вставлен в <head> без атрибутов async или defer, браузер останавливает разбор остального HTML, пока не скачает и не выполнит этот файл целиком. LCP-элемент физически не может отрисоваться раньше, чем закончится этот блок, даже если само изображение уже готово к показу.

Хуже всего с этим справляются тег-менеджеры и инструменты A/B-тестирования, встроенные без разбора: они по умолчанию грузятся синхронно и максимально рано, чтобы успеть подменить контент до первой отрисовки - и именно поэтому чаще всего оказываются причиной сорванного LCP на лендингах и посадочных страницах.

Поздно подключённый виджет сдвигает уже показанную страницу

Вторая типичная поломка - не про время загрузки, а про момент появления элемента на уже отрисованной странице.

Чат-виджет, баннер согласия на cookie или блок отзывов, вставленные через JavaScript через несколько секунд после начала загрузки, раздвигают контент, который пользователь уже начал читать. Это ровно то, что считает метрика CLS (Cumulative Layout Shift): совокупный сдвиг видимых элементов за время жизни страницы; порог хорошего значения - 0,1.

Причины сдвига и рабочие CSS-фиксы - зарезервированное место под контейнер, position: fixed для баннеров вместо вставки в поток документа - разобраны подробно в статье про то, почему показатели качества сайта прыгают между визитами. Здесь важно другое: сторонние виджеты - самый частый источник именно такого позднего сдвига, потому что скрипт вставляет себя в DOM по собственному расписанию, а не по расписанию вашей вёрстки.

Чужой код создаёт самые длинные задачи и портит INP

Interaction to Next Paint (INP): время от начала взаимодействия пользователя со страницей - клика, тапа, нажатия клавиши - до момента, когда браузер отрисовывает видимый результат; порог хорошего значения - 200 миллисекунд.

По данным Web Almanac 2024, на медианной странице presentation delay - задержка между завершением обработчика события и отрисовкой кадра - вносит наибольший вклад в INP, и её главная причина - main thread, занятый посторонней работой в момент взаимодействия. Сторонние скрипты вешают собственные глобальные обработчики событий и выполняют тяжёлую инициализацию сразу при загрузке страницы - это происходит до первого клика пользователя и незаметно для команды, которая занимается вёрсткой основного сайта.

Механику длинных задач и три фазы INP мы разбирали отдельно в статье про оптимизацию INP - там фокус на обработчиках событий и гидратации фреймворков. Здесь речь конкретно про сторонний код: он не подчиняется вашим правилам разбивки задач и обычно остаётся самым тяжёлым отдельным источником блокировки main thread на странице.

Сетевой водопад - почему чужие домены отбирают полосу у ваших ресурсов

Каждый новый домен в запросах - это отдельное DNS-разрешение, TCP-соединение и, для HTTPS, TLS-рукопожатие, прежде чем браузер получит хотя бы первый байт файла.

На сайте с десятком сторонних скриптов браузер параллельно устанавливает соединения с десятком разных серверов, конкурируя за ограниченное количество одновременных подключений и за полосу пропускания с вашими собственными критическими ресурсами - шрифтами, CSS, hero-изображением. В итоге собственные файлы сайта могут прийти позже не потому что они большие, а потому что браузер занят установлением связи с чужими доменами.

Увидеть это напрямую можно в водопаде запросов WebPageTest или во вкладке Network в Chrome DevTools: сторонние домены с их отдельными линиями DNS и Connect в начале водопада - явный сигнал, что часть времени до LCP уходит не на ваш контент.

Как правильно загружать сторонний код

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

Атрибут async запускает выполнение скрипта сразу после его скачивания, не дожидаясь остального HTML - подходит для аналитики, которой важно не потерять данные о раннем визите. Атрибут defer откладывает выполнение до конца разбора HTML и сохраняет порядок скриптов - подходит для виджетов, не критичных для первого экрана. Оба варианта не блокируют построение DOM так, как это делает синхронный <script> без атрибутов.

Для по-настоящему второстепенных инструментов - чата поддержки, тепловых карт, виджетов отзывов - работает более агрессивный приём: не грузить скрипт вообще до первого взаимодействия пользователя со страницей (скролла, клика, движения мыши) или до момента простоя браузера через requestIdleCallback. Пользователь видит готовый интерфейс сразу, а тяжёлый код подгружается тогда, когда конкурировать за main thread уже не с чем.

Пример: отложенная загрузка стороннего скрипта до простоя браузера
function loadThirdPartyScript(src) {
  const script = document.createElement('script');
  script.src = src;
  script.async = true;
  document.body.appendChild(script);
}

// Загружаем чат только когда браузер свободен, но не позже 5 секунд
if ('requestIdleCallback' in window) {
  requestIdleCallback(() => loadThirdPartyScript('https://widget.example.com/chat.js'), { timeout: 5000 });
} else {
  setTimeout(() => loadThirdPartyScript('https://widget.example.com/chat.js'), 3000);
}

// Или загружаем по факту первого взаимодействия пользователя
['scroll', 'mousemove', 'touchstart'].forEach((event) => {
  window.addEventListener(event, () => loadThirdPartyScript('https://widget.example.com/chat.js'), { once: true, passive: true });
});

Ещё один рабочий приём для видео, кнопок соцсетей и чатов - facade-паттерн: вместо реального виджета сначала показывается лёгкая статичная заглушка, похожая на настоящий интерфейс, а тяжёлый скрипт подгружается только по клику на неё. Подробное описание паттерна и готовые реализации есть в документации Lighthouse от Chrome для разработчиков.

Тег-менеджер вместо хардкода - контроль порядка загрузки и согласия

Когда каждый отдел вставляет свой скрипт напрямую в шаблон сайта, никто не видит совокупную картину и не может управлять порядком загрузки централизованно.

Тег-менеджер: инструмент, который управляет загрузкой сторонних скриптов через единый контейнер вместо хардкода тегов в код сайта; правила запуска, порядок и условия задаются в интерфейсе, а не правкой шаблона. Это не делает скрипты бесплатными по производительности - тег-менеджер сам по себе тоже JavaScript, - но даёт возможность отложить менее важные теги, привязать запуск к событиям и остановить срабатывание пикселя до согласия пользователя на обработку данных.

Именно согласие - частая причина, по которой скрипты грузятся раньше, чем должны: без централизованного управления баннер согласия и рекламные пиксели независимы друг от друга, и пиксель успевает поставить cookie до клика по баннеру. Правильную последовательность - баннер загружается первым, блокирует некритичные скрипты, и только после явного согласия происходит их инициализация - мы разбирали в техническом чек-листе лендинга для платного трафика применительно к Google Consent Mode и Meta Pixel.

Как провести аудит скриптов на сайте

Прежде чем убирать или откладывать что-либо, нужно точно знать, какой скрипт сколько стоит - на глаз это не определить: разные виджеты выглядят одинаково лёгкими в интерфейсе и совершенно по-разному нагружают main thread.

Вкладка Coverage в Chrome DevTools показывает, какой процент скачанного JavaScript и CSS реально используется на странице - если сторонний файл выполняется на 90% вхолостую, это сигнал, что подключена вся библиотека ради одной функции. Вкладка Performance записывает таймлайн загрузки и подписывает длинные задачи источником скрипта - конкретным доменом и файлом, а не общей меткой “JavaScript”.

Как найти виновника через Chrome DevTools

Откройте DevTools (F12) -> вкладка Performance -> Record. Перезагрузите страницу и выполните типичное взаимодействие - клик по кнопке, открытие фильтра. Остановите запись и найдите на треке Main красные блоки длинных задач: клик по блоку раскрывает Bottom-Up с точным именем функции и файла, который её вызвал.

Второй источник данных - раздел “Уменьшите влияние стороннего кода” в PageSpeed Insights: он показывает список сторонних доменов, вес их файлов и суммарное время блокировки main thread на конкретной странице, по методике аудита Lighthouse.

Для картины по всему сайту, а не одной странице, полезен водопад запросов WebPageTest: он показывает последовательность и параллельность всех запросов, включая сторонние, с точным временем DNS, Connect и временем до первого байта для каждого домена.

Какие скрипты оставить, а какие снять

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

Рабочая рамка для каждого стороннего скрипта на сайте - три вопроса. Кто-то реально смотрит данные тепловой карты последний месяц, или дашборд открыли один раз при подключении и забыли? A/B-тест ещё активен, или эксперимент завершён полгода назад, а скрипт остался в коде? Есть ли инструмент, который выполняет ту же задачу, но уже встроен в используемый тег-менеджер или аналитику, вместо отдельного стороннего домена?

По каждому пункту, где ответ “нет” или “не уверены”, скрипт - кандидат на удаление или как минимум на перевод в отложенную загрузку. На практике заметная часть стороннего кода на сайте старше года - это инструменты, подключённые под конкретную задачу, которая уже закрыта, но никто не заводил задачу на их отключение, потому что удаление скрипта не выглядит приоритетной работой по сравнению с новыми фичами.

Реальный кейс - что изменилось после аудита

В типовом проекте аудита маркетингового сайта B2B-компании (35-50 сотрудников) на странице оказалось четырнадцать сторонних скриптов: два тег-менеджера, оставшихся после смены платформы аналитики, три инструмента тепловых карт разных периодов, брошенный виджет A/B-теста и чат поддержки, инициализирующийся синхронно в <head>.

После инвентаризации восемь скриптов убрали полностью - три оказались дублирующими друг друга по функции, ещё два никто не открывал больше трёх месяцев. Оставшиеся перевели на отложенную загрузку: чат - на facade с запуском по клику, тепловую карту - через requestIdleCallback, аналитику оставили синхронной, но только основной счётчик, а не весь стек тегов.

По полевым данным CrUX через месяц после изменений: INP на мобильных устройствах снизился с 410 до 180 миллисекунд, LCP - с 3,4 до 2,3 секунды, а PageSpeed стабилизировался в диапазоне 85-92 вместо разброса 45-78. Ни одна строка кода на самом сайте не менялась - весь эффект дал только пересмотр стороннего кода.

Для кого это особенно актуально

Сильнее всего накопленный сторонний код бьёт по компаниям, где сайтом одновременно управляют несколько отделов: маркетинг подключает пиксели и тег-менеджеры, продукт ставит инструменты опросов и тепловые карты, поддержка добавляет чат, и ни один из них не согласовывает подключение с разработкой. Это типично для компаний от 15-20 сотрудников, где сайт вырос из простого лендинга в инструмент нескольких команд.

Отдельная категория - сайты, которые недавно переехали на новую платформу или мигрировали с WordPress: старые интеграции часто переносят как есть вместе с контентом, не проверяя, актуальны ли они ещё.

Часто задаваемые вопросы

Сколько сторонних скриптов можно подключить без риска для скорости сайта?

Универсального числа нет - вес одного плохо реализованного тег-менеджера может стоить дороже пяти лёгких скриптов вместе. Ориентир из Web Almanac 2024: медианная страница из топ-1000 сайтов несёт 66 сторонних запросов, но это не цель, а фон, на который стоит смотреть только вместе с фактическим временем блокировки main thread по каждому скрипту.

Можно ли просто удалить тег-менеджер вместо оптимизации отдельных скриптов?

Не всегда - тег-менеджер сам по себе не главная проблема, а инструмент управления. Он становится проблемой, если настроен на синхронную загрузку всех тегов в <head> без разбора приоритета. Правильная альтернатива - не отказ от тег-менеджера, а настройка условий и порядка запуска тегов внутри него, включая привязку к согласию пользователя.

Как понять, что именно чат-виджет портит INP, а не что-то ещё?

Во вкладке Performance в Chrome DevTools длинные задачи подписаны источником - доменом и файлом скрипта, который их вызвал. Если после записи типичного взаимодействия большая часть красных блоков привязана к домену чат-виджета, а не к вашему коду, причина установлена точно, без предположений.

Стоит ли отказываться от тепловых карт и записи сессий ради скорости?

Не обязательно полностью, но стоит проверить, реально ли данные используются. По данным Web Almanac 2024, страницы со скриптами категории “User Behavior” - тепловые карты и запись сессий - показывают хороший INP только на 37% мобильных визитов, заметно хуже, чем в среднем по сайту. Если инструмент даёт реальные инсайты команде, его стоит оставить, но перевести на отложенную загрузку через requestIdleCallback, а не грузить синхронно.

Как часто нужно повторять аудит сторонних скриптов?

Практический ориентир - раз в квартал или после любого крупного изменения в маркетинговом стеке: новая рекламная платформа, смена виджета поддержки, запуск нового A/B-теста. Один забытый скрипт, который никто не отключил после завершения эксперимента, может месяцами тянуть показатели вниз незаметно для команды.

Что стоит сделать в первую очередь:

  • Открыть вкладку Performance в Chrome DevTools и найти длинные задачи, подписанные конкретным сторонним доменом
  • Перевести некритичные виджеты - чат, тепловые карты, опросы - на facade-загрузку или запуск после первого взаимодействия
  • Свести все сторонние теги в один тег-менеджер с привязкой к согласию пользователя вместо хардкода в шаблон
  • Провести инвентаризацию раз в квартал и задавать по каждому скрипту вопрос, кто реально смотрит его данные

Если PageSpeed на вашем сайте скачет от визита к визиту, а на странице скопилось больше десятка сторонних тегов - опишите задачу команде Exceltic.dev. Проведём аудит стороннего кода, найдём конкретные источники длинных задач и предложим план по отложенной загрузке без потери функциональности. Это часть разработки и оптимизации сайтов, которой занимается Exceltic.dev.

Ещё статьи

Все →