تخطّ إلى المحتوى الرئيسي

Events API

تتبّع أحداث المستخدم وسلوكه برمجياً عبر REST API.

كل نقاط النهاية في هذه الصفحة نسبية إلى عنوان الأساس https://api-eu1.joryio.com. راجع نظرة عامة على API.

حدث الشراء

تقارير الإيرادات والإسناد وCLV والنماذج التنبؤية جميعها تقرأ حدثًا واحدًا. إذا أرسلت عمليات الشراء باسم مختلف، فلن تُحتسب في أي مكان.

اسم الحدثOrder Completed
الخصائص المطلوبةtotal, currency
موصى بهاtotal_base, base_currency, orderId
{
"eventName": "Order Completed",
"userId": "user_123",
"properties": {
"total": 149.90,
"currency": "EUR",
"total_base": 162.35,
"base_currency": "USD",
"orderId": "1024"
}
}

لماذا اسم واحد فقط

تستخدم منصات أخرى أسماء أخرى - Placed Order (Klaviyo) وpurchase (GA4). نحن لا نقبلها عمدًا، لأن قبول عدة أسماء يعني جمعها معًا: متجر يشغّل وسم GA4 إلى جانب موصّلنا سيرسل عملية بيع واحدة باسمين ويرى إيراداته مضاعفة. رقم إيرادات خاطئ بمقدار الضعف أصعب بكثير في الاكتشاف من رقم يساوي صفرًا بوضوح.

لذلك القاعدة هي عقد واحد منشور. إذا لم تظهر الطلبات، يكون السبب واضحًا فورًا عند الإعداد - وقابلًا للإصلاح - بدلًا من أن يكون خاطئًا بصمت لأشهر.

عن المبالغ

total وtotal_base رقمان مختلفان، وليسا بديلين:

  • total - ما دفعه العميل بالعملة التي دفع بها.
  • total_base + base_currency - الطلب نفسه محوّلًا إلى عملة تقاريرك. أرسلهما إذا كنت تبيع بأكثر من عملة، لتُجمع الإجماليات بشكل صحيح.

أرسل total وحده إذا كانت لديك عملة واحدة. orderId اختياري لكنه موصى به: فهو يمنع ازدواج طلب يصل أكثر من مرة (إعادة محاولة، تحديث صفحة الدفع).

إذا كنت ترسل بالفعل اسمًا آخر

تُحفظ أحداثك السابقة، لكنها لا تُعامل كطلبات. حوّل الطلبات الجديدة إلى Order Completed، وتبدأ تقارير الإيرادات من تلك النقطة. نحن لا نعيد كتابة الأحداث القديمة، لذا لا يُعاد تفسير أي شيء بصمت.

المصادقة

تتطلب جميع الطلبات مصادقة بمفتاح API:

Authorization: Bearer jry_live_your_api_key_here
Content-Type: application/json

تتبع حدث

تتبّع حدثاً واحداً لمستخدم مع خصائص اختيارية.

تقبل نقطة النهاية هذه شكلين للنص: كائن حدث واحد، الموثق هنا، أو مصفوفة JSON مجردة من كائنات الأحداث للتتبع على دفعات، بحد أقصى 500. راجع تتبع أحداث متعددة، نص مصفوفة.

نقطة النهاية

POST /events/track

نص الطلب

الحقلالنوعمطلوبالوصف
userIdstringنعم*معرّف المستخدم لديك. يلزم واحد من userId أو joryioUserId أو anonymousId أو userAlias
eventNamestringنعماسم الحدث، بحد أقصى 255 حرفاً
propertiesobjectلاخصائص الحدث، 200 مفتاح علوي كحد أقصى، 50KB وعمق تداخل 5
timestampstring أو numberلاوقت الحدث؛ سلسلة ISO 8601 أو ميلي ثانية epoch، والافتراضي الآن
joryioUserIdstringلامعرّف المستخدم الداخلي في Joryio، وهو id سداسي من 24 حرفاً في استجابات Users API، بديل لـ userId
anonymousIdstringلامعرّف زائر مجهول، بديل
userAliasobjectلا{ aliasLabel, aliasName }، معرّف alias بديل لـ userId
sessionIdstringلامعرّف الجلسة
deviceIdstringلامعرّف الجهاز
clientEventIdstringلامعرّف حدث يولده العميل؛ يستخدم كمعرّف الحدث المخزن، فتزال تكرارات إعادة المحاولة بالقيمة نفسها

مثال لطلب

curl -X POST https://api-eu1.joryio.com/events/track \
-H "Authorization: Bearer jry_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"userId": "user_123",
"eventName": "Order Completed",
"properties": {
"orderId": "order_456",
"total": 99.99,
"currency": "USD",
"items": 3,
"paymentMethod": "credit_card"
},
"timestamp": "2024-01-20T14:30:00.000Z"
}'

الاستجابة

يعيد شكل الكائن الواحد معرّف الحدث المخزن:

{
"eventId": "9b2f6c1e-4a8d-4f0b-9c3d-2e1f5a6b7c8d",
"success": true
}

ملاحظات

  • تعالج الأحداث بصورة غير متزامنة.
  • استخدم تسمية أحداث متسقة. راجع أفضل ممارسات تسمية الأحداث.
  • تُفهرس الخصائص لاستخدامها في التقسيم.
  • يستخدم الطابع الزمني وقت الخادم إن لم تقدمه.

تتبع أحداث متعددة، نص مصفوفة

لا توجد نقطة نهاية دفعات منفصلة: يقبل POST /events/track إما كائن حدث واحداً أو مصفوفة JSON مجردة من كائنات الأحداث، بلا كائن غلاف. يتتبع شكل المصفوفة حتى 500 حدث في طلب واحد.

نقطة النهاية

POST /events/track

نص الطلب

مصفوفة JSON بحد أقصى 500 عنصر. يتبع كل عنصر تنسيق الكائن الواحد نفسه.

يتحقق النظام من كل عنصر بالكامل. يُبلغ عن العنصر غير الصالح في rejected بفهرسه في المصفوفة، ولا يُقبل بصمت، في حين تستمر معالجة العناصر الصالحة الأخرى.

مثال لطلب

curl -X POST https://api-eu1.joryio.com/events/track \
-H "Authorization: Bearer jry_live_your_api_key" \
-H "Content-Type: application/json" \
-d '[
{
"userId": "user_123",
"eventName": "Product Viewed",
"properties": {
"productId": "prod_456",
"price": 49.99
}
},
{
"userId": "user_123",
"eventName": "Added To Cart",
"properties": {
"productId": "prod_456",
"quantity": 1
}
},
{
"userId": "user_456",
"eventName": "Page Viewed",
"properties": {
"page": "/pricing"
}
}
]'

الاستجابة

بخلاف شكل الكائن، الذي يعيد { eventId, success }، يعيد شكل المصفوفة ملخصاً مجمعاً:

{
"processed": 3,
"accepted": 3,
"rejected": []
}
الحقلالوصف
processedعدد العناصر التي استقبلتها مصفوفة الطلب
acceptedالأحداث المسجلة فعلياً
rejectedفشل لكل عنصر: index موضعه في مصفوفة الطلب وname اسم الحدث إن وجد وreason السبب

مثال لعنصر واحد غير صالح:

{
"processed": 3,
"accepted": 2,
"rejected": [
{
"index": 1,
"name": "Added To Cart",
"reason": "property hacker should not exist"
}
]
}

الحدود

  • 500 حدث كحد أقصى في الطلب؛ يعيد الزائد 400، كما تعيد المصفوفة الفارغة 400.
  • يتبع كل حدث تنسيق الكائن الواحد.
  • معالجة الدفعة ليست ذرية: تُسجل الأحداث الصالحة حتى عند رفض بعض العناصر. افحص rejected للفشل الجزئي.

الاستعلام عن الأحداث

استرجع الأحداث بالتصفية والترقيم. لا توجد نقطة نهاية لجلب حدث بمعرّفه؛ صفِّ هذا الاستعلام بدلاً منها.

نقطة النهاية

GET /events/query

معاملات الاستعلام

المعاملالنوعالافتراضيالوصف
userIdstring-تصفية بمعرّف المستخدم
eventNamestring-تصفية باسم الحدث
startDatestring-الأحداث بعد هذا التاريخ، ISO 8601
endDatestring-الأحداث قبل هذا التاريخ، ISO 8601
limitnumber100النتائج في الصفحة، بحد أقصى 1000
offsetnumber0عدد الأحداث التي يجب تجاوزها

مثال لطلب

# Get all "Order Completed" events in January 2024
curl -X GET "https://api-eu1.joryio.com/events/query?eventName=Order+Completed&startDate=2024-01-01T00:00:00Z&endDate=2024-02-01T00:00:00Z&limit=100" \
-H "Authorization: Bearer jry_live_your_api_key"

الاستجابة

مصفوفة JSON مجردة، الأحدث أولاً. تستخدم حقول الحدث snake_case لأنها من مخزن التحليلات:

[
{
"event_id": "9b2f6c1e-4a8d-4f0b-9c3d-2e1f5a6b7c8d",
"user_id": "665f1e2a9b3c4d5e6f7a8b9c",
"anonymous_id": "",
"event_name": "Order Completed",
"properties": {
"orderId": "order_456",
"total": 99.99
},
"timestamp": "2024-01-20 14:30:00",
"session_id": "",
"device_id": ""
}
]

تجميع الأحداث

احصل على إحصاءات أحداث مجمعة بالتجميع والمقاييس.

نقطة النهاية

POST /events/aggregate

نص الطلب

الحقلالنوعمطلوبالوصف
eventNamestringنعماسم الحدث المراد تجميعه
startDatestringلاتاريخ البدء، ISO 8601
endDatestringلاتاريخ النهاية، ISO 8601
groupBystringلاتجميع زمني: hour أو day أو week أو month، الافتراضي day
metricsarrayلاالمقاييس: count وsum وavg وmin وmax، الافتراضي ['count']
sumFieldstringلااسم مفتاح properties للجمع أو التجميع، مثل total
avgFieldstringلااسم مفتاح properties لحساب المتوسط
eventPropertiesobjectلاتصفية بخصائص الحدث

مثال لطلب

curl -X POST https://api-eu1.joryio.com/events/aggregate \
-H "Authorization: Bearer jry_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"eventName": "Order Completed",
"startDate": "2024-01-01T00:00:00Z",
"endDate": "2024-02-01T00:00:00Z",
"groupBy": "day",
"metrics": ["count", "sum"],
"sumField": "total"
}'

الاستجابة

{
"success": true,
"data": {
"eventName": "Order Completed",
"groupBy": "day",
"metrics": ["count", "sum"],
"results": [
{
"period": "2024-01-01T00:00:00Z",
"count": 45,
"sum_value": 4567.89
},
{
"period": "2024-01-02T00:00:00Z",
"count": 52,
"sum_value": 5123.45
}
],
"total": 2
}
}

المقاييس المدعومة

  • count: العدد الإجمالي للأحداث.
  • sum: مجموع قيم الحقل المحدد.
  • avg: متوسط قيم الحقل المحدد.
  • min: أدنى قيمة للحقل المحدد.
  • max: أعلى قيمة للحقل المحدد.

مثال: تحليل الإيرادات

# Get daily revenue from purchases
curl -X POST https://api-eu1.joryio.com/events/aggregate \
-H "Authorization: Bearer jry_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"eventName": "Order Completed",
"startDate": "2024-01-01T00:00:00Z",
"endDate": "2024-01-31T00:00:00Z",
"groupBy": "day",
"metrics": ["count", "sum", "avg"],
"sumField": "total"
}'

مثال: استخدام ميزة بحسب الساعة

# Track feature usage patterns by hour
curl -X POST https://api-eu1.joryio.com/events/aggregate \
-H "Authorization: Bearer jry_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"eventName": "Feature Used",
"startDate": "2024-01-20T00:00:00Z",
"endDate": "2024-01-21T00:00:00Z",
"groupBy": "hour",
"metrics": ["count"]
}'

أحداث شائعة

أحداث التجارة الإلكترونية

// Product Viewed
POST /events/track
{
"userId": "user_123",
"eventName": "Product Viewed",
"properties": {
"productId": "prod_456",
"productName": "Premium Plan",
"category": "Subscription",
"price": 99.99,
"currency": "USD"
}
}

// Added To Cart
POST /events/track
{
"userId": "user_123",
"eventName": "Added To Cart",
"properties": {
"productId": "prod_456",
"quantity": 1,
"price": 99.99
}
}

// Order Completed
POST /events/track
{
"userId": "user_123",
"eventName": "Order Completed",
"properties": {
"orderId": "order_789",
"total": 249.99,
"currency": "USD",
"itemCount": 3,
"discount": 25.00,
"paymentMethod": "credit_card"
}
}

أحداث دورة حياة المستخدم

// Signup Completed
POST /events/track
{
"userId": "user_123",
"eventName": "Signup Completed",
"properties": {
"method": "email",
"source": "homepage_cta"
}
}

// Onboarding Completed
POST /events/track
{
"userId": "user_123",
"eventName": "Onboarding Completed",
"properties": {
"stepsCompleted": 5,
"timeSpent": "8m 30s"
}
}

// Trial Started
POST /events/track
{
"userId": "user_123",
"eventName": "Trial Started",
"properties": {
"plan": "premium",
"trialDays": 14
}
}

أحداث التفاعل

// Feature Used
POST /events/track
{
"userId": "user_123",
"eventName": "Feature Used",
"properties": {
"featureName": "export",
"exportFormat": "csv",
"recordCount": 1500
}
}

// Page Viewed
POST /events/track
{
"userId": "user_123",
"eventName": "Page Viewed",
"properties": {
"page": "/pricing",
"category": "Marketing",
"referrer": "google"
}
}

خصائص الحدث

أفضل الممارسات

استخدم أسماء خصائص وصفية.

جيد:

{
"properties": {
"productId": "prod_123",
"productName": "Premium Plan",
"price": 99.99,
"currency": "USD"
}
}

غير جيد:

{
"properties": {
"pid": "prod_123",
"n": "Premium Plan",
"p": 99.99
}
}

أنواع البيانات المدعومة

{
"properties": {
"string": "value",
"number": 99.99,
"integer": 5,
"boolean": true,
"date": "2024-01-15T10:30:00Z",
"array": ["tag1", "tag2"],
"object": {
"nested": "value",
"deep": {
"property": "value"
}
}
}
}

الخصائص المحجوزة

الخصائص التي تبدأ بـ $ محجوزة للنظام:

  • $app_id - معرّف التطبيق.
  • $app_name - اسم التطبيق.
  • $platform - المنصة، web أو ios أو android.
  • $session_id - معرّف الجلسة.
  • $anonymous_id - معرّف المستخدم المجهول.

لا تستخدم هذه الأسماء لخصائص مخصصة.


حدود الأحداث

حدود الحجم

الحدالقيمة
أقصى طول لاسم الحدث255 حرفاً
أقصى طول للمعرّف، userId وanonymousId وsessionId وdeviceId وclientEventId255 حرفاً
أقصى مفاتيح خصائص عليا لكل حدث200
أقصى حجم للخصائص، JSON50 KB
أقصى عمق لتداخل الخصائص5 مستويات
أقصى أحداث في طلب نص مصفوفة500

حدود المعدل

لا تملك Events API اليوم حدود معدل ثابتة لكل نقطة نهاية. راجع نظرة API العامة: حدود المعدل.


استجابات الأخطاء

تستخدم كل الأخطاء نص الخطأ القياسي. راجع نظرة API العامة: استجابة الخطأ.

400 طلب غير صالح: فشل التحقق

{
"statusCode": 400,
"message": "Bad Request Exception",
"timestamp": "2026-01-15T10:30:00.000Z",
"path": "/events/track",
"errors": [
"eventName should not be empty"
]
}

400 طلب غير صالح: خصائص ضخمة

{
"statusCode": 400,
"message": "Event properties exceed maximum size of 50KB (received 63KB)",
"timestamp": "2026-01-15T10:30:00.000Z",
"path": "/events/track"
}

أفضل الممارسات

1. اجمع الأحداث عند الإمكان

جيد: أرسل أحداثاً متعددة بنص مصفوفة.

await fetch('/events/track', {
method: 'POST',
body: JSON.stringify([event1, event2, event3])
});

غير جيد: طلبات منفردة.

await fetch('/events/track', { method: 'POST', body: JSON.stringify(event1) });
await fetch('/events/track', { method: 'POST', body: JSON.stringify(event2) });
await fetch('/events/track', { method: 'POST', body: JSON.stringify(event3) });

2. استخدم تسمية أحداث متسقة

اتبع نمط «كائن + فعل بصيغة الماضي»:

جيد: Product Viewed وOrder Completed وTrial Started.

غير جيد: view_product وclicked وuser_action_123.

3. ضمّن طوابع زمنية

للأحداث التاريخية، ضمّن وقتاً دقيقاً دائماً:

{
"userId": "user_123",
"eventName": "Order Completed",
"timestamp": "2024-01-15T10:30:00.000Z", // Actual event time
"properties": { ... }
}

4. أبقِ الخصائص مختصرة

ضمّن الخصائص ذات الصلة فقط.

جيد:

{
"eventName": "Order Completed",
"properties": {
"orderId": "order_123",
"total": 99.99,
"currency": "USD"
}
}

غير جيد:

{
"eventName": "Order Completed",
"properties": {
"orderId": "order_123",
"total": 99.99,
"currency": "USD",
"userAgent": "Mozilla/5.0...", // Too much detail
"sessionData": { /* large object */ },
"cookies": [ /* array of cookies */ ]
}
}

5. تعامل مع الأخطاء بأمان

نفذ منطق إعادة المحاولة بتراجع أسي:

async function trackWithRetry(event, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
const response = await fetch('/events/track', {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(event)
});

if (response.ok) return await response.json();

if (response.status === 429) {
const retryAfter = response.headers.get('Retry-After') || Math.pow(2, i);
await sleep(retryAfter * 1000);
continue;
}

throw new Error(`HTTP ${response.status}`);
} catch (error) {
if (i === maxRetries - 1) throw error;
await sleep(Math.pow(2, i) * 1000); // 1s, 2s, 4s
}
}
}

التصحيح

تفعيل وضع التصحيح في SDK

عند استخدام Web SDK:

import JoryioSDK from '@joryio/web-sdk';

const joryio = new JoryioSDK({
sdkKey: 'jry_sdk_web_...',
enableDebug: true // Log all events to console
});

التحقق من الأحداث في لوحة التحكم

  1. انتقل إلى المستخدمون وابحث عن المستخدم.
  2. انقر تبويب النشاط.
  3. راجع جميع الأحداث المتتبعة.

مشاكل شائعة

الأحداث لا تظهر:

  • تحقق من صحة مفتاح API.
  • تحقق من تعريف المستخدم.
  • تأكد من صحة اسم الحدث وخصائصه.
  • تحقق من حدود المعدل.

الخصائص لا تظهر:

  • تحقق من صحة أسماء الخصائص.
  • تحقق من دعم أنواع البيانات.
  • تجنب أسماء الخصائص المحجوزة التي تبدأ بـ $.

SDKs

للتكامل الأسهل، استخدم SDKs الرسمية:


الخطوات التالية