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

Интеграция JavaScript SDK (Client)

HashEntry CMP SDK — это скрипт без зависимостей, который показывает баннер cookie, блокирует помеченные вами скрипты до тех пор, пока посетитель их не разрешит, и записывает каждое решение на сервере HashEntry. Он также может записывать одобрения документов (условия, договоры, политики) — см. Одобрение и подписание документов.

На этой странице описано, что SDK делает на сегодняшний день. Там, где поведение зависит от настройки в панели управления или от вашей собственной разметки, это указано.


<head>
<script
src="https://tool.hashentry.com/cmp.js"
data-site="YOUR_SITE_API_KEY"
async
></script>
</head>

SDK загружает с сервера конфигурацию, привязанную к вашему API-ключу (дизайн баннера, тексты, категории, документы, настройки поведения), и решает, нужен ли баннер этому посетителю.

Чтобы решение о cookie могло быть записано на сервере, должны быть выполнены два условия:

  1. Сайт подтверждён в панели управления. Запросы для неподтверждённого сайта отклоняются с 403 SITE_NOT_VERIFIED.
  2. К сайту прикреплён документ политики cookie. См. следующий раздел.

Согласие на cookie записывается только в том случае, если оно ссылается на точную активную версию документа типа cookie_policy, прикреплённого к сайту. Принятая версия политики является частью доказательства, поэтому SDK не смягчает это правило.

  • Если к сайту не прикреплена опубликованная политика cookie, SDK не показывает баннер (а также виджет и ссылку «Do Not Sell») и во всех регионах оставляет заблокированными все помеченные необязательные скрипты: выбор, который нельзя сохранить как доказательство, не собирается. События consent:error и error срабатывают с code: "COOKIE_POLICY_MISSING", а ошибка выводится в консоль браузера. CMP.accept() / CMP.reject() завершаются с success: false, error.code = "COOKIE_POLICY_MISSING" и pending_sync: false; ничего не сохраняется, не применяется и не ставится в очередь. Как только политика будет прикреплена, баннер появится при следующей загрузке страницы, и посетитель примет решение по этой версии. Согласие, записанное в то время, когда политика была прикреплена, остаётся действительным.
  • Решение никогда не удерживается, чтобы позже быть отправленным с версией политики, которую посетитель не видел. Если предыдущая версия SDK оставила такое решение в локальной очереди, оно отбрасывается (consent:error с final: true, reprompt: true), и посетителя спрашивают снова.
  • Единственное исключение — режим local без data-site: на сервер ничего не отправляется, поэтому баннер показывается, а решения остаются в браузере (local_only: true).
  • Если согласие ссылается на версию, которая не является активной, сервер отвечает 409 CONFIG_OUTDATED. См. Повторное согласие и изменившиеся версии документов.

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


Блокируются только те скрипты, которые вы пометили. SDK не сканирует страницу в поисках трекеров и не перехватывает скрипты, которые вы оставили без изменений: обычный тег <script> выполняется сразу, с согласием или без него.

Чтобы придержать скрипт, измените его type на text/plain и укажите его категорию:

<!-- Встроенный скрипт: выполняется только после того, как разрешена категория "analytics" -->
<script type="text/plain" data-cookie-category="analytics">
/* фрагмент кода аналитики */
</script>
<!-- Внешний скрипт: используйте data-src вместо src -->
<script type="text/plain" data-cookie-category="marketing"
data-src="https://connect.facebook.net/en_US/fbevents.js"></script>
  • Названия категорий должны совпадать с ключами категорий вашего баннера (analytics, marketing, preferences или ваши собственные ключи). Скрипты с пометкой necessary активируются сразу, до загрузки конфигурации.
  • Помеченные скрипты, которые добавляются на страницу позже (навигация в SPA, внедрение тегов), также обрабатываются.
  • Скрипт, который уже выполнился, остановить нельзя. Когда посетитель отзывает категорию, скрипты которой выполнились на текущей странице, SDK удаляет известные cookie этой категории и по умолчанию перезагружает страницу (см. reload_on_revoke).
  • При отзыве категории SDK удаляет cookie и записи хранилища, перечисленные для этой категории в конфигурации вашего баннера, а также небольшой встроенный список широко известных имён. Cookie, о которых он не знает, не удаляются, а сторонние cookie на других доменах удалить с вашей страницы невозможно.

АтрибутПо умолчаниюОписание
data-site—API-ключ сайта. Обязателен в режиме remote; в остальных режимах он также нужен, чтобы решения записывались на сервере.
data-modelocal-fallbackИсточник конфигурации: remote, local, local-fallback. См. Режимы работы.
data-languageautoЯзык баннера. auto использует <html lang>, затем язык браузера.
data-regionautoПринудительно задаёт регион или правовой режим (DE, US, gdpr, ccpa, none, …) вместо определения. Это регион соответствия (каким правилам следует баннер); он не определяет, где хранятся данные и какой хост API вызывается.
data-config—Встроенная JSON-конфигурация (для local / local-fallback).
data-debugfalsetrue выводит отладочные сообщения. Ошибки и предупреждения всегда выводятся в консоль.
data-headlessfalsetrue не отображает никакого интерфейса (баннер, виджет, ссылка «Do Not Sell»). См. Режим headless.
data-consent-modeнастройка панели управленияtrue / false принудительно включает или выключает Google Consent Mode v2. См. Google Consent Mode v2.
data-reload-on-revokeнастройка панели управленияtrue / false переопределяет флаг поведения reload_on_revoke.
data-modules—Модули, которые нужно загрузить заранее, например documents, preferences. См. Файлы сборки и модули по требованию.
data-module-baseпапка самого скриптаБазовый URL, с которого загружаются файлы модулей. Нужен только тогда, когда они размещены не рядом с cmp.js.
data-api-urlAPI HashEntryБазовый URL API для first-party прокси или собственного домена. Если у региона данных вашей учётной записи есть собственный хост API, ответ конфигурации сообщает его (api_base_url), и SDK использует его для всех последующих вызовов; код установки, сформированный в панели, уже содержит соответствующий data-api-url. Значение, заданное вами здесь, всегда имеет приоритет.

window.CMP существует сразу после выполнения скрипта. Методы, которые что-либо записывают, возвращают промис с объектом результата; они не выбрасывают исключений.

CMP.ready(() => { /* конфигурация загружена, состояние согласия определено */ });
// Баннер
CMP.show(); // открыть баннер (например, по ссылке в подвале)
CMP.hide();
// Решения — каждый метод возвращает Promise<ConsentResult>
CMP.accept(); // разрешить все категории
CMP.accept({ marketing: false }); // разрешить все, кроме marketing
CMP.reject(); // только необходимые
CMP.withdraw(); // отозвать сохранённое согласие
// Состояние
CMP.getConsent(); // ConsentState или null
CMP.hasConsent('analytics'); // boolean ("necessary" всегда true)
// Язык
CMP.setLanguage('de');
CMP.getLanguage();
CMP.setLocale('de', { ccpa: { optOut: 'Widersprechen' } }); // тексты для одного языка
// Метаданные: добавляются к каждому согласию и одобрению, записанному после этого
CMP.setMetadata({ order_id: 'ORD-54321' });
CMP.setMetadata('customer_id', 'CUST-999');
CMP.getMetadata();
// Переопределение региона, тема, URL API, локальная конфигурация
CMP.setRegion('DE');
CMP.setTheme({ primaryColor: '#0F766E' });
CMP.setApiUrl('/hashentry-api');
CMP.getApiUrl();
CMP.setConfig({ banner_config: { /* … */ } });
// События
CMP.on('consent:given', (payload) => {});
CMP.off('consent:given', handler);
// Документы (загружаются по требованию — см. «Одобрение и подписание документов»)
CMP.showDocumentApproval('terms-of-service', { language: 'en' });
CMP.approveDocument('terms-of-service', { /* … */ });

Отзыв выключает все необязательные категории, удаляет известные cookie этих категорий, переводит Google Consent Mode в denied, отправляет на сервер решение withdrawn (если согласие было сохранено), удаляет сохранённое согласие из браузера и — в регионах с моделью opt-in — снова показывает баннер. Если скрипты отозванной категории уже выполнились на странице, страница перезагружается, если только reload_on_revoke не выключен.

Меняет язык открытого баннера и заново загружает конфигурацию для этого языка, поскольку версии документов привязаны к языку: последующие согласия будут ссылаться на версию политики cookie для нового языка. Если у баннера нет перевода на этот язык, используется язык баннера по умолчанию.

Значения объединяются и отправляются как metadata с каждым последующим решением о cookie и одобрением документа. Сервер принимает не более 30 ключей и примерно 16 КБ метаданных на запись.

<script>
window.__CMP_QUEUE = window.__CMP_QUEUE || [];
window.__CMP_QUEUE.push(['setLanguage', 'de']);
window.__CMP_QUEUE.push(['setMetadata', { order_id: 'ORD-12345' }]);
window.__CMP_QUEUE.push(['on', 'consent:given', (p) => console.log(p)]);
</script>

Вызовы из очереди выполняются по порядку при запуске SDK. Язык, заданный таким способом, не переопределяется автоматическим определением.


{
success: true,
consent_token: 'ct_…',
proof_hash: '…', // 64 шестнадцатеричных символа
created_at: '2026-10-10T10:00:00+00:00',
idempotency_key: '…' // один UUID на действие пользователя, используется повторно при каждой повторной попытке
}

success равен true только тогда, когда сервер принял запись. В противном случае:

{
success: false,
consent_token: '',
proof_hash: '',
created_at: '…',
error: { code: 'NETWORK_ERROR', status: 0, message: '…' },
pending_sync: true, // хранится в локальной очереди, отправка будет повторена
idempotency_key: '…'
}
  • error.code — это машинный код сервера или один из кодов SDK, перечисленных ниже; error.status — HTTP-статус (0, если ответ не был получен).
  • pending_sync: true означает, что решение применено в браузере и ожидает в локальной очереди (localStorage). Отправка повторяется при следующей загрузке страницы, когда вкладка снова становится видимой и когда браузер снова выходит в сеть, всегда с тем же idempotency_key, в течение не более 7 дней или 12 попыток.
  • local_only: true появляется, когда отправлять нечего (например, режим local без data-site).

Выбор посетителя в любом случае применяется в браузере немедленно; результат сообщает вам, есть ли запись о нём на сервере. Исключение — COOKIE_POLICY_MISSING: решение не сохраняется и не применяется.

{ success: true, decision: 'accepted', consent_token: 'ct_…', proof_hash: '…', slug: 'terms-of-service', version: '2.0.0' }
{ success: false, slug: 'terms-of-service', version: '2.0.0', error: { code: 'DOCUMENT_VERSION_CHANGED', status: 409, message: '…' } }

Одобрения документов никогда не ставятся в очередь на потом: если success не равен true, одобрение не записано.


СобытиеДанные событияКогда
ready{}Запуск завершён (в том числе когда конфигурацию не удалось загрузить).
banner:shown{ type } или { headless: true, reason, config }Баннер был показан или — в режиме headless — должен быть показан вами.
banner:hidden{ reason } или { headless: true }Баннер был закрыт.
consent:given{ decision, categories, source }Решение, отличное от «отклонить все», сохранено локально.
consent:rejected{ decision, categories, source }Решение «отклонить все» сохранено локально.
consent:changed{ oldCategories, newCategories }Решение заменило более раннее.
consent:withdrawn{ categories, cleanedCookies }Был вызван CMP.withdraw().
consent:synced{ consent_token, idempotency_key }Сервер принял запись (сразу или из очереди).
consent:error{ code, status, message, idempotency_key, pending_sync, final?, reprompt? }Запись не удалось доставить. final: true означает, что она была отброшена.
document:approved{ slug, version, consentId }Одобрение документа было записано.
document:rejected{ slug, version }Посетитель отклонил документ.
document:error{ slug, version, code, status, message }Документ не удалось загрузить или одобрение не было записано.
scripts:activated{ category, count }Помеченные скрипты категории были активированы.
config:updated{ content_hash }Более новая конфигурация заменила кешированную.
language:changed{ from, to }Язык изменился.
error{ scope, code, status, message, … }Любая из перечисленных выше ошибок; scope принимает значения config, consent, module или document.

consent:given / consent:rejected срабатывают, когда решение сохранено в браузере. Используйте consent:synced (или результат промиса), когда вам нужно знать, что оно есть на сервере.


Коды, которые формирует сам SDK:

КодЗначение
NOT_READYМетод принятия решения был вызван до загрузки конфигурации. Вызывайте его внутри CMP.ready().
COOKIE_POLICY_MISSINGК сайту не прикреплён опубликованный документ политики cookie. Баннер не показывается, необязательные скрипты остаются заблокированными, а решение не сохраняется и не ставится в очередь.
NETWORK_ERROR, TIMEOUTНет ответа от API (тайм-аут: 5 с на попытку).
HTTP_<status>Сервер ответил ошибкой, не содержащей машинного кода.
DOCUMENT_VERSION_CHANGEDУказанная версия документа больше не является активной; запись была отброшена.
PENDING_EXPIREDРешение из очереди не удалось доставить в течение 7 дней, и оно было отброшено.
MODULE_LOAD_FAILEDНе удалось загрузить файл модуля (documents или preferences). Также сообщается через событие error с scope: "module".
APPROVAL_TOKEN_REQUIREDДокумент требует одноразового токена одобрения, а токен не был передан (этот код возвращает и сервер).
CONFIG_UNAVAILABLEКонфигурацию не удалось загрузить (сообщается через событие error).
UNEXPECTED_ERRORВсё остальное.

Коды, возвращаемые сервером, передаются без изменений. Наиболее важные из них перечислены на странице REST API — например, CONFIG_OUTDATED, SITE_NOT_VERIFIED, ORIGIN_NOT_ALLOWED, RATE_LIMIT_EXCEEDED, CONSENT_LIMIT_EXCEEDED, APPROVAL_TOKEN_INVALID.

Временные ответы сервера. 503 (API_KEY_LOOKUP_UNAVAILABLE, ADMISSION_UNAVAILABLE, QUEUE_OVERLOADED) и 429 RATE_LIMIT_EXCEEDED автоматически повторяются с тем же idempotency_key; SDK ожидает время, указанное в заголовке Retry-After. Если это время превышает 5 секунд, SDK не ждёт на странице: решение остаётся в локальной очереди (pending_sync: true) и отправляется позже. После 429 TOO_MANY_INVALID_API_KEYS SDK не отправляет других запросов в течение этого просмотра страницы, а решения в очереди сохраняются; проверьте значение data-site. Ни один из этих ответов не влияет на вашу страницу: срабатывает событие error, а обратные вызовы CMP.ready() всё равно выполняются.

Заголовок раздела «Временные ответы сервера. 503 (API_KEY_LOOKUP_UNAVAILABLE, ADMISSION_UNAVAILABLE, QUEUE_OVERLOADED) и 429 RATE_LIMIT_EXCEEDED автоматически повторяются с тем же idempotency_key; SDK ожидает время, указанное в заголовке Retry-After. Если это время превышает 5 секунд, SDK не ждёт на странице: решение остаётся в локальной очереди (pending_sync: true) и отправляется позже. После 429 TOO_MANY_INVALID_API_KEYS SDK не отправляет других запросов в течение этого просмотра страницы, а решения в очереди сохраняются; проверьте значение data-site. Ни один из этих ответов не влияет на вашу страницу: срабатывает событие error, а обратные вызовы CMP.ready() всё равно выполняются.»

Повторное согласие и изменившиеся версии документов

Заголовок раздела «Повторное согласие и изменившиеся версии документов»

Когда баннер показывается снова. Сохранённое согласие запоминает хеш содержимого конфигурации баннера, для которой оно было дано. Баннер показывается снова, когда:

  • срок действия согласия истёк (срок действия задаётся в панели управления),
  • изменилась структура категорий / cookie баннера или
  • была опубликована новая версия прикреплённого документа — если только настройка баннера reconsent_on_doc_change не выключена; в этом случае повторное согласие запрашивается только при изменениях структуры.

Пока в регионе с моделью opt-in ожидается повторное согласие, предыдущий выбор посетителя остаётся в силе до тех пор, пока он не примет решение снова.

Ожидающие решения и изменившаяся версия документа. Если решение не удалось доставить (нет сети, страница закрыта, ошибка сервера) и при повторной отправке версия документа, на которую оно ссылается, уже не является активной, SDK:

  1. запрашивает у сервера текущую конфигурацию в обход кеша;
  2. если версия не изменилась (ответ 409 был вызван холодным кешем сервера), отправляет ту же запись ещё один раз;
  3. если версия изменилась, отбрасывает запись, удаляет локально сохранённое согласие и снова показывает баннер (consent:error с code: "DOCUMENT_VERSION_CHANGED", final: true, reprompt: true).

Ожидающая запись никогда не отправляется повторно с другой версией документа: посетитель этой версии не видел.


Регионы, профили регулирования и флаги поведения

Заголовок раздела «Регионы, профили регулирования и флаги поведения»

Регион посетителя определяется в следующем порядке: CMP.setRegion() → data-region → результат GeoIP сервера в ответе с конфигурацией (detected_region) → оценка по часовому поясу браузера → фиксированный режим регулирования баннера → самые строгие правила (GDPR). SDK никогда не обращается к сторонним сервисам геолокации.

РегионПравовой режимМодельПоведение
ЕС / ЕЭЗ, Швейцарияgdpropt-inБаннер; помеченные скрипты заблокированы, пока не разрешены.
Турцияkvkkopt-inТак же, как для GDPR.
Великобританияuk_gdpropt-inТак же, как для GDPR (см. uk_analytics_exemption).
Бразилияlgpdopt-inТак же, как для GDPR.
ЮАР, Канада, Китай, Южная Кореяpopia, pipeda, pipl, pipaopt-inПрименяются правила баннера GDPR.
СШАccpa — только если включено, иначе gdpropt-out / opt-inСм. ccpa_opt_out_enabled.
Неизвестноgdpropt-inСамые строгие правила.
none (явно)none—Без баннера; все скрипты выполняются.

В каждом профиле opt-in у баннера всегда есть кнопка «Отклонить» с тем же визуальным весом, что и у кнопки «Принять», и ни одна необязательная категория не выбрана заранее — независимо от того, что задано в дизайне баннера.

Это поведение меняют три флага поведения (баннер → настройки поведения в панели управления, banner_config.behavior в локальной конфигурации):

ФлагПо умолчаниюЭффект
uk_analytics_exemptionвыключенТолько для посетителей из Великобритании: скрипты с пометкой analytics могут выполняться до принятия решения. Для любой другой категории согласие по-прежнему необходимо, а после того как посетитель принял решение, применяется его решение.
ccpa_opt_out_enabledвыключенПосетители, определённые как находящиеся в США, получают модель opt-out: скрипты выполняются по умолчанию, показывается ссылка «Do Not Sell or Share My Personal Information», а сигнал Global Privacy Control применяется один раз как opt-out (consent_type: do_not_sell_opt_out). Когда флаг выключен, посетители из США получают баннер opt-in.
reload_on_revokeвключёнПерезагружать страницу, когда посетитель отзывает категорию, скрипты которой уже выполнились на этой странице. Выключайте его, только если ваши теги сами реагируют на изменения согласия.

Когда Consent Mode включён, SDK создаёт window.dataLayer и функцию gtag, если их ещё нет, и отправляет:

  1. gtag('consent', 'default', { …all denied…, wait_for_update: 500 }) во время запуска,
  2. gtag('consent', 'update', { … }) после каждого решения и при каждой загрузке страницы с сохранённым согласием.
СигналПолучает значение granted, когда разрешена эта категория
ad_storage, ad_user_data, ad_personalizationmarketing
analytics_storageanalytics
functionality_storage, personalization_storagepreferences
security_storageвсегда

SDK также отправляет в data layer события hashentry_consent_default и hashentry_consent_update.

Настройка:

  1. Включите Google Consent Mode для баннера в панели управления или добавьте data-consent-mode="true" в тег скрипта.
  2. Разместите тег скрипта HashEntry выше вашего тега Google / фрагмента GTM.
  3. Если команда default должна предшествовать тегам Google при самом первом просмотре страницы посетителем, используйте data-consent-mode="true" и загружайте cmp.js без async. Настройка панели управления приходит вместе с конфигурацией, которая при первом посещении загружается асинхронно; при последующих посещениях она читается из кешированной конфигурации во время запуска.

Consent Mode только отправляет сигналы. Теги, которые не управляются Consent Mode, по-прежнему нужно помечать для блокировки, как описано выше.


С data-headless="true" SDK ничего не отображает. Он по-прежнему загружает конфигурацию, блокирует помеченные скрипты, обновляет Consent Mode и записывает решения.

CMP.on('banner:shown', ({ headless, reason, config }) => {
if (headless) openMyBanner(config); // reason: no_consent | expired | reconsent | withdrawn | api | opt_out
});
myAcceptButton.onclick = async () => {
const result = await CMP.accept({ analytics: true, marketing: false });
if (!result.success && !result.pending_sync) showError(result.error);
};

РежимИсточник конфигурации
remoteТолько сервер. data-site обязателен.
localТолько страница (CMP.setConfig, data-config или <script type="application/json" id="cmp-config">).
local-fallback (по умолчанию)Сервер; если он недоступен — конфигурация страницы.

Режим определяет только то, откуда берётся конфигурация. Решения отправляются на сервер в любом режиме, пока задан data-site. В режиме local без data-site решения хранятся только в браузере (local_only: true).

Локальная конфигурация имеет ту же структуру, что и ответ сервера:

<script type="application/json" id="cmp-config">
{
"banner_config": {
"layout": "bottom_bar",
"theme": { "primary_color": "#2563EB", "font_family": "system", "theme_mode": "auto" },
"behavior": { "show_widget": true, "show_reject_button": true, "show_settings_button": true },
"categories": [
{ "key": "necessary", "required": true, "default": true },
{ "key": "analytics", "required": false, "default": false,
"cookies": [{ "name": "_ga", "provider": "Google", "type": "cookie", "duration": "2 years" }] }
],
"languages": {
"default": "en",
"translations": {
"en": {
"title": "Cookie preferences",
"description": "We use cookies to measure how the site is used.",
"accept_button_text": "Accept all",
"reject_button_text": "Reject all",
"settings_button_text": "Manage preferences",
"save_selected_text": "Save selection",
"modal_title": "Cookie settings",
"always_active_text": "Always active",
"categories": {
"necessary": { "label": "Necessary", "description": "Required for the site to work." },
"analytics": { "label": "Analytics", "description": "Visitor statistics." }
}
}
}
}
}
}
</script>
<script src="https://tool.hashentry.com/cmp.js" data-site="YOUR_SITE_API_KEY" data-mode="local" async></script>

Если задан data-site, SDK при запуске один раз запрашивает у сервера документ политики cookie, поскольку согласие должно ссылаться на его версию. Если политика не прикреплена, баннер не показывается (COOKIE_POLICY_MISSING). Чтобы показывать баннер даже при недоступности сервера, включите documents (политику cookie и её версию) в конфигурацию на странице.


Все тексты баннера (заголовок, описание, кнопки, названия категорий) берутся из конфигурации баннера — они не являются частью скрипта.

SDK поставляется с небольшим встроенным словарём, только на английском и турецком языках, для текстов, относящихся к его собственному интерфейсу: диалог «Do Not Sell», кнопки и строка ошибки одобрения документа, заголовки таблицы cookie и кнопка закрытия. На любом другом языке эти тексты отображаются на английском, если вы не зададите их сами:

CMP.setLocale('de', {
document: { approve: 'Ich stimme zu', reject: 'Ablehnen', saving: 'Wird gespeichert…', error: 'Ihre Zustimmung konnte nicht gespeichert werden. Bitte versuchen Sie es erneut.' },
ccpa: { link: '…', description: '…', cancel: 'Abbrechen', optOut: 'Widersprechen' },
cookies: { name: 'Name', provider: 'Anbieter', type: 'Typ', duration: 'Dauer', purpose: 'Zweck', category: 'Kategorie', count: '{n} Cookies', empty: 'Keine Cookies registriert.' }
});

Конфигурация может содержать те же ключи для каждого языка в languages.translations.<lang>.sdk_texts.


ФайлСодержимоеЧем загружается
cmp.jsЯдро и согласие на cookieВашим тегом скрипта.
cmp-documents.<hash>.jsОдобрение документов (showDocumentApproval, approveDocument)Скриптом cmp.js, при первом вызове одного из этих методов.
cmp-preferences.<hash>.jsЦентр настроек, таблица сведений о cookie, диалог подтверждения «Do Not Sell»Скриптом cmp.js, когда посетитель впервые открывает одно из них.

Вы никогда не добавляете второй тег скрипта. Сайт, который использует только баннер cookie, никогда не скачивает модуль документов.

  • Файл модуля запрашивается из того же расположения, что и cmp.js (оно определяется по src скрипта).
  • Чтобы избежать короткой задержки при первом вызове, загрузите модуль заранее: data-modules="documents".
  • Вызовы, сделанные до того, как модуль загрузился, просто ожидают его. Если модуль не удаётся загрузить, метод завершается с success: false и error.code = "MODULE_LOAD_FAILED"; следующий вызов предпринимает новую попытку.
  • Если модуль preferences не удаётся загрузить, баннер остаётся на экране с кнопками принятия и отклонения, срабатывает событие error с scope: "module" и code: "MODULE_LOAD_FAILED", а следующий клик предпринимает новую попытку. Чтобы центр настроек открывался без задержки, загрузите модуль заранее: data-modules="preferences".
  • Имя файла содержит хеш содержимого, который встраивается в cmp.js во время сборки, поэтому cmp.js всегда запрашивает модуль, собранный вместе с ним.

Content Security Policy. Модуль загружается с помощью элемента <script> с того же источника (origin), что и cmp.js; SDK не использует ни eval, ни встроенные скрипты. Для скриптов достаточно указать источник SDK:

script-src https://tool.hashentry.com;
connect-src https://system.hashentry.com;
  • SDK оформляет свой интерфейс с помощью элементов <style> внутри собственного shadow root. Если ваша политика ограничивает style-src, либо разрешите 'unsafe-inline' для стилей, либо используйте nonce: укажите nonce в теге cmp.js (<script nonce="…" …>), и SDK скопирует его в элементы стилей и в создаваемый им тег скрипта модуля.
  • При script-src 'strict-dynamic' и nonce в теге cmp.js скрипт модуля разрешается без указания источника в списке.
  • Диалог одобрения документа отображает документ в изолированном (sandboxed) iframe без src; скрипты внутри документа не выполняются.

Subresource Integrity. https://tool.hashentry.com/cmp.js обновляется по тому же адресу при выходе новой версии SDK, поэтому атрибут integrity для этого URL перестал бы работать при следующем релизе. Если вам нужен SRI, разместите проверенную копию cmp.js вместе с файлами cmp-documents.*.js / cmp-preferences.*.js той же сборки на собственном источнике и задайте integrity в своём теге.

Самостоятельный хостинг. Скопируйте cmp.js, cmp-documents.<hash>.js, cmp-preferences.<hash>.js, cmp-preferences.js и cmp-documents.js из одной и той же сборки в одну папку. Если файлы модулей находятся в другом месте, задайте data-module-base.


Чтобы отправлять запросы API через собственный домен, задайте в data-api-url (или через CMP.setApiUrl) путь или URL на вашей стороне и перенаправляйте его на API HashEntry, не изменяя путь после префикса:

<script src="https://tool.hashentry.com/cmp.js"
data-site="YOUR_SITE_API_KEY"
data-api-url="/hashentry-api" async></script>
# /hashentry-api/tool/v1/consents → https://system.hashentry.com/tool/v1/consents
location /hashentry-api/ {
proxy_pass https://system.hashentry.com/;
proxy_set_header Host system.hashentry.com;
proxy_ssl_server_name on;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

Подпись запроса охватывает путь /tool/v1/..., поэтому запрос к вышестоящему серверу должен прийти именно с этим путём. Записанный IP-адрес — это тот адрес, который видит HashEntry; будет ли адрес посетителя взят из X-Forwarded-For, зависит от того, считается ли прокси доверенным на стороне HashEntry, — уточните это в службе поддержки, прежде чем на это полагаться.


ИмяГдеНазначение
_he_consentfirst-party cookieРешение посетителя (категории, метки времени, серверный токен).
he_consent_tokenlocalStorageКопия того же решения.
he_config_cachelocalStorageКешированная конфигурация (до 7 дней, повторно проверяется в фоне при каждой загрузке).
he_pending_consentslocalStorageРешения, ещё не принятые сервером (удаляются после доставки; отбрасываются через 7 дней).
he_gpc_appliedlocalStorageОтмечает, что opt-out по сигналу GPC был применён один раз.
he_sdk_reloadsessionStorageЗащищает самообновление SDK от циклов перезагрузки.

SDK не загружает шрифты и какие-либо другие ресурсы у третьих сторон.