Перейти к содержимому

Язык

Разработка5 мин чтения

Баннеры cookie и Core Web Vitals: как удержать LCP, CLS и INP в норме

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

Редакция CookieshОпубликовано

Баннер cookie может ухудшить все три метрики Core Web Vitals: он может задержать отрисовку самого крупного элемента (Largest Contentful Paint, LCP) или сам стать им, сдвигать содержимое и повышать совокупный сдвиг макета (Cumulative Layout Shift, CLS), а также делать кнопку «Принять» медлительной, что отражается на задержке до следующей отрисовки (Interaction to Next Paint, INP). Способы исправления известны: загружайте скрипт согласия асинхронно, показывайте баннер как фиксированный оверлей, откладывайте второстепенный интерфейс и делайте обработчики кликов легкими.

Баннер часто оказывается первым, что видит новый посетитель, и состоит он из JavaScript, CSS и текста, которые конкурируют с вашим основным контентом за пропускную способность и время основного потока. Core Web Vitals измеряют именно эту конкуренцию, причем оценка ведется по 75-му процентилю реальных загрузок страниц.

Метрика Что она измеряет Порог «хорошо» Как баннер может ее ухудшить
LCP Момент отрисовки самого крупного изображения или текстового блока 2,5 с или меньше Скрипт согласия, блокирующий отрисовку, или сам баннер, ставший самым крупным элементом
CLS Насколько сильно видимое содержимое неожиданно смещается 0,1 или меньше Баннер, вставленный в поток страницы и сдвигающий содержимое вниз
INP Насколько быстро страница реагирует на клики, касания и нажатия клавиш 200 мс или меньше Тяжелая работа в обработчике кнопки «Принять» или «Отклонить»

В марте 2024 года INP заменил метрику First Input Delay (FID), и для согласия это важно. FID измерял только задержку перед обработкой первого взаимодействия; INP измеряет полное время от любого взаимодействия до следующего кадра, а «Принять все» часто становится первым, на что нажимает посетитель.

Как не дать скрипту согласия заблокировать LCP?

Загружайте его с атрибутом async и делайте его компактным. Синхронный скрипт в <head> останавливает парсер HTML, пока не загрузится и не выполнится, а это задерживает заголовок и главное изображение вместе со всем остальным.

<head>
  <script src="https://consent.example.com/loader.js" async></script>

  <!-- Неактивен, пока скрипт согласия не включит его после получения согласия -->
  <script type="text/plain" data-consent="analytics"
          src="https://analytics.example.com/script.js"></script>
</head>

Асинхронная загрузка безопасна, если необязательные теги неактивны, как в этом примере: ничего не выполняется, пока скрипт согласия этого не разрешит. Подходы с «автоблокировкой», которые перехватывают скрипты по мере их добавления, обычно должны выполняться синхронно раньше всех остальных скриптов, а это стоит времени отрисовки. Методы сравниваются в нашем руководстве о том, как блокировать скрипты до получения согласия.

Вторая ловушка для LCP — сам баннер. LCP фиксирует самое крупное изображение или текстовый блок, отрисованный в области просмотра до взаимодействия посетителя со страницей. На небольшом телефоне баннер с длинным абзацем может оказаться больше вашего заголовка, и если он отрисовывается поздно, поздно наступает и LCP. Делайте текст первого уровня лаконичным, используйте системный шрифт, чтобы баннер никогда не ждал загрузки веб-шрифта, и никогда не выводите баннер в виде изображения.

Откладывать показ баннера бесполезно: поздний баннер все равно может стать элементом LCP, просто позже.

Как не дать баннеру вызывать сдвиги макета?

Показывайте его как фиксированный оверлей. CLS учитывает смещение уже существующего содержимого, поэтому элемент с position: fixed, появляющийся поверх страницы, ничего не сдвигает. Классическая ошибка — панель, вставляемая в начало <body> после первой отрисовки, которая сдвигает вниз всю страницу.

.consent-banner {
  position: fixed;
  inset: auto 0 0 0; /* закреплен внизу, вне потока документа */
  z-index: 1000;
  font: 1rem/1.5 system-ui, sans-serif; /* не нужно ждать веб-шрифт */
  animation: consent-in 200ms ease-out;
}

@keyframes consent-in {
  from { transform: translateY(100%); }
}

@media (prefers-reduced-motion: reduce) {
  .consent-banner { animation: none; }
}

Если используете анимацию, анимируйте transform или opacity. Анимация top, height или margin меняет макет и может засчитываться как сдвиг. Если дизайн действительно требует баннера в потоке документа, резервируйте под него место в HTML, отрисованном на сервере, — но это хорошо работает, только если сервер считывает файл cookie согласия и не резервирует место для вернувшихся посетителей.

Продумайте и то, что происходит после получения согласия. Сдвиги в течение 500 мс после клика или нажатия клавиши не учитываются в CLS, а вот рекламный блок, встроенное видео или виджет чата, загружающиеся через несколько секунд, учитываются. Задайте таким контейнерам фиксированные размеры или aspect-ratio.

Как отложить интерфейс баннера, не нарушая требований?

Отдавайте первый уровень сразу, а центр настроек загружайте по требованию. Первый уровень — это короткое сообщение и несколько кнопок; второй уровень с переключателями категорий, списками поставщиков и таблицами файлов cookie обычно и составляет основной вес.

Откладывать нельзя сам выбор. Кнопке «Отклонить все» место на первом уровне, причем с той же заметностью, что и у «Принять все». В декабре 2021 года французский регулятор CNIL оштрафовал Google на 150 млн евро, а Facebook — на 60 млн евро, потому что отказаться от файлов cookie было сложнее, чем принять их. Подробнее читайте в статьях темные паттерны в баннерах cookie и лучшие практики дизайна баннеров.

Как сохранить отзывчивость кнопок «Принять» и «Отклонить» для INP?

Делайте минимум до следующей отрисовки, а затем уступайте поток. Медленный обработчик обычно в рамках одной длинной задачи записывает файл cookie согласия, отправляет запись в журнал согласий, обновляет Google Consent Mode и внедряет несколько скриптов поставщиков, поэтому кнопка выглядит зависшей.

function yieldToMain() {
  if (globalThis.scheduler?.yield) return globalThis.scheduler.yield();
  return new Promise((resolve) => setTimeout(resolve, 0));
}

acceptButton.addEventListener('click', async () => {
  banner.remove();                                    // 1. сначала видимая реакция
  saveConsent({ analytics: true, marketing: true });  // 2. быстро и синхронно
  await yieldToMain();                                // 3. даем браузеру отрисовать кадр
  activateTags(['analytics', 'marketing']);           // 4. тяжелая работа в следующей задаче
});

customizeButton.addEventListener('click', async () => {
  customizeButton.setAttribute('aria-busy', 'true');
  const { openPreferences } = await import('./preference-center.js'); // загружается по требованию
  openPreferences();
});

Отправляйте запись в журнал согласий с помощью navigator.sendBeacon(), чтобы сетевые операции никогда не задерживали взаимодействие, а большое количество тегов активируйте пакетами, уступая поток между ними. scheduler.yield() пока поддерживается не во всех браузерах, поэтому нужен запасной вариант.

Как протестировать влияние баннера?

Тестируйте сначала как новый посетитель, а затем как вернувшийся. Лабораторные инструменты вроде Lighthouse запускаются с пустым хранилищем, поэтому всегда видят баннер:

  1. Откройте страницу в новом профиле браузера из региона, где показывается баннер.
  2. Запустите Lighthouse или PageSpeed Insights и проверьте, какой элемент определен как элемент LCP.
  3. Запишите трассировку на панели Performance в Chrome DevTools, нажмите «Принять все» и поищите длинные задачи после клика.
  4. В той же трассировке проверьте сдвиги макета во время появления баннера и после загрузки тегов.
  5. Повторите тест как вернувшийся посетитель с сохраненным согласием, ведь в этом случае срабатывает больше тегов.
  6. Затем сравните полевые данные в Search Console или PageSpeed Insights; они охватывают скользящее окно в 28 дней, поэтому изменения проявляются постепенно.

Итоги

Баннер согласия не обязан ухудшать Core Web Vitals. Загружайте его асинхронно, держите вне потока документа, откладывайте тяжелый второй уровень и делайте обработчики кликов легкими, сохраняя при этом одинаковую простоту всех вариантов выбора. Такие инструменты, как Cookiesh, могут взять на себя загрузку: асинхронный загрузчик весит меньше 5 КБ в сжатом gzip виде, раздается через глобальную граничную CDN и спроектирован так, чтобы не вызывать сдвигов макета.

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

Частые вопросы

Улучшит ли Core Web Vitals скрытие баннера от Lighthouse?

Нет. Оценка Core Web Vitals в Google основана на полевых данных реальных пользователей Chrome, многие из которых видят ваш баннер. Скрывая его от лабораторных инструментов, вы скрываете проблему только от себя, а если отдавать тестовым инструментам другую страницу, диагностика становится ненадежной.

Что лучше для производительности: панель внизу экрана или модальное окно по центру?

Оба варианта не вызывают сдвигов макета, если используют фиксированное позиционирование. Большое модальное окно занимает больше области просмотра и на мобильных устройствах с большей вероятностью будет определено как элемент LCP, поэтому компактная панель внизу обычно безопаснее для производительности — при условии, что все варианты выбора в ней одинаково заметны.

Стоит ли отдельно измерять Core Web Vitals для посетителей, которые уже дали согласие?

Это полезно. Вернувшиеся посетители не видят баннер, но у них срабатывает больше тегов, поэтому их профиль загрузки и отзывчивости отличается от профиля новых посетителей. Сегментация измерений покажет, какая группа требует доработки, но помните, что отправка данных мониторинга реальных пользователей третьей стороне сама по себе может требовать согласия.

Источники

  1. web.dev: Web Vitals
  2. Directive 2002/58/EC (ePrivacy Directive), EUR-Lex
  3. EDPB Guidelines 05/2020 on consent

Редакция Cookiesh

Инженеры по защите данных и специалисты по комплаенсу пишут практические руководства о согласии, файлах cookie и защите данных для продуктовых команд.

Запускайте баннеры cookie по всем правилам — за минуты, а не за спринты

Начните бесплатно с одним доменом. Переходите на платный тариф, когда понадобятся дополнительные домены, геотаргетинг или собственный брендинг.

Без привязки карты · Отмена в любой момент