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
גוף בקשה
| שדה | סוג | חובה | תיאור |
|---|---|---|---|
userId | string | כן* | מזהה המשתמש שלכם. *נדרש אחד מ־userId, joryioUserId, anonymousId או userAlias |
eventName | string | כן | שם האירוע (עד 255 תווים) |
properties | object | לא | מאפייני האירוע (עד 200 מפתחות ברמה העליונה, 50KB, עומק קינון 5) |
timestamp | string או number | לא | חותמת זמן (מחרוזת ISO 8601 או epoch במילישניות, ברירת מחדל: עכשיו) |
joryioUserId | string | לא | מזהה המשתמש הפנימי של Joryio - ה־id בן 24 התווים המוחזר בתגובות ה־API של משתמשים (חלופה ל־userId) |
anonymousId | string | לא | מזהה מבקר אנונימי (מזהה חלופי) |
userAlias | object | לא | { aliasLabel, aliasName } - מזהה alias (חלופה ל־userId) |
sessionId | string | לא | מזהה session |
deviceId | string | לא | מזהה מכשיר |
clientEventId | string | לא | מזהה אירוע שנוצר בצד הלקוח - משמש כמזהה האירוע השמור, ולכן כפילויות מוסרות מניסיונות חוזרים עם אותו ערך |
דוגמת בקשה
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
פרמטרי שאילתה
| פרמטר | סוג | ברירת מחדל | תיאור |
|---|---|---|---|
userId | string | - | סינון לפי מזהה משתמש |
eventName | string | - | סינון לפי שם אירוע |
startDate | string | - | אירועים לאחר תאריך זה (ISO 8601) |
endDate | string | - | אירועים לפני תאריך זה (ISO 8601) |
limit | number | 100 | תוצאות לעמוד (לכל היותר 1000) |
offset | number | 0 | מספר אירועים לדילוג |
דוגמת בקשה
# 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
גוף בקשה
| שדה | סוג | חובה | תיאור |
|---|---|---|---|
eventName | string | כן | שם האירוע לסיכום |
startDate | string | לא | תאריך התחלה (ISO 8601) |
endDate | string | לא | תאריך סיום (ISO 8601) |
groupBy | string | לא | קיבוץ זמן: hour, day, week, month (ברירת מחדל: day) |
metrics | array | לא | מדדים לחישוב: count, sum, avg, min, max (ברירת מחדל: ['count']) |
sumField | string | לא | שם המפתח בתוך properties לחישוב סכום (למשל total) |
avgField | string | לא | שם המפתח בתוך properties לחישוב ממוצע |
eventProperties | object | לא | סינון לפי מאפייני אירוע |
דוגמת בקשה
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
});
אימות אירועים בלוח הבקרה
- עברו אל Users → חפשו משתמש
- לחצו על לשונית Activity
- ראו את כל האירועים שנאספו
תקלות נפוצות
אירועים לא מופיעים:
- ודאו שמפתח ה־API נכון
- ודאו שהמשתמש מזוהה
- ודאו שהשם והמאפיינים תקינים
- בדקו מגבלות קצב
מאפיינים לא מופיעים:
- ודאו ששמות המאפיינים נכונים
- בדקו שסוגי הנתונים נתמכים
- הימנעו ממאפיינים שמורים (תחילית $)
SDKs
להטמעה קלה יותר, השתמשו ב־SDKs רשמיים:
- Web SDK: מדריך שילוב
- iOS SDK: Swift Package / CocoaPods
- Android SDK: Gradle
- React Native SDK: npm install @joryio/react-native-sdk