متتبّع أحداث عام الغرض. استخدمه لأي شيء تحتاج تحليلات عليه ولا يكون اشتراكًا:
مشاهدات الصفحة
إرسال نماذج العملاء المحتملين (Lead)
تتبع النقرات على صفحات الهبوط
أحداث مخصصة يحددها التاجر
إن كانت بياناتك تحمل هوية مستخدم ذات معنى (عنوان بريد إلكتروني)، استخدم /v1/signups بدلًا منها: فهي تحتسب كل عنوان بريد مرة واحدة لكل متجر. أما أرقام الهاتف فلا يُزال تكرارها هناك. /v1/events للبيانات عالية الحجم بلا هوية.
المصادقة
مفتاح عام + HMAC. نفس مخطط /v1/signups. خادمك الخلفي يوقّع كل نداء.
⚠️ تنبيه — أمران يعطّلان أي مفتاح جديد تمامًا
بوابة البرنامج التجريبي. الـ API مُقيَّد بالبرنامج التجريبي في الإنتاج. المفتاح الذي لم تُسجّله DZBuild يُرجع
403 forbidden"API is in pilot mode; key not enrolled"في كل نداء.تأخير التفعيل. المفتاح العام الجديد ليس صالحًا للاستعمال لحظة إنشائه. وإلى أن يُفعَّل لهذه النقاط ستحصل على
401 unauthorized"Invalid or revoked public key". راسل الدعم مباشرة بعد إنشائه لتفعيله.
إلغاء مفتاح عام لا يوقفه وحده: تظل النداءات الموقّعة مقبولة إلى أن يعطّله الدعم. راسل الدعم كلما ألغيت مفتاحًا عامًا.
الجسم
{
"name": "lead_submitted",
"properties": { "plan": "pro", "country": "DZ", "form": "footer" },
"nonce": "32-hex-single-use"
}
الحقل | النوع | إلزامي | ملاحظات |
| string ≤ 64 بايت | ✅ | اسم الحدث. |
| object | قيم قابلة لـ JSON. تُحفظ كما هي. | |
| 32-hex string | ✅ | استعمل نفس قيمة ترويسة |
كما يجب أن تحمل طلبات POST ترويسة Idempotency-Key (بحد أقصى 64 حرفًا، من مجموعة المحارف [A-Za-z0-9_-:.]). بدونها تحصل على 400 bad_request ولا يدخل الحدث الطابور أصلًا. والـ nonce ذو الـ 32 خانة ست عشرية الذي تولّده أصلًا قيمة صالحة — أعد استعماله.
name يُخزَّن مع كل حدث، لكن لا توجد نقطة في الـ API ولا شاشة في لوحة التحكم تعرض الأحداث المخزَّنة: ما يمكنك قراءته، بمفتاح منصة، هو العدد الشهري في GET /v1/usage (usage.event.total). ومع ذلك التزم بمعجم صغير ثابت للأسماء، وتجنّب توليدها ديناميكيًا (مثل viewed_product_42 سيء؛ استخدم name="viewed_product" مع properties.product_id=42).
الاستجابة 202
{
"data": { "status": "queued", "kind": "event", "store_id": 13 },
"meta": { "request_id": "...", "api_version": "v1", "edge": true }
}
نفس تدفّق الاشتراكات: يُقبَل في ~30 مللي ثانية، ويُخزَّن خلال 5 ثوانٍ تقريبًا.
إزالة التكرار
إزالة التكرار تعتمد على الـ nonce وحده، لكل متجر. لا توجد إزالة تكرار قائمة على البريد.
المكرَّر يُسقَط بالكامل: لا يُخزَّن شيء، ولا يتحرك أي عدّاد استهلاك، ولا شيء في الـ API يخبرك بحدوث ذلك. فالنداء أرجع 202 رغم ذلك، لأن إزالة التكرار تحدث بعد القبول. أي أن المكرَّر غير مرئي لك — ولّد دائمًا nonce جديدًا.
الـ nonce محروس على مرحلتين، بعمرين مختلفين:
لمدة ساعة واحدة يُرفض الـ nonce المعاد استعماله رفضًا صريحًا بـ
401 unauthorized"Nonce reused".وإلى الأبد بعد ذلك، يُقبل الـ nonce المُعاد تدويره بـ
202ثم يُهمَل بصمت — بلا خطأ، وبلا حدث.
مثال عملي: تتبع مشاهدات الصفحة (Node.js، خادمي)
import crypto from 'node:crypto';export async function trackEvent(name, properties = {}) {
const KEY_ID = process.env.DZ_PUBLIC_KEY;
const SECRET = process.env.DZ_SIGNING_SECRET;
const nonce = crypto.randomBytes(16).toString('hex');
const ts = Math.floor(Date.now() / 1000).toString();
const body = JSON.stringify({ name, properties, nonce });
const hash = crypto.createHash('sha256').update(body).digest('hex');
const sig = crypto.createHmac('sha256', SECRET).update(`${KEY_ID}\n${nonce}\n${ts}\n${hash}`).digest('hex'); await fetch('https://api.dzbuild.app/v1/events', {
method: 'POST',
headers: {
'Authorization': `DZ-Public ${KEY_ID}`,
'X-DZ-Timestamp': ts, 'X-DZ-Nonce': nonce, 'X-DZ-Signature': sig,
'Idempotency-Key': nonce, // إلزامية في كل POST
'Content-Type': 'application/json',
},
body,
});
}// داخل Express middleware:
app.use((req, res, next) => {
trackEvent('page_view', { path: req.path, ua: req.get('user-agent') }).catch(() => {});
next();
});
لاحظ أننا لا ننتظر النداء من middleware مشاهدات الصفحة — fire-and-forget لكي لا يُحظر طلب المستخدم. الـ API يردّ في ~30 مللي ثانية على أي حال، لكن هذا يحمي من مشاكل شبكة عابرة.
ما يُحسب من حصتك
كل نداء /v1/events يصل فعلًا يزيد usage.event.total و usage.event.billable. لا يوجد "قراءات مجانية ثم كتابات قابلة للفوترة" هنا — الأحداث قابلة للفوترة من الطلب الأول. أما المكرَّرات (نفس الـ nonce) فلا تحرّك أي عدّاد، لأنها لا تُخزَّن أصلًا.
إن ارتفع حجم الأحداث، اجمع من جانبك: خزّنها في طابور خاص، واطلق نداء /v1/events لكل حدث منطقي على دفعات من 1 (الـ API لا يقبل الدُّفعات). وكل نداء يُحسب ضمن حد الدقيقة الخاص بالمتجر، المشترك بين كل مفاتيحه.
الأخطاء
نفس /v1/signups. انظر الأخطاء. والثلاثة التي توقع الناس على هذه النقطة تحديدًا:
HTTP | الكود / الرسالة | السبب |
400 |
| الترويسة مفقودة |
400 |
| أطول من اللازم، أو يستعمل محارف خارج تلك المجموعة (محارف base64 وهي |
403 |
| المفتاح غير مُسجَّل في البرنامج التجريبي |
متى لا تستعمل /v1/events
لـ طلبات الواجهة — لوحة تحكم التاجر تسجّلها أصلًا، وتكرارها هنا يضخّم عدد أحداثك فقط. ولاحظ أن طلبات الواجهة لا تُطلق webhook
order.createdفي API v1؛ الطلبات المُنشأة عبرPOST /v1/ordersوحدها تفعل ذلك (انظر كتالوج الأحداث).لـ أحداث داخلية لا تتعلق ببيانات التاجر (استهلاك CPU، نتائج cache). استعمل APM حقيقيًا.
لـ أحجام ضخمة (أكثر من مليون حدث/يوم). ابنِ خط تحليلاتك واصدّر فقط التجميعات هنا.