Zum Inhalt springen

JavaScript SDK (Client) Integration

Das HashEntry CMP SDK ist ein Skript ohne Abhängigkeiten, das das Cookie-Banner anzeigt, die von Ihnen markierten Skripte blockiert, bis der Besucher sie erlaubt, und jede Entscheidung auf dem HashEntry-Server erfasst. Es kann außerdem Zustimmungen zu Dokumenten (AGB, Verträge, Richtlinien) erfassen — siehe Dokumentzustimmung & Signatur.

Diese Seite beschreibt, was das SDK heute tut. Wo ein Verhalten von einer Dashboard-Einstellung oder von Ihrem eigenen Markup abhängt, wird darauf hingewiesen.


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

Das SDK lädt die an Ihren API-Schlüssel gebundene Konfiguration (Banner-Design, Texte, Kategorien, Dokumente, Verhaltenseinstellungen) vom Server und entscheidet, ob für diesen Besucher ein Banner erforderlich ist.

Zwei Voraussetzungen müssen erfüllt sein, bevor eine Cookie-Entscheidung auf dem Server erfasst werden kann:

  1. Die Website ist im Dashboard verifiziert. Anfragen für eine nicht verifizierte Website werden mit 403 SITE_NOT_VERIFIED abgelehnt.
  2. Der Website ist ein Cookie-Richtlinien-Dokument zugeordnet. Siehe den nächsten Abschnitt.

Eine Cookie-Einwilligung wird nur erfasst, wenn sie auf genau die aktive Version eines Dokuments vom Typ cookie_policy verweist, das der Website zugeordnet ist. Die akzeptierte Version der Richtlinie ist Teil des Nachweises, daher lockert das SDK diese Regel nicht.

  • Ist keine veröffentlichte Cookie-Richtlinie zugeordnet, zeigt das SDK das Banner nicht an (auch nicht das Widget oder den Link „Do Not Sell“) und hält in jeder Region alle markierten, nicht notwendigen Skripte blockiert: Eine Wahl, die nicht als Nachweis gespeichert werden kann, wird nicht erhoben. Die Ereignisse consent:error und error werden mit code: "COOKIE_POLICY_MISSING" ausgelöst, und der Fehler wird in die Browserkonsole geschrieben. CMP.accept() / CMP.reject() liefern success: false, error.code = "COOKIE_POLICY_MISSING" und pending_sync: false; nichts wird gespeichert, angewendet oder in die Warteschlange gestellt. Sobald eine Richtlinie zugeordnet ist, erscheint das Banner beim nächsten Seitenaufruf, und der Besucher entscheidet anhand dieser Version. Eine Einwilligung, die aufgezeichnet wurde, während eine Richtlinie zugeordnet war, bleibt gültig.
  • Eine Entscheidung wird nie zurückgehalten und später mit einer Richtlinienversion gesendet, die der Besucher nicht gesehen hat. Hat eine frühere SDK-Version eine solche Entscheidung in der lokalen Warteschlange hinterlassen, wird sie verworfen (consent:error mit final: true, reprompt: true) und der Besucher wird erneut gefragt.
  • Die einzige Ausnahme ist der Modus local ohne data-site: Es wird nichts an den Server gesendet, daher wird das Banner angezeigt und die Entscheidungen bleiben im Browser (local_only: true).
  • Verweist die Einwilligung auf eine Version, die nicht die aktive ist, antwortet der Server mit 409 CONFIG_OUTDATED. Siehe Erneute Einwilligung und geänderte Dokumentversionen.

Was Sie tun müssen: Erstellen Sie im Dashboard ein Cookie-Richtlinien-Dokument, veröffentlichen Sie eine Version in jeder Sprache, die Ihr Banner verwendet, und ordnen Sie es der Website zu.


Nur Skripte, die Sie markieren, werden blockiert. Das SDK durchsucht die Seite nicht nach Trackern und fängt keine Skripte ab, die Sie unverändert lassen: Ein normales <script>-Tag wird sofort ausgeführt, mit oder ohne Einwilligung.

Um ein Skript zurückzuhalten, ändern Sie dessen type in text/plain und geben Sie seine Kategorie an:

<!-- Inline-Skript: wird erst ausgeführt, nachdem "analytics" erlaubt wurde -->
<script type="text/plain" data-cookie-category="analytics">
/* Analytics-Snippet */
</script>
<!-- Externes Skript: data-src statt src verwenden -->
<script type="text/plain" data-cookie-category="marketing"
data-src="https://connect.facebook.net/en_US/fbevents.js"></script>
  • Die Kategorienamen müssen mit den Kategorieschlüsseln Ihres Banners übereinstimmen (analytics, marketing, preferences oder Ihre eigenen Schlüssel). Mit necessary markierte Skripte werden sofort aktiviert, noch bevor die Konfiguration geladen ist.
  • Markierte Skripte, die der Seite später hinzugefügt werden (SPA-Navigation, Tag-Injektion), werden ebenfalls behandelt.
  • Ein Skript, das bereits ausgeführt wurde, kann nicht gestoppt werden. Widerruft ein Besucher eine Kategorie, deren Skripte auf der aktuellen Seite ausgeführt wurden, löscht das SDK die bekannten Cookies dieser Kategorie und lädt die Seite standardmäßig neu (siehe reload_on_revoke).
  • Wird eine Kategorie widerrufen, löscht das SDK die Cookies / Speichereinträge, die in Ihrer Banner-Konfiguration für diese Kategorie aufgeführt sind, sowie eine kleine eingebaute Liste bekannter Namen. Cookies, die es nicht kennt, werden nicht gelöscht, und Drittanbieter-Cookies auf anderen Domains können von Ihrer Seite aus nicht gelöscht werden.

AttributStandardBeschreibung
data-site—API-Schlüssel der Website. Im Modus remote erforderlich; auch in den anderen Modi nötig, damit Entscheidungen auf dem Server erfasst werden.
data-modelocal-fallbackKonfigurationsquelle: remote, local, local-fallback. Siehe Betriebsmodi.
data-languageautoBanner-Sprache. auto verwendet <html lang>, danach die Browser-Sprache.
data-regionautoErzwingt eine Region oder ein Regelwerk (DE, US, gdpr, ccpa, none, …) anstelle der Erkennung. Dies ist die Compliance-Region (welchen Regeln das Banner folgt); sie legt weder den Speicherort der Daten noch den aufgerufenen API-Host fest.
data-config—Inline-JSON-Konfiguration (für local / local-fallback).
data-debugfalsetrue gibt Debug-Logs aus. Fehler und Warnungen werden immer in der Konsole ausgegeben.
data-headlessfalsetrue rendert überhaupt keine UI (Banner, Widget, „Do Not Sell“-Link). Siehe Headless-Modus.
data-consent-modeDashboard-Einstellungtrue / false schaltet Google Consent Mode v2 zwingend ein oder aus. Siehe Google Consent Mode v2.
data-reload-on-revokeDashboard-Einstellungtrue / false überschreibt das Verhaltens-Flag reload_on_revoke.
data-modules—Module, die vorab geladen werden sollen, z. B. documents, preferences. Siehe Bundles und bei Bedarf geladene Module.
data-module-baseOrdner des Skripts selbstBasis-URL, von der die Moduldateien geladen werden. Nur nötig, wenn sie nicht neben cmp.js ausgeliefert werden.
data-api-urlHashEntry-APIAPI-Basis-URL für einen First-Party-Proxy oder eine eigene Domain. Hat die Datenregion Ihres Kontos einen eigenen API-Host, teilt die Konfigurationsantwort ihn mit (api_base_url) und das SDK verwendet ihn für alle weiteren Aufrufe; der im Panel erzeugte Einbettungscode enthält dann bereits das passende data-api-url. Ein hier von Ihnen gesetzter Wert hat immer Vorrang.

window.CMP existiert, sobald das Skript ausgeführt wurde. Methoden, die etwas erfassen, geben ein Promise mit einem Ergebnisobjekt zurück; sie werfen keine Ausnahmen.

CMP.ready(() => { /* Konfiguration geladen, Einwilligungsstatus ausgewertet */ });
// Banner
CMP.show(); // Banner öffnen (z. B. über einen Footer-Link)
CMP.hide();
// Entscheidungen — jede gibt Promise<ConsentResult> zurück
CMP.accept(); // alle Kategorien erlauben
CMP.accept({ marketing: false }); // alle außer marketing erlauben
CMP.reject(); // nur notwendige
CMP.withdraw(); // die gespeicherte Einwilligung widerrufen
// Status
CMP.getConsent(); // ConsentState oder null
CMP.hasConsent('analytics'); // boolean ("necessary" ist immer true)
// Sprache
CMP.setLanguage('de');
CMP.getLanguage();
CMP.setLocale('de', { ccpa: { optOut: 'Widersprechen' } }); // Texte für eine Sprache
// Metadaten: werden jeder danach erfassten Einwilligung und Zustimmung hinzugefügt
CMP.setMetadata({ order_id: 'ORD-54321' });
CMP.setMetadata('customer_id', 'CUST-999');
CMP.getMetadata();
// Regions-Override, Theme, API-URL, lokale Konfiguration
CMP.setRegion('DE');
CMP.setTheme({ primaryColor: '#0F766E' });
CMP.setApiUrl('/hashentry-api');
CMP.getApiUrl();
CMP.setConfig({ banner_config: { /* … */ } });
// Ereignisse
CMP.on('consent:given', (payload) => {});
CMP.off('consent:given', handler);
// Dokumente (bei Bedarf geladen — siehe "Dokumentzustimmung & Signatur")
CMP.showDocumentApproval('terms-of-service', { language: 'en' });
CMP.approveDocument('terms-of-service', { /* … */ });

Der Widerruf schaltet alle nicht notwendigen Kategorien aus, löscht die bekannten Cookies dieser Kategorien, setzt Google Consent Mode auf denied, sendet eine Entscheidung withdrawn an den Server (sofern eine Einwilligung gespeichert war), entfernt die gespeicherte Einwilligung aus dem Browser und zeigt — in Opt-in-Regionen — das Banner erneut an. Wurden Skripte einer widerrufenen Kategorie auf der Seite bereits ausgeführt, wird die Seite neu geladen, sofern reload_on_revoke nicht ausgeschaltet ist.

Ändert die Sprache des geöffneten Banners und lädt die Konfiguration für diese Sprache neu, weil Dokumentversionen sprachspezifisch sind: Spätere Einwilligungen verweisen dann auf die Version der Cookie-Richtlinie in der neuen Sprache. Hat das Banner keine Übersetzung für die Sprache, fällt es auf die Standardsprache des Banners zurück.

Die Werte werden zusammengeführt und als metadata mit jeder späteren Cookie-Entscheidung und Dokumentzustimmung gesendet. Der Server akzeptiert höchstens 30 Schlüssel und etwa 16 KB Metadaten pro Datensatz.

<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>

In die Warteschlange gestellte Aufrufe werden der Reihe nach ausgeführt, wenn das SDK startet. Eine auf diese Weise gesetzte Sprache wird von der automatischen Erkennung nicht überschrieben.


{
success: true,
consent_token: 'ct_…',
proof_hash: '…', // 64 Hex-Zeichen
created_at: '2026-10-10T10:00:00+00:00',
idempotency_key: '…' // eine UUID pro Benutzeraktion, bei jedem Wiederholungsversuch wiederverwendet
}

success ist nur dann true, wenn der Server den Datensatz angenommen hat. Andernfalls:

{
success: false,
consent_token: '',
proof_hash: '',
created_at: '…',
error: { code: 'NETWORK_ERROR', status: 0, message: '…' },
pending_sync: true, // bleibt in der lokalen Warteschlange, wird erneut versucht
idempotency_key: '…'
}
  • error.code ist der Maschinencode des Servers oder einer der unten aufgeführten SDK-Codes; error.status ist der HTTP-Status (0, wenn keine Antwort empfangen wurde).
  • pending_sync: true bedeutet, dass die Entscheidung im Browser angewendet ist und in einer lokalen Warteschlange (localStorage) wartet. Sie wird beim nächsten Seitenaufruf, wenn der Tab wieder sichtbar wird und wenn der Browser wieder online ist, erneut versucht, immer mit demselben idempotency_key, bis zu 7 Tage lang oder für 12 Versuche.
  • local_only: true erscheint, wenn es nichts zu senden gibt (zum Beispiel im Modus local ohne data-site).

Die Wahl des Besuchers wird in jedem Fall sofort im Browser angewendet; das Ergebnis sagt Ihnen, ob der Server einen Datensatz dazu hat. Die Ausnahme ist COOKIE_POLICY_MISSING: Die Entscheidung wird weder gespeichert noch angewendet.

{ 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: '…' } }

Dokumentzustimmungen werden nie für später in die Warteschlange gestellt: Ist success nicht true, wurde die Zustimmung nicht erfasst.


EreignisPayloadWann
ready{}Start abgeschlossen (auch wenn die Konfiguration nicht geladen werden konnte).
banner:shown{ type } oder { headless: true, reason, config }Das Banner wurde angezeigt oder sollte — im Headless-Modus — von Ihnen angezeigt werden.
banner:hidden{ reason } oder { headless: true }Das Banner wurde geschlossen.
consent:given{ decision, categories, source }Eine andere Entscheidung als „alle ablehnen“ wurde lokal gespeichert.
consent:rejected{ decision, categories, source }„Alle ablehnen“ wurde lokal gespeichert.
consent:changed{ oldCategories, newCategories }Eine Entscheidung hat eine frühere ersetzt.
consent:withdrawn{ categories, cleanedCookies }CMP.withdraw() wurde aufgerufen.
consent:synced{ consent_token, idempotency_key }Der Server hat einen Datensatz angenommen (sofort oder aus der Warteschlange).
consent:error{ code, status, message, idempotency_key, pending_sync, final?, reprompt? }Ein Datensatz konnte nicht zugestellt werden. final: true bedeutet, dass er verworfen wurde.
document:approved{ slug, version, consentId }Eine Dokumentzustimmung wurde erfasst.
document:rejected{ slug, version }Der Besucher hat ein Dokument abgelehnt.
document:error{ slug, version, code, status, message }Ein Dokument konnte nicht geladen werden oder die Zustimmung wurde nicht erfasst.
scripts:activated{ category, count }Markierte Skripte einer Kategorie wurden aktiviert.
config:updated{ content_hash }Eine neuere Konfiguration hat die zwischengespeicherte ersetzt.
language:changed{ from, to }Die Sprache hat sich geändert.
error{ scope, code, status, message, … }Jeder der oben genannten Fehler; scope ist config, consent, module oder document.

consent:given / consent:rejected werden ausgelöst, wenn die Entscheidung im Browser gespeichert ist. Verwenden Sie consent:synced (oder das Promise-Ergebnis), wenn Sie wissen müssen, dass der Server sie hat.


Codes, die das SDK selbst erzeugt:

CodeBedeutung
NOT_READYEine Entscheidungsmethode wurde aufgerufen, bevor die Konfiguration geladen war. Rufen Sie sie innerhalb von CMP.ready() auf.
COOKIE_POLICY_MISSINGDer Website ist kein veröffentlichtes Cookie-Richtlinien-Dokument zugeordnet. Das Banner wird nicht angezeigt, nicht notwendige Skripte bleiben blockiert, und die Entscheidung wird weder gespeichert noch in die Warteschlange gestellt.
NETWORK_ERROR, TIMEOUTKeine Antwort von der API (Timeout: 5 s pro Versuch).
HTTP_<status>Der Server hat mit einem Fehler geantwortet, der keinen Maschinencode trägt.
DOCUMENT_VERSION_CHANGEDDie referenzierte Dokumentversion ist nicht mehr die aktive; der Datensatz wurde verworfen.
PENDING_EXPIREDEine Entscheidung in der Warteschlange konnte nicht innerhalb von 7 Tagen zugestellt werden und wurde verworfen.
MODULE_LOAD_FAILEDEine Moduldatei (documents oder preferences) konnte nicht geladen werden. Wird auch über das Ereignis error mit scope: "module" gemeldet.
APPROVAL_TOKEN_REQUIREDDas Dokument erfordert ein einmaliges Zustimmungstoken und es wurde keines übergeben (wird auch vom Server zurückgegeben).
CONFIG_UNAVAILABLEDie Konfiguration konnte nicht geladen werden (wird über das Ereignis error gemeldet).
UNEXPECTED_ERRORAlles andere.

Vom Server zurückgegebene Codes werden unverändert durchgereicht. Die wichtigsten sind auf der Seite zur REST-API aufgeführt — zum Beispiel CONFIG_OUTDATED, SITE_NOT_VERIFIED, ORIGIN_NOT_ALLOWED, RATE_LIMIT_EXCEEDED, CONSENT_LIMIT_EXCEEDED, APPROVAL_TOKEN_INVALID.

Vorübergehende Serverantworten. 503 (API_KEY_LOOKUP_UNAVAILABLE, ADMISSION_UNAVAILABLE, QUEUE_OVERLOADED) und 429 RATE_LIMIT_EXCEEDED werden automatisch mit demselben idempotency_key wiederholt; das SDK wartet die im Header Retry-After angegebene Zeit ab. Ist diese Zeit länger als 5 Sekunden, wartet das SDK nicht innerhalb der Seite: Die Entscheidung bleibt in der lokalen Warteschlange (pending_sync: true) und wird später gesendet. Nach 429 TOO_MANY_INVALID_API_KEYS sendet das SDK während dieses Seitenaufrufs keine weiteren Anfragen, und Entscheidungen in der Warteschlange bleiben erhalten; prüfen Sie den Wert von data-site. Keine dieser Antworten beeinträchtigt Ihre Seite: Das Ereignis error wird ausgelöst, und CMP.ready()-Callbacks werden weiterhin ausgeführt.

Abschnitt betitelt „Vorübergehende Serverantworten. 503 (API_KEY_LOOKUP_UNAVAILABLE, ADMISSION_UNAVAILABLE, QUEUE_OVERLOADED) und 429 RATE_LIMIT_EXCEEDED werden automatisch mit demselben idempotency_key wiederholt; das SDK wartet die im Header Retry-After angegebene Zeit ab. Ist diese Zeit länger als 5 Sekunden, wartet das SDK nicht innerhalb der Seite: Die Entscheidung bleibt in der lokalen Warteschlange (pending_sync: true) und wird später gesendet. Nach 429 TOO_MANY_INVALID_API_KEYS sendet das SDK während dieses Seitenaufrufs keine weiteren Anfragen, und Entscheidungen in der Warteschlange bleiben erhalten; prüfen Sie den Wert von data-site. Keine dieser Antworten beeinträchtigt Ihre Seite: Das Ereignis error wird ausgelöst, und CMP.ready()-Callbacks werden weiterhin ausgeführt.“

Erneute Einwilligung und geänderte Dokumentversionen

Abschnitt betitelt „Erneute Einwilligung und geänderte Dokumentversionen“

Wann das Banner erneut angezeigt wird. Die gespeicherte Einwilligung merkt sich den Inhalts-Hash der Banner-Konfiguration, für die sie erteilt wurde. Das Banner wird erneut angezeigt, wenn:

  • die Einwilligung abgelaufen ist (die Gültigkeitsdauer wird im Dashboard festgelegt),
  • sich die Kategorie- / Cookie-Struktur des Banners geändert hat oder
  • eine neue Version eines zugeordneten Dokuments veröffentlicht wurde — es sei denn, die Banner-Einstellung reconsent_on_doc_change ist ausgeschaltet; in diesem Fall lösen nur Strukturänderungen eine erneute Einwilligung aus.

Solange in einer Opt-in-Region eine erneute Einwilligung aussteht, bleibt die bisherige Wahl des Besuchers wirksam, bis er erneut entscheidet.

Ausstehende Entscheidungen und eine geänderte Dokumentversion. Wenn eine Entscheidung nicht zugestellt werden konnte (offline, Seite geschlossen, Serverfehler) und die Dokumentversion, auf die sie verweist, beim erneuten Versuch nicht mehr die aktive ist, geht das SDK wie folgt vor:

  1. Es fragt beim Server die aktuelle Konfiguration ab und umgeht dabei den Cache;
  2. ist die Version unverändert (der 409 wurde durch einen kalten Server-Cache verursacht), sendet es denselben Datensatz noch einmal;
  3. hat sich die Version geändert, verwirft es den Datensatz, entfernt die lokal gespeicherte Einwilligung und zeigt das Banner erneut an (consent:error mit code: "DOCUMENT_VERSION_CHANGED", final: true, reprompt: true).

Ein ausstehender Datensatz wird nie mit einer anderen Dokumentversion erneut gesendet: Der Besucher hat diese Version nicht gesehen.


Regionen, Regulierungsprofile und Verhaltens-Flags

Abschnitt betitelt „Regionen, Regulierungsprofile und Verhaltens-Flags“

Die Region des Besuchers wird in dieser Reihenfolge ermittelt: CMP.setRegion() → data-region → das GeoIP-Ergebnis des Servers in der Konfigurationsantwort (detected_region) → eine Schätzung anhand der Browser-Zeitzone → der fest eingestellte Regulierungsmodus des Banners → die strengsten Regeln (DSGVO). Das SDK ruft niemals einen Geolokalisierungsdienst eines Drittanbieters auf.

RegionRegelwerkModellVerhalten
EU / EWR, SchweizgdprOpt-inBanner; markierte Skripte bleiben blockiert, bis sie erlaubt werden.
TürkeikvkkOpt-inWie DSGVO.
Vereinigtes Königreichuk_gdprOpt-inWie DSGVO (siehe uk_analytics_exemption).
BrasilienlgpdOpt-inWie DSGVO.
Südafrika, Kanada, China, Südkoreapopia, pipeda, pipl, pipaOpt-inEs werden die Banner-Regeln der DSGVO angewendet.
USAccpa — nur wenn aktiviert, sonst gdprOpt-out / Opt-inSiehe ccpa_opt_out_enabled.
UnbekanntgdprOpt-inStrengste Regeln.
none (explizit)none—Kein Banner; alle Skripte werden ausgeführt.

In jedem Opt-in-Profil hat das Banner immer eine Schaltfläche „Ablehnen“ mit demselben visuellen Gewicht wie „Akzeptieren“, und keine optionale Kategorie ist vorausgewählt — unabhängig davon, was das Banner-Design vorgibt.

Drei Verhaltens-Flags (Banner → Verhaltenseinstellungen im Dashboard, banner_config.behavior in einer lokalen Konfiguration) ändern dies:

FlagStandardWirkung
uk_analytics_exemptionausNur für Besucher aus dem Vereinigten Königreich: Mit analytics markierte Skripte dürfen vor einer Entscheidung ausgeführt werden. Jede andere Kategorie benötigt weiterhin eine Einwilligung, und sobald der Besucher entschieden hat, gilt seine Entscheidung.
ccpa_opt_out_enabledausBesucher, die in den USA erkannt werden, erhalten das Opt-out-Modell: Skripte werden standardmäßig ausgeführt, ein Link „Do Not Sell or Share My Personal Information“ wird angezeigt, und ein Global-Privacy-Control-Signal wird einmalig als Opt-out angewendet (consent_type: do_not_sell_opt_out). Ist das Flag aus, erhalten US-Besucher das Opt-in-Banner.
reload_on_revokeanLädt die Seite neu, wenn ein Besucher eine Kategorie widerruft, deren Skripte auf dieser Seite bereits ausgeführt wurden. Schalten Sie es nur aus, wenn Ihre Tags selbst auf Änderungen der Einwilligung reagieren.

Wenn Consent Mode eingeschaltet ist, erstellt das SDK window.dataLayer und eine Funktion gtag, falls sie nicht existieren, und sendet:

  1. gtag('consent', 'default', { …all denied…, wait_for_update: 500 }) während des Starts,
  2. gtag('consent', 'update', { … }) nach jeder Entscheidung und bei jedem Seitenaufruf mit gespeicherter Einwilligung.
SignalErteilt, wenn diese Kategorie erlaubt ist
ad_storage, ad_user_data, ad_personalizationmarketing
analytics_storageanalytics
functionality_storage, personalization_storagepreferences
security_storageimmer

Das SDK sendet außerdem die Data-Layer-Ereignisse hashentry_consent_default und hashentry_consent_update.

Einrichtung:

  1. Schalten Sie Google Consent Mode für das Banner im Dashboard ein, oder fügen Sie dem Script-Tag data-consent-mode="true" hinzu.
  2. Platzieren Sie das HashEntry-Script-Tag oberhalb Ihres Google-Tags / GTM-Snippets.
  3. Wenn der Befehl default beim allerersten Seitenaufruf eines Besuchers vor den Google-Tags stehen muss, verwenden Sie data-consent-mode="true" und laden Sie cmp.js ohne async. Die Dashboard-Einstellung kommt mit der Konfiguration an, die bei einem ersten Besuch asynchron geladen wird; bei späteren Besuchen wird sie während des Starts aus der zwischengespeicherten Konfiguration gelesen.

Consent Mode sendet nur Signale. Tags, die nicht von Consent Mode gesteuert werden, müssen weiterhin wie oben beschrieben für die Blockierung markiert werden.


Mit data-headless="true" rendert das SDK nichts. Es lädt weiterhin die Konfiguration, blockiert markierte Skripte, aktualisiert Consent Mode und erfasst Entscheidungen.

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);
};

ModusKonfigurationsquelle
remoteNur der Server. data-site ist erforderlich.
localNur die Seite (CMP.setConfig, data-config oder <script type="application/json" id="cmp-config">).
local-fallback (Standard)Der Server; ist er nicht erreichbar, die Konfiguration der Seite.

Der Modus legt nur fest, woher die Konfiguration kommt. Entscheidungen werden in jedem Modus an den Server gesendet, solange data-site gesetzt ist. Im Modus local ohne data-site bleiben Entscheidungen nur im Browser (local_only: true).

Eine lokale Konfiguration hat dieselbe Struktur wie die Serverantwort:

<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>

Ist data-site gesetzt, fragt das SDK beim Start einmal das Cookie-Richtlinien-Dokument vom Server ab, weil eine Einwilligung auf dessen Version verweisen muss. Ist keine Richtlinie zugeordnet, wird das Banner nicht angezeigt (COOKIE_POLICY_MISSING). Soll das Banner auch dann erscheinen, wenn der Server nicht erreichbar ist, nehmen Sie documents (die Cookie-Richtlinie und ihre Version) in die Seitenkonfiguration auf.


Alle Banner-Texte (Titel, Beschreibung, Schaltflächen, Kategorienamen) stammen aus der Banner-Konfiguration — sie sind nicht Teil des Skripts.

Das SDK enthält ein kleines eingebautes Wörterbuch, nur auf Englisch und Türkisch, für Texte, die zu seiner eigenen UI gehören: den „Do Not Sell“-Dialog, die Schaltflächen und die Fehlerzeile der Dokumentzustimmung, die Überschriften der Cookie-Tabelle und die Schaltfläche zum Schließen. In jeder anderen Sprache fallen diese Texte auf Englisch zurück, sofern Sie sie nicht bereitstellen:

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.' }
});

Eine Konfiguration kann dieselben Schlüssel pro Sprache unter languages.translations.<lang>.sdk_texts enthalten.


DateiInhaltGeladen
cmp.jsKern und Cookie-EinwilligungDurch Ihr Script-Tag.
cmp-documents.<hash>.jsDokumentzustimmung (showDocumentApproval, approveDocument)Durch cmp.js, beim ersten Aufruf einer dieser Methoden.
cmp-preferences.<hash>.jsEinstellungszentrum, Tabelle mit Cookie-Details, Bestätigungsdialog „Do Not Sell“Durch cmp.js, wenn der Besucher eines davon zum ersten Mal öffnet.

Sie fügen nie ein zweites Script-Tag hinzu. Eine Website, die nur das Cookie-Banner verwendet, lädt das Dokumentmodul nie herunter.

  • Die Moduldatei wird vom selben Ort wie cmp.js angefordert (abgeleitet aus dem src des Skripts).
  • Um die kurze Verzögerung beim ersten Aufruf zu vermeiden, laden Sie es vorab: data-modules="documents".
  • Aufrufe, die erfolgen, bevor das Modul angekommen ist, warten einfach darauf. Kann es nicht geladen werden, wird die Methode mit success: false und error.code = "MODULE_LOAD_FAILED" aufgelöst; der nächste Aufruf versucht es erneut.
  • Kann das Modul preferences nicht geladen werden, bleibt das Banner mit seinen Schaltflächen zum Akzeptieren und Ablehnen sichtbar, das Ereignis error wird mit scope: "module" und code: "MODULE_LOAD_FAILED" ausgelöst, und der nächste Klick versucht es erneut. Um das Einstellungszentrum ohne Verzögerung zu öffnen, laden Sie das Modul vorab: data-modules="preferences".
  • Der Dateiname enthält einen Inhalts-Hash, der beim Build in cmp.js eingebettet wird, sodass cmp.js immer das Modul anfordert, das zusammen mit ihm gebaut wurde.

Content Security Policy. Das Modul wird mit einem <script>-Element vom selben Ursprung wie cmp.js geladen; das SDK verwendet weder eval noch Inline-Skripte. Für Skripte ist der Ursprung des SDK alles, was Sie benötigen:

script-src https://tool.hashentry.com;
connect-src https://system.hashentry.com;
  • Das SDK gestaltet seine UI mit <style>-Elementen innerhalb seines eigenen Shadow Root. Wenn Ihre Richtlinie style-src einschränkt, erlauben Sie entweder 'unsafe-inline' für Styles oder verwenden Sie eine Nonce: Setzen Sie die Nonce auf das cmp.js-Tag (<script nonce="…" …>), und das SDK kopiert sie auf die Style-Elemente und auf das Script-Tag des Moduls, das es erzeugt.
  • Mit script-src 'strict-dynamic' und einer Nonce auf dem cmp.js-Tag ist das Modulskript erlaubt, ohne dass der Ursprung aufgeführt werden muss.
  • Der Dialog zur Dokumentzustimmung rendert das Dokument in einem iframe mit Sandbox und ohne src; Skripte innerhalb des Dokuments werden nicht ausgeführt.

Subresource Integrity. https://tool.hashentry.com/cmp.js wird an Ort und Stelle aktualisiert, wenn eine neue SDK-Version veröffentlicht wird, sodass ein integrity-Attribut für diese URL bei der nächsten Veröffentlichung nicht mehr passen würde. Wenn Sie SRI benötigen, hosten Sie eine geprüfte Kopie von cmp.js zusammen mit den cmp-documents.*.js / cmp-preferences.*.js-Dateien desselben Builds auf Ihrem eigenen Ursprung und setzen Sie integrity auf Ihr eigenes Tag.

Self-Hosting. Kopieren Sie cmp.js, cmp-documents.<hash>.js, cmp-preferences.<hash>.js, cmp-preferences.js und cmp-documents.js aus demselben Build in einen Ordner. Liegen die Moduldateien an anderer Stelle, setzen Sie data-module-base.


Um API-Anfragen über Ihre eigene Domain zu senden, setzen Sie data-api-url (oder CMP.setApiUrl) auf einen Pfad oder eine URL auf Ihrer Seite und leiten Sie diese an die HashEntry-API weiter, ohne den Pfad unterhalb des Präfixes zu ändern:

<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;
}

Die Anfragesignatur umfasst den Pfad /tool/v1/..., daher muss die Upstream-Anfrage mit genau diesem Pfad ankommen. Die erfasste IP-Adresse ist diejenige, die HashEntry sieht; ob die Adresse des Besuchers aus X-Forwarded-For übernommen wird, hängt davon ab, ob der Proxy auf der HashEntry-Seite als vertrauenswürdig eingestuft ist — fragen Sie den Support, bevor Sie sich darauf verlassen.


NameWoZweck
_he_consentFirst-Party-CookieDie Entscheidung des Besuchers (Kategorien, Zeitstempel, Server-Token).
he_consent_tokenlocalStorageKopie derselben Entscheidung.
he_config_cachelocalStorageZwischengespeicherte Konfiguration (bis zu 7 Tage, bei jedem Laden im Hintergrund erneut validiert).
he_pending_consentslocalStorageEntscheidungen, die der Server noch nicht angenommen hat (nach der Übermittlung entfernt; nach 7 Tagen verworfen).
he_gpc_appliedlocalStorageVermerkt, dass ein GPC-Opt-out einmal angewendet wurde.
he_sdk_reloadsessionStorageSchützt die Selbstaktualisierung des SDK vor Neulade-Schleifen.

Das SDK lädt keine Schriftarten oder sonstigen Ressourcen von Drittanbietern.