تخطَّ إلى المحتوى

دمج حزمة JavaScript SDK (العميل)

حزمة HashEntry CMP SDK هي سكريبت بلا تبعيات يعرض لافتة ملفات تعريف الارتباط، ويحظر السكريبتات التي تضع عليها علامة إلى أن يسمح بها الزائر، ويسجّل كل قرار على خادم HashEntry. ويمكنها أيضًا تسجيل الموافقات على المستندات (الشروط والعقود والسياسات) — راجع الموافقة على المستندات والتوقيع.

تصف هذه الصفحة ما تفعله الحزمة اليوم. وحيثما يعتمد سلوكٌ ما على إعداد في لوحة التحكم أو على ترميز صفحتك أنت، تذكر الصفحة ذلك.


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

تحمّل الحزمة من الخادم التكوين المرتبط بمفتاح API الخاص بك (تصميم اللافتة والنصوص والفئات والمستندات وإعدادات السلوك) وتقرر هل يحتاج هذا الزائر إلى لافتة أم لا.

يجب توفر أمرين قبل أن يمكن تسجيل قرار ملفات تعريف الارتباط على الخادم:

  1. أن يكون الموقع موثَّقًا في لوحة التحكم. تُرفض طلبات الموقع غير الموثَّق بـ 403 SITE_NOT_VERIFIED.
  2. أن يكون مستند سياسة ملفات تعريف الارتباط مرفقًا بالموقع. راجع القسم التالي.

مستند سياسة ملفات تعريف الارتباط مطلوب

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).
  • عند إلغاء فئة، تحذف الحزمة ملفات تعريف الارتباط / إدخالات التخزين المدرجة لتلك الفئة في تكوين لافتتك، إضافةً إلى قائمة مضمَّنة صغيرة من الأسماء المعروفة. ملفات تعريف الارتباط التي لا تعرفها الحزمة لا تُحذف، وملفات تعريف الارتباط التابعة لأطراف ثالثة على نطاقات أخرى لا يمكن حذفها من صفحتك.

السمةالافتراضيالوصف
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-debugfalseالقيمة true تطبع سجلات التصحيح. الأخطاء والتحذيرات تُطبع دائمًا في الكونسول.
data-headlessfalseالقيمة 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 المطابقة. والقيمة التي تحددها أنت هنا لها الأولوية دائمًا.

يتوفر window.CMP فور تشغيل السكريبت. الدوال التي تسجّل شيئًا تعيد promise يحمل كائن نتيجة؛ وهي لا ترمي استثناءات.

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();
// تجاوز المنطقة، السمة، عنوان 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', { /* … */ });

سحب الموافقة يوقف جميع الفئات غير الضرورية، ويحذف ملفات تعريف الارتباط المعروفة لتلك الفئات، ويضبط Google Consent Mode على denied، ويرسل إلى الخادم قرارًا قيمته withdrawn (إن كانت هناك موافقة مخزنة)، ويزيل الموافقة المخزنة من المتصفح، و— في مناطق opt-in — يعرض اللافتة من جديد. إذا كانت سكريبتات فئة ملغاة قد عملت بالفعل في الصفحة، يُعاد تحميل الصفحة ما لم يكن reload_on_revoke متوقفًا.

تغيّر لغة اللافتة المفتوحة وتعيد تحميل التكوين لتلك اللغة، لأن إصدارات المستندات خاصة بكل لغة: الموافقات اللاحقة تشير عندئذ إلى إصدار سياسة ملفات تعريف الارتباط الخاص باللغة الجديدة. إذا لم تكن للافتة ترجمة لتلك اللغة، يُرجَع إلى اللغة الافتراضية للافتة.

تُدمج القيم وتُرسل في 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>

تُنفَّذ الاستدعاءات الموضوعة في قائمة الانتظار بالترتيب عند بدء الحزمة. اللغة المضبوطة بهذه الطريقة لا يتجاوزها الاكتشاف التلقائي.


{
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: لا يُخزَّن القرار ولا يُطبَّق.

{ 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 }عُرضت اللافتة، أو — في الوضع بدون واجهة — ينبغي أن تعرضها أنت.
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) عندما تحتاج إلى معرفة أن القرار صار لدى الخادم.


الرموز التي تنتجها الحزمة نفسها:

الرمزالمعنى
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، يبقى اختيار الزائر السابق ساريًا إلى أن يقرر من جديد.

القرارات المعلَّقة وتغير إصدار المستند. إذا تعذر تسليم قرار (انقطاع الاتصال، إغلاق الصفحة، خطأ في الخادم) وكان إصدار المستند الذي يشير إليه، عند إعادة المحاولة، لم يعد هو الإصدار النشط، فإن الحزمة:

  1. تطلب من الخادم التكوين الحالي متجاوزةً الذاكرة المؤقتة؛
  2. إذا لم يتغير الإصدار (كان سبب 409 ذاكرة مؤقتة باردة في الخادم)، ترسل السجل نفسه مرة أخرى؛
  3. إذا تغير الإصدار، تُسقط السجل، وتزيل الموافقة المخزنة محليًا وتعرض اللافتة من جديد (consent:error مع code: "DOCUMENT_VERSION_CHANGED" و final: true و reprompt: true).

لا يُعاد إرسال سجل معلَّق بإصدار مستند مختلف أبدًا: فالزائر لم يرَ ذلك الإصدار.


المناطق وملفات التنظيم وعلامات السلوك

Section titled “المناطق وملفات التنظيم وعلامات السلوك”

تُحدَّد منطقة الزائر بهذا الترتيب: CMP.setRegion() ← data-region ← نتيجة GeoIP من الخادم في رد التكوين (detected_region) ← تقدير من المنطقة الزمنية للمتصفح ← وضع التنظيم الثابت للافتة ← القواعد الأشد صرامة (GDPR). لا تستدعي الحزمة أبدًا خدمة تحديد موقع جغرافي تابعة لطرف ثالث.

المنطقةالإطارالنموذجالسلوك
الاتحاد الأوروبي / المنطقة الاقتصادية الأوروبية، سويسرا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 مفعَّلًا، تنشئ الحزمة window.dataLayer ودالة gtag إن لم يكونا موجودين وتدفع:

  1. gtag('consent', 'default', { …all denied…, wait_for_update: 500 }) أثناء بدء التشغيل،
  2. gtag('consent', 'update', { … }) بعد كل قرار وعند كل تحميل صفحة مع موافقة مخزنة.
الإشارةتُمنح عند السماح بهذه الفئة
ad_storage, ad_user_data, ad_personalizationmarketing
analytics_storageanalytics
functionality_storage, personalization_storagepreferences
security_storageدائمًا

تدفع الحزمة أيضًا حدثَي طبقة البيانات 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" لا تعرض الحزمة شيئًا. لكنها تظل تحمّل التكوين وتحظر السكريبتات الموسومة وتحدّث 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_POLICY_MISSING). لعرض اللافتة حتى عند تعذر الوصول إلى الخادم، أدرج documents (سياسة ملفات تعريف الارتباط وإصدارها) في إعدادات الصفحة.


جميع نصوص اللافتة (العنوان، الوصف، الأزرار، أسماء الفئات) تأتي من تكوين اللافتة — وليست جزءًا من السكريبت.

تتضمن الحزمة قاموسًا مضمَّنًا صغيرًا، بالإنجليزية والتركية فقط، للنصوص التي تخص واجهتها هي: مربع حوار “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.


لإرسال طلبات الـ 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/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 — اسأل الدعم قبل الاعتماد على ذلك.


ما تخزنه الحزمة في المتصفح

Section titled “ما تخزنه الحزمة في المتصفح”
الاسمالمكانالغرض
_he_consentملف تعريف ارتباط للطرف الأولقرار الزائر (الفئات، التوقيتات، الرمز المميز الصادر عن الخادم).
he_consent_tokenlocalStorageنسخة من القرار نفسه.
he_config_cachelocalStorageالتكوين المخزَّن مؤقتًا (حتى 7 أيام، ويُعاد التحقق منه في الخلفية عند كل تحميل).
he_pending_consentslocalStorageالقرارات التي لم يقبلها الخادم بعد (تُحذف عند إيصالها وتُهمل بعد 7 أيام).
he_gpc_appliedlocalStorageيشير إلى أن opt-out عبر GPC قد طُبِّق مرة واحدة.
he_sdk_reloadsessionStorageيحمي التحديث الذاتي للحزمة من حلقات إعادة التحميل.

لا تحمّل الحزمة خطوطًا ولا أي مورد آخر من أطراف ثالثة.