دمج حزمة JavaScript SDK (العميل)
حزمة HashEntry CMP SDK هي سكريبت بلا تبعيات يعرض لافتة ملفات تعريف الارتباط، ويحظر السكريبتات التي تضع عليها علامة إلى أن يسمح بها الزائر، ويسجّل كل قرار على خادم HashEntry. ويمكنها أيضًا تسجيل الموافقات على المستندات (الشروط والعقود والسياسات) — راجع الموافقة على المستندات والتوقيع.
تصف هذه الصفحة ما تفعله الحزمة اليوم. وحيثما يعتمد سلوكٌ ما على إعداد في لوحة التحكم أو على ترميز صفحتك أنت، تذكر الصفحة ذلك.
البدء السريع
Section titled “البدء السريع”<head> <script src="https://tool.hashentry.com/cmp.js" data-site="YOUR_SITE_API_KEY" async ></script></head>تحمّل الحزمة من الخادم التكوين المرتبط بمفتاح API الخاص بك (تصميم اللافتة والنصوص والفئات والمستندات وإعدادات السلوك) وتقرر هل يحتاج هذا الزائر إلى لافتة أم لا.
يجب توفر أمرين قبل أن يمكن تسجيل قرار ملفات تعريف الارتباط على الخادم:
- أن يكون الموقع موثَّقًا في لوحة التحكم. تُرفض طلبات الموقع غير الموثَّق بـ
403 SITE_NOT_VERIFIED. - أن يكون مستند سياسة ملفات تعريف الارتباط مرفقًا بالموقع. راجع القسم التالي.
مستند سياسة ملفات تعريف الارتباط مطلوب
Section titled “مستند سياسة ملفات تعريف الارتباط مطلوب”لا تُسجَّل الموافقة على ملفات تعريف الارتباط إلا إذا أشارت إلى الإصدار النشط بعينه من مستند نوعه cookie_policy مرفق بالموقع. إصدار السياسة المقبول جزء من الدليل، ولذلك لا تتساهل الحزمة في هذه القاعدة.
- إذا لم تكن هناك سياسة ملفات تعريف ارتباط منشورة مرفقة، فإن 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. راجع إعادة طلب الموافقة وتغير إصدارات المستندات.
ما يجب عليك فعله: أنشئ مستند سياسة ملفات تعريف الارتباط في لوحة التحكم، وانشر إصدارًا بكل لغة تستخدمها لافتتك، وأرفقه بالموقع.
حظر السكريبتات قبل الموافقة
Section titled “حظر السكريبتات قبل الموافقة”لا تُحظر إلا السكريبتات التي تضع عليها علامة. لا تفحص الحزمة الصفحة بحثًا عن أدوات التتبع ولا تعترض السكريبتات التي تتركها دون تعديل: وسم <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، حقن الوسوم) تُعالَج كذلك.
- السكريبت الذي عمل بالفعل لا يمكن إيقافه. عندما يلغي الزائر فئة عملت سكريبتاتها في الصفحة الحالية، تحذف الحزمة ملفات تعريف الارتباط المعروفة لتلك الفئة، وافتراضيًا تعيد تحميل الصفحة (راجع
reload_on_revoke). - عند إلغاء فئة، تحذف الحزمة ملفات تعريف الارتباط / إدخالات التخزين المدرجة لتلك الفئة في تكوين لافتتك، إضافةً إلى قائمة مضمَّنة صغيرة من الأسماء المعروفة. ملفات تعريف الارتباط التي لا تعرفها الحزمة لا تُحذف، وملفات تعريف الارتباط التابعة لأطراف ثالثة على نطاقات أخرى لا يمكن حذفها من صفحتك.
سمات وسم السكريبت
Section titled “سمات وسم السكريبت”| السمة | الافتراضي | الوصف |
|---|---|---|
data-site | — | مفتاح API للموقع. مطلوب في وضع remote؛ ولازم أيضًا في الأوضاع الأخرى كي تُسجَّل القرارات على الخادم. |
data-mode | local-fallback | مصدر التكوين: remote أو local أو local-fallback. راجع أوضاع التشغيل. |
data-language | auto | لغة اللافتة. القيمة auto تستخدم <html lang> ثم لغة المتصفح. |
data-region | auto | تفرض منطقة أو إطارًا تنظيميًا (DE أو US أو gdpr أو ccpa أو none أو …) بدلًا من الاكتشاف. هذه منطقة الامتثال (القواعد التي يتبعها الشريط)؛ وهي لا تحدد مكان تخزين البيانات ولا مضيف الـ API الذي يُستدعى. |
data-config | — | تكوين JSON مضمَّن (لوضعي local / local-fallback). |
data-debug | false | القيمة true تطبع سجلات التصحيح. الأخطاء والتحذيرات تُطبع دائمًا في الكونسول. |
data-headless | false | القيمة true لا تعرض أي واجهة إطلاقًا (اللافتة، الأيقونة، رابط “Do Not Sell”). راجع الوضع بدون واجهة. |
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-url | واجهة HashEntry API | عنوان URL الأساسي للـ API عند استخدام بروكسي الطرف الأول أو نطاق مخصص. إذا كان لمنطقة بيانات حسابك مضيف API خاص بها، فإن استجابة الإعدادات تعلن عنه (api_base_url) ويستخدمه الـ SDK في جميع الاستدعاءات اللاحقة؛ كما أن كود التضمين الذي تولّده اللوحة يتضمن قيمة data-api-url المطابقة. والقيمة التي تحددها أنت هنا لها الأولوية دائمًا. |
واجهة JavaScript API (window.CMP)
Section titled “واجهة JavaScript API (window.CMP)”يتوفر window.CMP فور تشغيل السكريبت. الدوال التي تسجّل شيئًا تعيد promise يحمل كائن نتيجة؛ وهي لا ترمي استثناءات.
CMP.ready(() => { /* تم تحميل التكوين وتقييم حالة الموافقة */ });
// اللافتةCMP.show(); // فتح اللافتة (مثلًا من رابط في التذييل)CMP.hide();
// القرارات — كل منها يعيد Promise<ConsentResult>CMP.accept(); // السماح بجميع الفئاتCMP.accept({ marketing: false }); // السماح بالجميع عدا marketingCMP.reject(); // الضرورية فقطCMP.withdraw(); // سحب الموافقة المخزنة
// الحالةCMP.getConsent(); // ConsentState أو nullCMP.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();
// تجاوز المنطقة، السمة، عنوان 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', { /* … */ });CMP.withdraw()
Section titled “CMP.withdraw()”سحب الموافقة يوقف جميع الفئات غير الضرورية، ويحذف ملفات تعريف الارتباط المعروفة لتلك الفئات، ويضبط Google Consent Mode على denied، ويرسل إلى الخادم قرارًا قيمته withdrawn (إن كانت هناك موافقة مخزنة)، ويزيل الموافقة المخزنة من المتصفح، و— في مناطق opt-in — يعرض اللافتة من جديد. إذا كانت سكريبتات فئة ملغاة قد عملت بالفعل في الصفحة، يُعاد تحميل الصفحة ما لم يكن reload_on_revoke متوقفًا.
CMP.setLanguage(lang)
Section titled “CMP.setLanguage(lang)”تغيّر لغة اللافتة المفتوحة وتعيد تحميل التكوين لتلك اللغة، لأن إصدارات المستندات خاصة بكل لغة: الموافقات اللاحقة تشير عندئذ إلى إصدار سياسة ملفات تعريف الارتباط الخاص باللغة الجديدة. إذا لم تكن للافتة ترجمة لتلك اللغة، يُرجَع إلى اللغة الافتراضية للافتة.
CMP.setMetadata(...)
Section titled “CMP.setMetadata(...)”تُدمج القيم وتُرسل في metadata مع كل قرار لاحق بشأن ملفات تعريف الارتباط ومع كل موافقة لاحقة على مستند. يقبل الخادم 30 مفتاحًا على الأكثر ونحو 16 KB من البيانات الوصفية لكل سجل.
استدعاء الواجهة قبل تحميل السكريبت
Section titled “استدعاء الواجهة قبل تحميل السكريبت”<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>تُنفَّذ الاستدعاءات الموضوعة في قائمة الانتظار بالترتيب عند بدء الحزمة. اللغة المضبوطة بهذه الطريقة لا يتجاوزها الاكتشاف التلقائي.
كائنات النتيجة
Section titled “كائنات النتيجة”ConsentResult (accept, reject, withdraw)
Section titled “ConsentResult (accept, reject, withdraw)”{ 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هو الرمز الآلي الصادر عن الخادم أو أحد رموز الحزمة المذكورة أدناه؛ وerror.statusهو حالة HTTP (0إذا لم يُستلم أي رد).pending_sync: trueيعني أن القرار مطبَّق في المتصفح وينتظر في قائمة انتظار محلية (localStorage). تُعاد محاولته عند تحميل الصفحة التالي، وعندما يصبح التبويب مرئيًا من جديد، وعندما يعود المتصفح إلى الاتصال، ودائمًا بالقيمة نفسها لـidempotency_key، لمدة تصل إلى 7 أيام أو 12 محاولة.local_only: trueيظهر عندما لا يوجد ما يُرسل (مثلًا وضعlocalبدونdata-site).
يُطبَّق اختيار الزائر في المتصفح فورًا في جميع الحالات؛ والنتيجة تخبرك هل لدى الخادم سجل به أم لا. الاستثناء هو COOKIE_POLICY_MISSING: لا يُخزَّن القرار ولا يُطبَّق.
DocumentApprovalResult
Section titled “DocumentApprovalResult”{ 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 فالموافقة لم تُسجَّل.
الأحداث
Section titled “الأحداث”| الحدث | الحمولة | متى |
|---|---|---|
ready | {} | اكتمل بدء التشغيل (وأيضًا عندما يتعذر تحميل التكوين). |
banner:shown | { type } أو { headless: true, reason, config } | عُرضت اللافتة، أو — في الوضع بدون واجهة — ينبغي أن تعرضها أنت. |
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 (أو نتيجة الـ promise) عندما تحتاج إلى معرفة أن القرار صار لدى الخادم.
رموز الأخطاء
Section titled “رموز الأخطاء”الرموز التي تنتجها الحزمة نفسها:
| الرمز | المعنى |
|---|---|
NOT_READY | استُدعيت دالة قرار قبل تحميل التكوين. استدعِها داخل CMP.ready(). |
COOKIE_POLICY_MISSING | لا يوجد مستند سياسة ملفات تعريف ارتباط منشور مرفق بالموقع. لا تُعرض اللافتة، وتبقى السكربتات غير الضرورية محظورة، ولا يُخزَّن القرار ولا يوضع في قائمة الانتظار. |
NETWORK_ERROR, TIMEOUT | لا رد من الـ API (المهلة: 5 ثوانٍ لكل محاولة). |
HTTP_<status> | أجاب الخادم بخطأ لا يحمل رمزًا آليًا. |
DOCUMENT_VERSION_CHANGED | إصدار المستند المشار إليه لم يعد هو الإصدار النشط؛ أُسقط السجل. |
PENDING_EXPIRED | تعذر تسليم قرار في قائمة الانتظار خلال 7 أيام فأُسقط. |
MODULE_LOAD_FAILED | تعذر تحميل ملف وحدة (documents أو preferences). يُبلَّغ عنه أيضًا عبر الحدث error مع scope: "module". |
APPROVAL_TOKEN_REQUIRED | المستند يتطلب رمزًا مميزًا (token) للموافقة لمرة واحدة ولم يُمرَّر أي رمز (يعيده الخادم أيضًا). |
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() كالمعتاد.
Section titled “استجابات الخادم المؤقتة. تُعاد محاولة 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() كالمعتاد.”إعادة طلب الموافقة وتغير إصدارات المستندات
Section titled “إعادة طلب الموافقة وتغير إصدارات المستندات”متى تُعرض اللافتة من جديد. تتذكر الموافقة المخزنة تجزئة المحتوى (content hash) لتكوين اللافتة الذي مُنحت من أجله. تُعرض اللافتة من جديد عندما:
- تنتهي صلاحية الموافقة (مدة الصلاحية تُضبط في لوحة التحكم)،
- تتغير بنية الفئات / ملفات تعريف الارتباط في اللافتة، أو
- يُنشر إصدار جديد من مستند مرفق — ما لم يكن إعداد اللافتة
reconsent_on_doc_changeمتوقفًا، وفي هذه الحالة لا تؤدي إلى إعادة طلب الموافقة إلا تغييرات البنية.
ما دامت إعادة طلب الموافقة معلَّقة في منطقة opt-in، يبقى اختيار الزائر السابق ساريًا إلى أن يقرر من جديد.
القرارات المعلَّقة وتغير إصدار المستند. إذا تعذر تسليم قرار (انقطاع الاتصال، إغلاق الصفحة، خطأ في الخادم) وكان إصدار المستند الذي يشير إليه، عند إعادة المحاولة، لم يعد هو الإصدار النشط، فإن الحزمة:
- تطلب من الخادم التكوين الحالي متجاوزةً الذاكرة المؤقتة؛
- إذا لم يتغير الإصدار (كان سبب 409 ذاكرة مؤقتة باردة في الخادم)، ترسل السجل نفسه مرة أخرى؛
- إذا تغير الإصدار، تُسقط السجل، وتزيل الموافقة المخزنة محليًا وتعرض اللافتة من جديد (
consent:errorمعcode: "DOCUMENT_VERSION_CHANGED"وfinal: trueوreprompt: true).
لا يُعاد إرسال سجل معلَّق بإصدار مستند مختلف أبدًا: فالزائر لم يرَ ذلك الإصدار.
المناطق وملفات التنظيم وعلامات السلوك
Section titled “المناطق وملفات التنظيم وعلامات السلوك”تُحدَّد منطقة الزائر بهذا الترتيب: CMP.setRegion() ← data-region ← نتيجة GeoIP من الخادم في رد التكوين (detected_region) ← تقدير من المنطقة الزمنية للمتصفح ← وضع التنظيم الثابت للافتة ← القواعد الأشد صرامة (GDPR). لا تستدعي الحزمة أبدًا خدمة تحديد موقع جغرافي تابعة لطرف ثالث.
| المنطقة | الإطار | النموذج | السلوك |
|---|---|---|---|
| الاتحاد الأوروبي / المنطقة الاقتصادية الأوروبية، سويسرا | gdpr | opt-in | لافتة؛ السكريبتات الموسومة محظورة إلى أن يُسمح بها. |
| تركيا | kvkk | opt-in | مثل GDPR. |
| المملكة المتحدة | uk_gdpr | opt-in | مثل GDPR (راجع uk_analytics_exemption). |
| البرازيل | lgpd | opt-in | مثل GDPR. |
| جنوب أفريقيا، كندا، الصين، كوريا الجنوبية | popia, pipeda, pipl, pipa | opt-in | تُطبَّق قواعد لافتة GDPR. |
| الولايات المتحدة | ccpa — فقط إذا كان مفعَّلًا، وإلا gdpr | opt-out / opt-in | راجع ccpa_opt_out_enabled. |
| غير معروفة | gdpr | opt-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 | مفعَّلة | إعادة تحميل الصفحة عندما يلغي الزائر فئة عملت سكريبتاتها بالفعل في هذه الصفحة. لا توقفها إلا إذا كانت وسومك تتفاعل بنفسها مع تغيّرات الموافقة. |
Google Consent Mode v2
Section titled “Google Consent Mode v2”عندما يكون Consent Mode مفعَّلًا، تنشئ الحزمة window.dataLayer ودالة gtag إن لم يكونا موجودين وتدفع:
gtag('consent', 'default', { …all denied…, wait_for_update: 500 })أثناء بدء التشغيل،gtag('consent', 'update', { … })بعد كل قرار وعند كل تحميل صفحة مع موافقة مخزنة.
| الإشارة | تُمنح عند السماح بهذه الفئة |
|---|---|
ad_storage, ad_user_data, ad_personalization | marketing |
analytics_storage | analytics |
functionality_storage, personalization_storage | preferences |
security_storage | دائمًا |
تدفع الحزمة أيضًا حدثَي طبقة البيانات hashentry_consent_default و hashentry_consent_update.
الإعداد:
- فعِّل Google Consent Mode للافتة في لوحة التحكم، أو أضف
data-consent-mode="true"إلى وسم السكريبت. - ضع وسم سكريبت HashEntry فوق وسم Google / مقتطف GTM لديك.
- إذا كان لا بد أن يسبق أمر
defaultوسوم Google في أول مشاهدة صفحة للزائر على الإطلاق، فاستخدمdata-consent-mode="true"وحمّلcmp.jsبدونasync. إعداد لوحة التحكم يصل مع التكوين، وهذا يُحمَّل بشكل غير متزامن في الزيارة الأولى؛ وفي الزيارات اللاحقة يُقرأ من التكوين المخزَّن مؤقتًا أثناء بدء التشغيل.
Consent Mode يرسل إشارات فقط. الوسوم التي لا يتحكم بها Consent Mode ما زالت بحاجة إلى وضع علامة عليها لحظرها كما هو موصوف أعلاه.
الوضع بدون واجهة
Section titled “الوضع بدون واجهة”مع data-headless="true" لا تعرض الحزمة شيئًا. لكنها تظل تحمّل التكوين وتحظر السكريبتات الموسومة وتحدّث 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);};أوضاع التشغيل
Section titled “أوضاع التشغيل”| الوضع | مصدر التكوين |
|---|---|
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_POLICY_MISSING). لعرض اللافتة حتى عند تعذر الوصول إلى الخادم، أدرج documents (سياسة ملفات تعريف الارتباط وإصدارها) في إعدادات الصفحة.
اللغات والنصوص
Section titled “اللغات والنصوص”جميع نصوص اللافتة (العنوان، الوصف، الأزرار، أسماء الفئات) تأتي من تكوين اللافتة — وليست جزءًا من السكريبت.
تتضمن الحزمة قاموسًا مضمَّنًا صغيرًا، بالإنجليزية والتركية فقط، للنصوص التي تخص واجهتها هي: مربع حوار “Do Not Sell”، وأزرار الموافقة على المستند وسطر الخطأ، وعناوين جدول ملفات تعريف الارتباط وزر الإغلاق. في أي لغة أخرى تعود هذه النصوص إلى الإنجليزية ما لم توفّرها أنت:
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.
الحزم والوحدات المحملة عند الطلب
Section titled “الحزم والوحدات المحملة عند الطلب”| الملف | المحتوى | يُحمَّل |
|---|---|---|
cmp.js | النواة والموافقة على ملفات تعريف الارتباط | بواسطة وسم السكريبت الخاص بك. |
cmp-documents.<hash>.js | الموافقة على المستندات (showDocumentApproval, approveDocument) | بواسطة cmp.js، عند أول استدعاء لإحدى هاتين الدالتين. |
cmp-preferences.<hash>.js | مركز التفضيلات، جدول تفاصيل ملفات تعريف الارتباط، نافذة تأكيد «Do Not Sell» | بواسطة cmp.js، عندما يفتح الزائر أحدها لأول مرة. |
لا تضيف أبدًا وسم سكريبت ثانيًا. الموقع الذي يستخدم لافتة ملفات تعريف الارتباط فقط لا ينزّل وحدة المستندات أبدًا.
- يُطلب ملف الوحدة من الموضع نفسه الذي يوجد فيه
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؛ ولا تستخدم الحزمة eval ولا سكريبتات مضمَّنة. بالنسبة إلى السكريبتات، أصل الحزمة هو كل ما تحتاج إليه:
script-src https://tool.hashentry.com;connect-src https://system.hashentry.com;- تنسّق الحزمة واجهتها بعناصر
<style>داخل shadow root خاص بها. إذا كانت سياستك تقيّدstyle-src، فإما أن تسمح بـ'unsafe-inline'للأنماط أو تستخدم nonce: ضع الـ nonce على وسمcmp.js(<script nonce="…" …>) فتنسخه الحزمة إلى عناصر الأنماط وإلى وسم سكريبت الوحدة الذي تنشئه. - مع
script-src 'strict-dynamic'و nonce على وسمcmp.js، يُسمح بسكريبت الوحدة دون إدراج الأصل. - مربع حوار الموافقة على المستند يعرض المستند في
iframeمعزول (sandboxed) بدونsrc؛ والسكريبتات داخل المستند لا تعمل.
سلامة الموارد الفرعية (Subresource Integrity). يُحدَّث https://tool.hashentry.com/cmp.js في مكانه عند إصدار نسخة جديدة من الحزمة، ولذلك فإن سمة integrity على ذلك العنوان ستنكسر عند الإصدار التالي. إذا كنت تحتاج إلى 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.
بروكسي الطرف الأول
Section titled “بروكسي الطرف الأول”لإرسال طلبات الـ API عبر نطاقك أنت، اضبط data-api-url (أو CMP.setApiUrl) على مسار أو عنوان URL من جهتك وأعد توجيهه إلى واجهة HashEntry API دون تغيير المسار الواقع بعد البادئة:
<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/consentslocation /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 — اسأل الدعم قبل الاعتماد على ذلك.
ما تخزنه الحزمة في المتصفح
Section titled “ما تخزنه الحزمة في المتصفح”| الاسم | المكان | الغرض |
|---|---|---|
_he_consent | ملف تعريف ارتباط للطرف الأول | قرار الزائر (الفئات، التوقيتات، الرمز المميز الصادر عن الخادم). |
he_consent_token | localStorage | نسخة من القرار نفسه. |
he_config_cache | localStorage | التكوين المخزَّن مؤقتًا (حتى 7 أيام، ويُعاد التحقق منه في الخلفية عند كل تحميل). |
he_pending_consents | localStorage | القرارات التي لم يقبلها الخادم بعد (تُحذف عند إيصالها وتُهمل بعد 7 أيام). |
he_gpc_applied | localStorage | يشير إلى أن opt-out عبر GPC قد طُبِّق مرة واحدة. |
he_sdk_reload | sessionStorage | يحمي التحديث الذاتي للحزمة من حلقات إعادة التحميل. |
لا تحمّل الحزمة خطوطًا ولا أي مورد آخر من أطراف ثالثة.