מאפייני משתמש מותאמים
מאפייני משתמש הם מאפיינים שמתארים את המשתמשים שלכם. השתמשו בהם כדי להתאים מסרים, ליצור סגמנטים ולנתח את קהל המשתמשים.
מה הם מאפייני משתמש?
מאפיינים הם זוגות מפתח־ערך שמצורפים לפרופיל משתמש:
{
"userId": "user_123",
"attributes": {
"firstName": "John",
"lastName": "Doe",
"plan": "premium",
"signupDate": "2024-01-15",
"totalPurchases": 5,
"lastLoginDate": "2024-01-20",
"preferences": {
"newsletter": true,
"notifications": "email"
}
}
}
הגדרת מאפיינים
דרך SDK (צד הלקוח)
import JoryioSDK from '@joryio/web-sdk';
const joryio = new JoryioSDK({ sdkKey: 'jry_sdk_web_...' });
// Identify a user
joryio.identify('user_123');
// Set attributes separately
joryio.setAttributes({
firstName: 'John',
lastName: 'Doe',
plan: 'premium',
signupDate: '2024-01-15'
});
// Update attributes later
joryio.setAttributes({
plan: 'enterprise',
lastUpgrade: new Date().toISOString()
});
דרך API (צד השרת)
// Create or update user with attributes
fetch('https://api-eu1.joryio.com/api/users/track', {
method: 'POST',
headers: {
'Authorization': 'Bearer jry_live_your_api_key',
'Content-Type': 'application/json'
},
body: JSON.stringify({
attributes: {
externalId: 'user_123',
attributes: {
firstName: 'John',
plan: 'premium',
totalOrders: 10,
lifetimeValue: 1250.00
}
}
})
});
מאפיינים סטנדרטיים לעומת מותאמים
מאפיינים סטנדרטיים
שלחו תמיד מספרי טלפון בפורמט בינלאומי מלא (E.164): +, קידומת המדינה ואז המספר - למשל +972501234567. מספר בלי + נקרא לפי מדינת ברירת המחדל למספרי טלפון של סביבת העבודה; אם לא הוגדרה, או שאפשר לקרוא את הספרות בשתי דרכים, הוא נשמר כלא מאומת ולא משמש להודעות. איך מטופלים מספרי טלפון
שמורים על ידי Joryio (נשמרים בשורש):
userId- מזהה משתמש ייחודיemail- כתובת אימיילphone- מספר טלפוןexternalId- מזהה במערכת חיצוניתcreatedAt- זמן יצירת משתמשupdatedAt- זמן עדכון אחרון
מאפיינים מותאמים
כל מאפיין אחר שתגדירו (נשמר באובייקט attributes):
firstName,lastName,nameplan,subscription Tiercompany,industry,jobTitletotalPurchases,lifetimeValuepreferences,settings- וכל דבר נוסף שאתם צריכים!
סוגי נתונים
מאפיינים תומכים בסוגי נתונים מרובים:
מחרוזת (String)
{
firstName: "John",
plan: "premium",
country: "US"
}
מספר (Number)
{
age: 30,
totalPurchases: 15,
lifetimeValue: 1250.50
}
בוליאני (Boolean)
{
emailVerified: true,
newsletter: false,
isPremium: true
}
תאריך/חותמת זמן
{
signupDate: "2024-01-15",
lastLoginDate: "2024-01-20T10:30:00Z",
trialEndsAt: "2024-02-15T23:59:59Z"
}
לתאריכים, השתמשו בפורמט ISO 8601: YYYY-MM-DDTHH:mm:ssZ
מערך (Array)
{
tags: ["vip", "early-adopter"],
interests: ["technology", "sports", "music"],
purchasedProducts: ["product_1", "product_2"]
}
אובייקט/מקונן
{
preferences: {
theme: "dark",
language: "en",
notifications: {
email: true,
sms: false,
push: true
}
},
address: {
street: "123 Main St",
city: "San Francisco",
state: "CA",
zip: "94102"
}
}
כיצד נקבע הסוג
Joryio לעולם לא מנחשת לפי השם של השדה. הסוג נקבע לפי הסדר הזה:
- הוגדר - מישהו קבע את הסוג בעמוד המאפיינים (או בעמוד האירועים, עבור מאפייני אירוע). זה תמיד גובר.
- שדה מסחר סטנדרטי -
price,total,revenue,quantity,tax,shipping,discount,subtotalו-valueמטופלים כמספרים כברירת מחדל, בין אם שלחתם12.34או"12.34". מזהים כמוorder_idו-skuאינם ברשימה הזו במכוון: הם נראים לעיתים קרובות כמספרים, וקביעתם כמספר היא הסיבה שהזמנה כמו007מפסיקה להתאים. - הוסק מהנתונים שלכם - הסוג הנפוץ ביותר בדגימה, לכל אירוע בנפרד.
Product Added.stepו-Onboarding Step Tapped.stepמקבלים סוג נפרד, כך ששם שחוזר לשני דברים שונים אינו התנגשות.
כשהערכים לא מסכימים
אם יותר מכ-20% מהערכים הם מסוג אחר, המאפיין מוצג כ-מעורב יחד עם הספירות (למשל string 994 - number 448). Joryio לא בוחרת צד. היא משווה את הערכים כטקסט - מה שלעולם לא נותן תשובה שגויה, רק גסה - ומבקשת מכם לקבוע את הסוג.
קביעת הסוג מתקנת את ההשוואה גם עבור ערכים שכבר נשמרו: שדה שהוגדר כמספר משווה "12.34" ו-12.34 כאותו מספר, כך ש-price > 100 מפסיק להשוות טקסט (שבו "90" > "100" הוא אמת).
קביעת סוג משנה את אופן ההשוואה של הערכים. היא אינה כותבת מחדש את מה שנשמר - הנתונים ההיסטוריים שלכם שומרים בדיוק את הערכים ששלחתם.
מה עולה קביעת סוג
קביעת סוג היא החלטה כיצד לטפל באי־התאמה, לא דרך לסיים אותה. ערכים שלא ניתן לקרוא כסוג שבחרתם מפסיקים להתאים למסננים - והם נושרים משני צידיו של טווח.
נניח ש-step מכיל את המספרים 1, 2, 3 ברוב האירועים ואת המילים
"invite" ו-"photo" בחלקם, ואתם קובעים אותו כמספר:
| מסנן | איש קשר שה-step שלו הוא "invite" |
|---|---|
step > 1 | לא תואם |
step <= 1 | לא תואם |
step = 1 | לא תואם |
step שונה מ-1 | תואם |
step קיים | תואם |
כך ששתי שכבות שנועדו לחלק את הקהל לשניים - step > 1 ו-step <= 1 - משאירות
את אנשי הקשר האלה באף אחת מהן. בדיקת פיצול שנבנתה כך מאבדת אותם בשקט.
מספרים שנכתבו כטקסט תקינים: "12.34" נקרא כ-12.34 ומתאים כרגיל. רק ערכים
שאין להם קריאה כסוג שנבחר מושפעים.
רשימת המאפיינים מציגה כמה ערכים מושפעים לצד הסוג, כך שאי־ההתאמה נשארת גלויה גם אחרי שהחלטתם. התיקון הוא במקור - שלחו את הערך בצורה אחידה - כי שום דבר כאן לא כותב מחדש נתונים שכבר שלחתם.
שדות סטנדרטיים מקבלים סוג אוטומטית
לחלק מהשדות יש משמעות שאנחנו מגדירים ולא אתם בוחרים, והסוג שלהם קבוע:
- מאפייני פלטפורמה שהמערכת כותבת -
lastEventTime(תאריך, גם אם הוא נשמר כטקסט),total_purchases,ml_churn_score,is_purchase_overdue. - מאפייני מסחר סטנדרטיים -
price,total,revenue,quantity,tax,shipping,discount,subtotal,value.
אין צורך לקבוע אותם, ואי אפשר לשנות אותם. זה מכוון: אם אותו שדה סטנדרטי היה יכול להיות מספר בסביבת עבודה אחת וטקסט באחרת, שום דבר שנבנה מעליו - דוחות, המלצות, הכנסות - לא היה יכול להסתמך עליו.
אם אחד מהשמות האלה אומר משהו אחר בנתונים שלכם, שלחו אותו בשם אחר. price
שהוא בעצם תווית צריך להיות price_label. כל מה שמחוץ לרשימות האלה נתון לקביעתכם.
דוגמאות נפוצות למאפיינים
מסחר אלקטרוני
joryio.setAttributes({
// Account info
accountType: "premium",
memberSince: "2024-01-15",
// Purchase history
totalOrders: 15,
lastOrderDate: "2024-01-20",
lifetimeValue: 2500.00,
avgOrderValue: 166.67,
// Preferences
favoriteCategory: "electronics",
preferredShipping: "express",
// Engagement
cartAbandoned: false,
wishlistItems: 5,
reviewsWritten: 3
});
SaaS
joryio.setAttributes({
// Subscription
plan: "pro",
billingCycle: "monthly",
subscriptionStatus: "active",
trialEndsAt: "2024-02-15T23:59:59Z",
mrr: 99,
// Usage
loginCount: 45,
lastLoginDate: "2024-01-20",
featuresUsed: ["export", "api", "integrations"],
apiCallsThisMonth: 10500,
storageUsedGB: 15.5,
// Team
teamSize: 8,
role: "admin",
companyName: "Acme Corp"
});
מדיה/תוכן
joryio.setAttributes({
// Subscription
subscriptionTier: "premium",
contentAccessLevel: "unlimited",
// Engagement
articlesRead: 125,
videosWatched: 45,
podcastsListened: 30,
favoriteTopics: ["technology", "business"],
// Behavior
avgSessionDuration: 25.5,
lastVisit: "2024-01-20T14:30:00Z",
deviceType: "mobile"
});
עדכון מאפיינים
מיזוג לעומת החלפה
מיזוג (ברירת מחדל) - מעדכן שדות שצוינו:
// Initial attributes
{
firstName: "John",
plan: "free",
country: "US"
}
// Update attributes (merges with existing)
joryio.setAttributes({
plan: "premium"
});
// Result (plan updated, others preserved)
{
firstName: "John",
plan: "premium", // Updated
country: "US" // Preserved
}
קריאה ל־setAttributes() ממזגת מאפיינים חדשים עם קיימים. מאפיינים שלא צוינו נשמרים.
הגדלה/הפחתה
עבור מונים, הגדילו במקום לאחזר את הערך הנוכחי:
// Bad: Race condition possible
const current = await getUserAttribute('loginCount');
joryio.setAttributes({ loginCount: current + 1 });
// Good: Atomic increment
joryio.incrementAttribute('loginCount', 1);
// Decrement
joryio.incrementAttribute('creditsRemaining', -10);
מאפייני מערך
אפשר לשמור ולתפעל מערכים כערכי מאפיינים:
// Set array attribute
joryio.setAttributes({
tags: ['vip', 'early-adopter'],
interests: ['technology', 'sports']
});
// Add to array (only adds if value doesn't already exist)
joryio.addToArray('tags', 'premium');
// Result: ['vip', 'early-adopter', 'premium']
// Add duplicate (no-op, prevents duplicates)
joryio.addToArray('tags', 'vip');
// Result: ['vip', 'early-adopter', 'premium'] (unchanged)
// Remove from array
joryio.removeFromArray('tags', 'early-adopter');
// Result: ['vip', 'premium']
פרטי השיטות:
| שיטה | תיאור |
|---|---|
addToArray(key, value) | מוסיף ערך למערך אם הוא לא קיים (מונע כפילויות). יוצר מערך חדש אם המאפיין לא קיים. |
removeFromArray(key, value) | מסיר את כל המופעים של הערך מהמערך. מזהיר אם המאפיין אינו מערך. |
מאפייני מערך מתאימים ל:
- תגיות משתמשים:
['vip', 'trial', 'beta-tester'] - תחומי עניין:
['sports', 'technology', 'fashion'] - מוצרים שנרכשו:
['prod_123', 'prod_456'] - דגלי יכולות:
['feature-a', 'feature-b'] - תפקידים:
['admin', 'editor']
שימוש במאפיינים לסגמנטציה
צרו סגמנטים לפי מאפיינים:
מסנן מאפיין פשוט
plan equals "premium"
השוואה מספרית
lifetimeValue >= 1000
totalPurchases > 5
age between 25 and 45
מסננים לפי תאריך
signupDate is within last 30 days
trialEndsAt is within next 7 days
lastLoginDate is more than 14 days ago
התאמת מחרוזות
email contains "@company.com"
country equals "US"
firstName exists
plan is not "free"
מסנני מערך
tags contains "vip"
interests contains any of ["technology", "business"]
התאמה אישית של הודעות
השתמשו במאפיינים בתוכן קמפיינים:
התאמה אישית למייל
Hi {{firstName}},
Your {{plan}} plan includes these benefits:
...
{{#if trialEndsAt}}
Your trial ends on {{trialEndsAt}}. Upgrade now!
{{/if}}
תוכן דינמי
{{#if plan == "free"}}
<p>Upgrade to Premium for more features!</p>
{{else}}
<p>Thanks for being a {{plan}} member!</p>
{{/if}}
בלוקים מותנים
{{#if totalPurchases > 10}}
<div class="vip-offer">
As a valued customer, here's an exclusive offer...
</div>
{{/if}}
שיטות עבודה מומלצות למאפיינים
1. השתמשו בשמות תיאוריים
טוב:
{
subscriptionTier: "premium",
lifetimeValueUSD: 1250.00,
emailVerified: true
}
לא טוב:
{
sub: "p",
ltv: 1250,
verified: 1
}
2. היו עקביים
השתמשו באותה מוסכמה לשמות:
טוב (camelCase):
{
firstName: "John",
lastName: "Doe",
signupDate: "2024-01-15"
}
לא טוב (מעורב):
{
first_name: "John",
LastName: "Doe",
"signup-date": "2024-01-15"
}
3. השתמשו בסוגים מתאימים
טוב:
{
age: 30, // Number
isPremium: true, // Boolean
signupDate: "2024-01-15", // ISO Date String
tags: ["vip", "beta"] // Array
}
לא טוב:
{
age: "30", // String instead of number
isPremium: "true", // String instead of boolean
signupDate: 1705276800, // Timestamp instead of ISO
tags: "vip,beta" // String instead of array
}
4. אל תשמרו נתונים רגישים
לעולם אל תשמרו:
- סיסמאות או גיבובי סיסמאות
- מספרי כרטיס אשראי מלאים
- מספרי תעודת זהות
- פרטי בנק
- מידע רפואי
מותר לשמור:
- 4 ספרות אחרונות של כרטיס
- סוג אמצעי תשלום ("visa", "mastercard")
- טוקנים מוצפנים/מגובבים
- מידע פרופיל ציבורי
5. שמרו על שמות קצרים
טוב: plan, ltv, mrr
לא טוב: currentSubscriptionPlanTierLevel
שמות מאפיינים שמורים
הימנעו משימוש בשמות השמורים הבאים:
userId,user_id,idemailphonecreatedAt,created_atupdatedAt,updated_at$app_id,$platform(עם קידומת $)
עדכונים בכמות גדולה
עדכנו מאפיינים למספר משתמשים בבת אחת:
// API: Bulk update - each field of POST /users/track accepts an array (attributes: max 1000)
POST /users/track
{
"attributes": [
{
"externalId": "user_1",
"attributes": { "plan": "premium" }
},
{
"externalId": "user_2",
"attributes": { "plan": "enterprise" }
}
]
}
מגבלות מאפיינים
| מגבלה | ערך |
|---|---|
| מקסימום מאפיינים למשתמש | 200 |
| אורך מקסימלי לשם מאפיין | 100 תווים |
| אורך מקסימלי לערך מחרוזת | 10,000 תווים |
| אורך מקסימלי למערך | 100 פריטים |
| עומק קינון מקסימלי | 5 רמות |
פתרון בעיות
מאפיינים לא מופיעים
- בדקו את איות שם המאפיין
- ודאו שהמשתמש עבר identify
- הפעילו מצב debug כדי לראות את קריאות ה-API
- בדקו שגיאות API בתגובה
מאפיין לא מתעדכן
- ודאו שאתם משתמשים במיזוג (לא בהחלפה)
- בדקו שסוג הנתונים תואם
- ודאו ששם המאפיין נכון
- בדקו את מגבלות הקצב (rate limits)
סגמנטציה לא עובדת
- ודאו שהמאפיין קיים אצל המשתמשים
- בדקו את סוג הנתונים של המאפיין
- בדקו את לוגיקת המסנן על משתמשים מוכרים
- ודאו שערכי המאפיין תואמים למסנן במדויק