דלג לתוכן הראשי

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 לצד המחבר שלנו תשלח מכירה אחת בשני שמות ותראה הכנסה כפולה. מספר הכנסות שגוי פי 2 קשה הרבה יותר לזהות ממספר שהוא בבירור 0.

לכן הכלל הוא חוזה אחד מפורסם. אם ההזמנות לא מופיעות, הסיבה גלויה מיד בהטמעה - וניתנת לתיקון - במקום להיות שגויה בשקט במשך חודשים.

על הסכומים

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

Track Event

מעקב אחר אירוע בודד עם מאפיינים אופציונליים.

נקודת הקצה מקבלת שתי צורות גוף: אובייקט אירוע בודד (המתועד כאן) או מערך JSON חשוף של אובייקטי אירוע למעקב באצווה (עד 500) - ראו Track Multiple Events (array body).

Endpoint

POST /events/track

גוף בקשה

שדהסוגחובהתיאור
userIdstringכן*מזהה המשתמש שלכם. *נדרש אחד מ־userId, joryioUserId, anonymousId או userAlias
eventNamestringכןשם האירוע (עד 255 תווים)
propertiesobjectלאמאפייני האירוע (עד 200 מפתחות ברמה העליונה, 50KB, עומק קינון 5)
timestampstring או numberלאחותמת זמן (מחרוזת ISO 8601 או epoch במילישניות, ברירת מחדל: עכשיו)
joryioUserIdstringלאמזהה המשתמש הפנימי של Joryio - ה־id בן 24 התווים המוחזר בתגובות ה־API של משתמשים (חלופה ל־userId)
anonymousIdstringלאמזהה מבקר אנונימי (מזהה חלופי)
userAliasobjectלא{ aliasLabel, aliasName } - מזהה alias (חלופה ל־userId)
sessionIdstringלאמזהה session
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
}

הערות

  • אירועים מעובדים בצורה אסינכרונית
  • השתמשו בשמות אירועים עקביים (ראו שיטות עבודה מומלצות לשמות אירועים)
  • המאפיינים נוספים לאינדקס לצורך פילוח
  • חותמת זמן נלקחת מהשרת אם לא סופקה

Track Multiple Events (array body)

אין נקודת קצה נפרדת לאצווה: POST /events/track מקבל או אובייקט אירוע בודד או מערך JSON חשוף של אובייקטי אירוע (בלי אובייקט עוטף). צורת המערך עוקבת אחרי עד 500 אירועים בבקשה אחת.

Endpoint

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 לכשלים חלקיים

Query Events

שליפת אירועים עם סינון ועימוד. אין נקודת קצה לשליפת אירוע לפי מזהה - סננו את השאילתה הזו במקום.

Endpoint

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": ""
},
{
"event_id": "1c3e5a7b-9d2f-4b6c-8e0a-3f5d7b9c1e2a",
"user_id": "665f1e2a9b3c4d5e6f7a8b9d",
"anonymous_id": "",
"event_name": "Order Completed",
"properties": {
"orderId": "order_789",
"total": 149.99
},
"timestamp": "2024-01-19 10:15:00",
"session_id": "",
"device_id": ""
}
]

Event Aggregation

קבלת סטטיסטיקות אירועים מצטברות עם קיבוץ ומדדים.

Endpoint

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
},
{
"period": "2024-01-03T00:00:00Z",
"count": 38,
"sum_value": 3890.12
}
],
"total": 3
}
}

מדדים נתמכים

  • 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, clientEventId)255 תווים
המספר המרבי של מפתחות ברמה העליונה לאירוע200
הגודל המרבי של מאפיינים (JSON)50 KB
עומק הקינון המרבי5 רמות
מספר האירועים המרבי בבקשת מערך500

מגבלות קצב

ל־Events API אין כיום מגבלות קצב קבועות לכל נקודת קצה - ראו סקירת API: מגבלות קצב.


תגובות שגיאה

כל השגיאות משתמשות בגוף השגיאה הסטנדרטי - ראו סקירת API: תגובת שגיאה.

400 Bad Request - כשל תיקוף

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

400 Bad Request - מאפיינים גדולים מדי

{
"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. שמות אירועים עקביים

עקבו אחרי התבנית "Object + Past Tense Verb":

טוב: 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. טיפול בשגיאות בצורה אלגנטית

מימשו לוגיקת ניסיונות חוזרים עם backoff מעריכי:

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

דיבוג

הפעלת מצב Debug (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. עברו אל Users → חפשו משתמש
  2. לחצו על לשונית Activity
  3. ראו את כל האירועים שנאספו

תקלות נפוצות

אירועים לא מופיעים:

  • ודאו שמפתח ה־API נכון
  • ודאו שהמשתמש מזוהה
  • ודאו שהשם והמאפיינים תקינים
  • בדקו מגבלות קצב

מאפיינים לא מופיעים:

  • ודאו ששמות המאפיינים נכונים
  • בדקו שסוגי הנתונים נתמכים
  • הימנעו ממאפיינים שמורים (תחילית $)

SDKs

להטמעה קלה יותר, השתמשו ב־SDKs רשמיים:


צעדים הבאים