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

הזרמת נתונים

הזרמת נתונים מעבירה אירועים מ־Joryio ליעדים חיצוניים כמעט בזמן אמת. כל זרם מקשר בין יעד לקבוצת אירועים, ו־Joryio מוסרת ליעד את האירועים התואמים באצוות.

עברו אל Data → Data Streaming כדי לנהל את הזרמים שלכם.

יעדים​

יעדסוגמה הוא עושה
Webhookנקודת קצה של HTTPשליחת כל אירוע בבקשת POST כאובייקט JSON לכל כתובת HTTPS
Snowflakeמחסן נתוניםטעינה רציפה של אירועים לטבלת Snowflake
BigQueryמחסן נתוניםהזרמת אירועים למערך נתונים ב-BigQuery
Amazon Redshiftמחסן נתוניםטעינת אירועים לאשכול Amazon Redshift
Amazon S3אחסון אובייקטיםכתיבת קובצי JSON / NDJSON באצוות ל־Bucket
Kafkaזרם אירועיםפרסום אירועים ב־topic של Kafka
Mixpanelאנליטיקת מוצרהעברת אירועים לפרויקט Mixpanel
Amplitudeאנליטיקת מוצרהעברת אירועים לפרויקט Amplitude

שדות חיבור​

לכל יעד יש פרטי חיבור משלו. נתונים סודיים (סיסמאות, מפתחות, טוקנים, JSON של חשבון שירות וערכי כותרות של Webhook) מוצפנים בעת האחסון ולעולם לא מוצגים שוב - ראו הרשאות מינימליות לפרטי גישה.

  • Webhook - כתובת URL, סוד לחתימה (אופציונלי), כותרות נוספות (אופציונלי, אובייקט JSON כגון {"Authorization": "Bearer <token>"}; הערכים מטופלים כסודות)
  • Snowflake - Account, Username, Password, Role (אופציונלי - התפקיד שבו רצות הפקודות; כשהוא ריק, חל תפקיד ברירת המחדל של המשתמש), Warehouse, Database, Schema, Table
  • BigQuery - Project ID, Dataset ID, Table ID, Service Account JSON
  • Amazon Redshift - Host, Port, Database, User, Password, Schema, Table
  • Amazon S3 - Bucket, Prefix, Region, Endpoint (אופציונלי, לאחסון תואם-S3), Access Key ID, Secret Access Key
  • Kafka - Brokers, Topic, SASL Username/Password, SSL
  • Mixpanel - Project Token, Region (US / EU / India)
  • Amplitude - API Key, Region (US / EU)

הרשאות מינימליות לפרטי גישה​

תנו לכל זרם פרטי גישה משלו, שיכולים לעשות דבר אחד בלבד: לכתוב לטבלה, לנתיב בדלי או לנושא שאליו הזרם מוסר. אם פרטי הגישה ידלפו אי פעם, זה כל מה שאפשר לעשות איתם - אי אפשר לקרוא בעזרתם את הנתונים שלכם או לגעת בשום דבר אחר. הדוגמאות שלהלן משתמשות בשמות לדוגמה (example-bucket, analytics.joryio_events, joryio-events); החליפו אותם בשמות שלכם.

איך Joryio שומרת פרטי גישה​

  • מוצפנים. סיסמאות, מפתחות, טוקנים, JSON של חשבון שירות וערכי כותרות של Webhook מוצפנים לפני שהם נשמרים.
  • לעולם לא מוצגים שוב. העורך וה-API מציגים סוד שמור כ-********. אף אחד - כולל אתם וצוות Joryio - לא יכול לקרוא אותו בחזרה בלוח הבקרה או ב-API.
  • נשמרים כשעורכים שדות אחרים. שדה סוד שמשאירים ריק (או ********) שומר על הערך השמור; רק ערך שמקלידים מחליף אותו. שינוי שם של זרם או של האירועים שלו לעולם לא נוגע בפרטי הגישה.
  • נמחקים יחד עם הזרם. מחיקת זרם מוחקת את פרטי הגישה השמורים שלו. כשהחשבון נמחק, הם נמחקים יחד עם שאר נתוני החשבון.

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

גם כותרות Webhook הן סודות. הזינו אותן כאובייקט JSON, למשל {"Authorization": "Bearer <token>"}. שמות הכותרות נשארים גלויים; כל ערך מוצפן ומוצג כ-********. בעריכת הזרם, השאירו ******** כדי לשמור ערך, הקלידו ערך חדש כדי להחליף אותו, או הסירו כותרת כדי למחוק אותה. השתמשו בטוקן שהונפק ל-Joryio בלבד, כך שתוכלו לבטל אותו בלי להשפיע על שום דבר אחר.

Amazon S3​

צרו משתמש IAM (או תפקיד) עבור Joryio שההרשאה היחידה שלו היא s3:PutObject על הדלי והקידומת של הזרם, והשתמשו במפתח הגישה שלו בזרם. Joryio כותבת אובייקטים תחת <prefix>/<date>/, כך שעם הקידומת joryio-events:

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "JoryioWriteEvents",
"Effect": "Allow",
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::example-bucket/joryio-events/*"
}
]
}

בדיקת חיבור מוודאת שהדלי קיים, ו-AWS מתירה זאת רק עם s3:ListBucket על הדלי. הרשאה זו מאפשרת למפתח לראות את שמות האובייקטים בדלי, ולכן היא אופציונלית: בלעדיה המסירה עובדת ורק הבדיקה מדווחת על כישלון. כדי לאפשר את הבדיקה, הוסיפו את ההצהרה הבאה:

{
"Sid": "JoryioTestConnection",
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::example-bucket"
}

לאחסון תואם-S3, צרו טוקן המוגבל לדלי האחד עם הרשאת כתיבת אובייקטים בלבד.

Amazon Redshift​

צרו משתמש מסד נתונים ייעודי שיכול רק להוסיף שורות לטבלה של הזרם:

CREATE USER joryio_loader PASSWORD '<strong-password>';
GRANT USAGE ON SCHEMA analytics TO joryio_loader;
GRANT INSERT ON TABLE analytics.joryio_events TO joryio_loader;

הזינו joryio_loader בשדה User של הזרם.

Snowflake​

צרו תפקיד שיכול רק להוסיף שורות לטבלה של הזרם (בתוספת הרשאות USAGE ש-Snowflake דורשת כדי להגיע אליה), ומשתמש שיש לו את התפקיד הזה:

CREATE ROLE JORYIO_WRITER;
GRANT USAGE ON WAREHOUSE LOAD_WH TO ROLE JORYIO_WRITER;
GRANT USAGE ON DATABASE ANALYTICS TO ROLE JORYIO_WRITER;
GRANT USAGE ON SCHEMA ANALYTICS.EVENTS TO ROLE JORYIO_WRITER;
GRANT INSERT ON TABLE ANALYTICS.EVENTS.JORYIO_EVENTS TO ROLE JORYIO_WRITER;

CREATE USER JORYIO_LOADER PASSWORD = '<strong-password>'
DEFAULT_ROLE = JORYIO_WRITER DEFAULT_WAREHOUSE = LOAD_WH;
GRANT ROLE JORYIO_WRITER TO USER JORYIO_LOADER;

הזינו JORYIO_LOADER בשדה Username ו-JORYIO_WRITER בשדה Role. השדה Role אופציונלי: כשהוא מוגדר, Joryio מריצה כל פקודה בתפקיד הזה; כשהוא ריק, חל תפקיד ברירת המחדל של המשתמש.

BigQuery​

צרו חשבון שירות עבור Joryio והעניקו לו BigQuery Data Editor (roles/bigquery.dataEditor) על מערך הנתונים של הזרם בלבד - בהגדרות השיתוף של מערך הנתונים, לא ברמת הפרויקט. לאחר מכן צרו עבורו מפתח JSON והדביקו אותו בשדה Service Account JSON.

Joryio מזרימה שורות באמצעות ה-API של BigQuery להוספת שורות, וקוראת את המטא-נתונים של הטבלה כדי לבדוק את החיבור; אף אחד מהם לא מריץ משימת שאילתה, ולכן אין צורך ב-BigQuery Job User. הרשאת Data Editor על מערך נתונים מאפשרת לשנות גם טבלאות אחרות בו, ולכן שמרו את טבלת הזרם במערך נתונים משלה, או העניקו תפקיד מותאם עם bigquery.tables.get ו-bigquery.tables.updateData בלבד על הטבלה.

Kafka​

צרו משתמש SASL עבור Joryio (Joryio מזדהה באמצעות SASL/PLAIN) והתירו לו רק WRITE ו-DESCRIBE על הנושא של הזרם. צרו את הנושא בעצמכם מראש - Joryio לא צריכה הרשאה ליצור נושאים.

kafka-acls --bootstrap-server <broker:port> --command-config admin.properties \
--add --allow-principal User:joryio \
--operation Write --operation Describe \
--topic joryio-events

Mixpanel, Amplitude ו-Webhooks​

  • Mixpanel - ה-Project Token יכול רק לשלוח אירועים לפרויקט שלו; הוא לא יכול לקרוא נתונים. השתמשו בטוקן של הפרויקט שהזרם אמור להזין.
  • Amplitude - ה-API Key הוא מפתח הקליטה של פרויקט אחד. השתמשו בפרויקט שהזרם אמור להזין.
  • Webhook - השתמשו בסוד חתימה ובטוקן Authorization שהונפקו ל-Joryio בלבד, וקבלו רק את מה שהזרם שולח.

יצירת זרם​

  1. עברו אל Data → Data Streaming ולחצו על Create Stream.
  2. הזינו Name לזרם (השם יוצג ברשימת הזרמים) ובחרו destination.
  3. מלאו את שדות ה־connection של היעד.
  4. בחרו payload format - ‏JSON (אובייקט אחד לכל אירוע) או NDJSON (אירוע אחד בכל שורה, כשהאירועים מופרדים בשורות חדשות).
  5. בחרו אילו events להזרים (ראו בהמשך).
  6. בדקו את שורת הסיכום ולחצו על Create Stream.

בחירת אירועים​

אתם קובעים בדיוק אילו אירועים הזרם מקבל:

  • כל האירועים - הפעילו כדי להזרים כל אירוע קיים ועתידי. כבו כדי לבחור אירועים מסוימים.
  • הודעות, לפי ערוץ - אירועי הודעות נבחרים לכל ערוץ בנפרד (ראו בחירה לפי ערוץ).
  • קבוצות אחרות - In-App, מסעות, קמפיינים, כרטיסי Wallet, מסחר אלקטרוני וזהות. סמנו קבוצה שלמה או אירועים בודדים.
  • אירועים מותאמים אישית - תחת Custom Event, חפשו או הקלידו אירועים שאתם עוקבים אחריהם (אלה שנשלחים עם track(), כמו purchase או page_view). הבורר מציג את האירועים שסביבת העבודה שלכם באמת תיעדה; אפשר גם להקליד אירוע שעדיין לא תועד וללחוץ Add.

בחירה לפי ערוץ​

העורך מציג אזור לכל ערוץ - דוא"ל, SMS, WhatsApp, פוש, Viber ו-Webhook - ובו רק האירועים שקיימים בערוץ הזה (אין "פתיחת SMS"). בתוך כל אזור האירועים מקובצים:

קבוצהאפשרויות
מעורבותשליחה, מסירה, פתיחה (דוא"ל), קריאה (WhatsApp), הקלקה
בעיותהחזרה, סימון כספאם, כישלון, לא נשלחה, דחייה, מענה אוטומטי (דוא"ל)
הסכמההסרה מרשימה, הרשמה
נכנסותהודעה נכנסת (SMS, WhatsApp, Viber)

לכל אזור יש תיבת בחירת הכול משלו, ו-בחירת הכול בכל הערוצים מסמנת הכול בבת אחת. ליד כל אפשרות מוצגת הערכת נפח חודשית - כמה אירועים כאלה סביבת העבודה שלכם תיעדה ב-30 הימים האחרונים - כדי שתראו לפני השמירה מה הבחירה תעלה ליעד.

שליחה, מסירה ופתיחה מסומנות נפח גבוה: כל אחת היא שורה אחת לכל הודעה. זרם חדש מתחיל עם כל שאר האפשרויות מסומנות, ושלוש אלה נשארות לבחירתכם.

פורמט הנתונים לא משתנה. סימון מסירה תחת SMS מזרים את האירוע הרגיל message.delivered שבו המאפיין channel הוא sms - אותו שם ואותם ערכים שמאגר האירועים, ה-REST API ואינטגרציות ה-Webhook משתמשים בהם. הודעות נכנסות שומרות על שמותיהן: sms.message.received, whatsapp.message.received ו-viber.message.received.

זרם שנוצר דרך ה-API עדיין יכול לבחור אירוע הודעה לפי שם ("events": ["message.delivered"], ואפשר לצמצם עם "channels"). זה ממשיך לעבוד, והעורך מציג אותו כאותו אירוע מסומן בכל ערוץ שהוא מכסה.

שינוי מצב הרשמה​

לאזור הרשמות יש אפשרות אחת, שינוי מצב הרשמה: כל הצטרפות והסרה בכל ערוץ ורשימה. היא מזרימה את שני אירועי ההסכמה ש-Joryio כבר מתעדת, כך ששום דבר לא נספר פעמיים:

  • message.subscribed - אדם נרשם לערוץ או לרשימה. status ו-previousStatus מתארים את השינוי, scope הוא channel או list (עם listId), ו-source מציין איך זה קרה (api, dashboard, preference_center, double_opt_in, keyword, הרשמה בחנות או בטופס וכן הלאה).
  • message.unsubscribed - אדם הסיר את עצמו. scope הוא channel, list או global, reason מציין איך זה הגיע (link, keyword, ...) ו-unsubscribeSource מציין את הדרך המדויקת (כפתור ההסרה של אפליקציית הדוא"ל, הכפתור בדף, מרכז ההעדפות, תשובת STOP).

החזרות ודיווחי ספאם הם אירועים נפרדים (message.bounced, message.spamreport). ייבוא אנשי קשר, סנכרון ממחסן נתונים וסנכרון ראשוני של חנות כותבים הסכמה בכמויות ואינם יוצרים את האירועים האלה.

אישורי מסירה​

דוחות מסירה, החזרות, דיווחי ספאם, הסרות מרשימה והודעות ש-Joryio לא שלחה הם אישורי מסירה (receipts). בוחרים אותם כמו כל אירוע הודעה אחר, והם מגיעים כאירועים האלה:

אירועערוציםמאפיינים בולטים
message.deliveredדוא"ל, SMS, Viber, פוש, WhatsAppmessageId, campaignId, canvasId
message.bouncedדוא"לbounceType (hard או soft), bounceSubType, dsnStatus, reason
message.spamreportדוא"לmessageId, campaignId
message.failedכל הערוציםerrorCode, errorReason
message.skippedכל הערוציםreason - למה Joryio לא שלחה (חסימה, מגבלת תדירות, הסכמה, שעות שקטות)
message.deferredדוא"להספק מנסה שוב אחרי כשל זמני
message.auto_repliedדוא"למענה "מחוץ למשרד" - הדוא"ל נמסר
message.unsubscribedכל הערוציםראו שינוי מצב הרשמה
message.opened (ערוץ whatsapp)WhatsAppאישור הקריאה
sms.message.received, whatsapp.message.received, viber.message.receivedSMS, WhatsApp, Viberתשובה נכנסת; ב-SMS וב-Viber, keyword הוא stop, start או help כשהתשובה הייתה מילת מפתח

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

זרמים שנוצרו לפני שאישורי המסירה היו זמינים

זרם שנשמר לפני שהיו אישורי מסירה עשוי כבר לבחור חלק מהם (למשל message.bounced). הם מעולם לא הגיעו, והם לא מתחילים להגיע מעצמם: הזרם מציג אישורי מסירה זמינים עכשיו, והם מתחילים לזרום ברגע ששומרים את הזרם שוב. זרמים חדשים מקבלים אישורי מסירה מההתחלה.

מה מכיל אירוע הודעה מוזרם​

  • כל אירוע נושא את מזהה איש הקשר ב-Joryio (userId), ואירועי הודעות נושאים גם את ה-externalId של איש הקשר כשיש לו.
  • כתובות דוא"ל ומספרי טלפון נכללים רק כשמי ששמר את הזרם לאחרונה מחזיק בהרשאה pii:view (למנהלים ולבעלים היא תמיד קיימת). אחרת הם מוסרים. שמירה חוזרת של הזרם מחילה את הכלל לפי מי ששומר.
  • תוכן ההודעה (גוף, כותרת, HTML) אף פעם לא נכלל באישור מסירה.
  • פתיחות והקלקות שנראות אוטומטיות (סורקי אבטחה, שרתי פרטיות של דוא"ל) לא מושמטות; הן נושאות $is_bot: true, כך שאתם מחליטים מה לעשות בהן.

קבוצות אירועים אחרות​

קבוצהאירועים
In-Appin_app.displayed, in_app.clicked, in_app.dismissed, in_app.converted
מסעותcanvas.experiment.entered, canvas.ai_decision.entered, canvas.step.entered, canvas.step.left
קמפייניםcampaign.sent, campaign.abtest.winner_declared, campaign.ai_decision.entered
כרטיסי Walletpass.issued, pass.installed, pass.updated, pass.update_pushed, pass.removed, pass.voided, pass.expired, pass.scanned
מסחר אלקטרוניOrder Completed, Order Refunded, Order Cancelled
זהות$identify, $alias

אפשר גם להזרים כל אירוע מותאם אישית שאתם שולחים עם track().

שליחה באצוות​

האירועים נצברים ונמסרים באצוות. אתם מגדירים:

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

אצווה נמסרת כשהיא מגיעה לגודל שהוגדר או כשחולף מרווח הריקון - המוקדם מביניהם.

כיצד זה עובד​

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

כאשר אירוע תואם לבחירת האירועים של זרם, הוא נכנס לתור ונמסר ליעד באצווה הבאה. כל מסירה כוללת את שם האירוע, המאפיינים, חותמת הזמן ומזהה המשתמש - ובאירועי הודעות גם את ה־channel שממנו נשלחה ההודעה. מחסני נתונים ויעדי אחסון טוענים את האצווה כשורות או כקבצים; יעדי אנליטיקת מוצר מעבירים כל אירוע דרך API הקליטה שלהם; Webhooks מקבלים גוף JSON או NDJSON.

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

הבטחות מסירה וכפילויות​

המסירה היא לפחות פעם אחת (at-least-once). במקרים נדירים - ניסיון חוזר אחרי כשל רשת, או הפעלה מחדש של תהליך באמצע אצווה - אותו אירוע עשוי להימסר ליעד שלכם יותר מפעם אחת.

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

כל אירוע נושא eventId יציב. זהו אותו ערך בכל מסירה של אותו אירוע, כך שתוכלו להשתמש בו לביטול כפילויות:

יעדמה אנחנו עושים
Amplitudeנשלח כ-insert_id - Amplitude מבטל כפילויות אוטומטית
Mixpanelנשלח כ-$insert_id - Mixpanel מבטל כפילויות אוטומטית
S3אצווה שנמסרת שוב נכתבת לאותו מפתח אובייקט, ודורסת במקום להוסיף קובץ נוסף
BigQuery, Snowflake, Redshiftבטלו כפילויות לפי eventId בעת הטעינה, למשל ROW_NUMBER() OVER (PARTITION BY eventId)
Webhookהתעלמו מ-eventId שכבר עיבדתם

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

ניטור​

רשימת הזרמים מציגה מדדים וסטטוס לכל זרם:

  • Active - מסירת האירועים פועלת כרגיל
  • Paused - הזרם נעצר זמנית (אפשר לחדש אותו בכל עת)
  • Error - המסירות האחרונות נכשלו (בדקו את החיבור)

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