تنبيهات علاقات الكيانات
تنبيهات العلاقات هي النسخة العامة من مشغّل عودة المنتج للمخزون، ولكن لأي كيان مخصص، مثل المقاعد والرحلات الجوية والدروس والعروض والمواعيد ومخزون B2B. الفكرة بسيطة:
عندما يتغير سجل في كتالوج، أبلغ كل جهة اتصال مرتبطة بهذا السجل عبر كيان ثانٍ ذي صلة.
تعرّف كيانًا أبًا: الكتالوج الذي تتغير سجلاته، مثل concert_tickets أو series، ثم تختار كيفية العثور على الجمهور: قائمة قبول ذات صلة، كيان قائمة انتظار أو متابعة، أو الأشخاص الذين أطلقوا حدثًا ذا صلة، مثل المشاهدة أو العرض. راجع طريقتان لتعريف الجمهور أدناه.
عند انتقال حقل مراقب في سجل الأب، يحل Joryio ذلك الجمهور ويصدر حدثًا لكل مستخدم يمكنك استخدامه كمشغّل دخول لرحلة أو حملة. ويُزال التكرار لكل شخص كي لا ترسل القيم المتذبذبة رسائل مزعجة.
لماذا كيانان؟
ميزة عودة المنتج للمخزون المدمجة تتم بنقرة واحدة لأن كتالوج المنتجات ذو شكل معروف: حقل مخزون وقائمة مشتركين. أما الكيانات المخصصة فمرنة؛ لا يستطيع Joryio تخمين الحقل الذي يعني "متاح" أو الكيان الذي يحتفظ بقائمة الانتظار، لذلك تعلن ذلك مرة واحدة في إعدادات الكيان الأب.
بالنسبة لمعظم متاجر التجارة الإلكترونية، يبقى كتالوج المنتجات هو الطريق الأسهل. استخدم تنبيهات العلاقات عندما لا يكون كتالوجك منتجات، أو عندما يكون الجمهور قائمة صريحة بدل نية تصفح مستنتجة.
طريقتان لتعريف الجمهور
قبل الإعداد، هذا هو الاختيار الأساسي: من سيتلقى الإشعار؟
- سلوكي،
audienceSource: "event": الأشخاص الذين أطلقوا حدث نية، مثلWatched EpisodeأوViewed Flight، يشير إلى السجل خلال نافذة بحث سابقة. لا سجلات متابعة أو انتظار تحتاج إلى صيانتها؛ فالجمهور هو السلوك نفسه. يشبه ذلك بناء جمهور عودة المنتج للمخزون من أحداث التصفح، وهو الأفضل لـ "أبلغ كل من شاهد أو عرض". - صريح،
audienceSource: "child_entity"وهو الافتراضي: صفوف كيان قبول ذي صلة، مثل قائمة "أبلغني" أو "تابع هذا العرض". وهو الأفضل عندما يشترك الناس عمدًا بغض النظر عن السلوك.
لا تحتاج كيان متابعة لحالة VOD؛ راجع المثال 2.
"أبلغني" كحدث مقابل كيان قائمة انتظار
سؤال شائع: إذا كانت نقرة "أبلغني" تصدر حدثًا، Notify Me مع product_id، فهل ما زلت تحتاج كيان قائمة انتظار؟ غالبًا لا: وجّه وضع الحدث إليه عبر intentEvent: "Notify Me" وintentRefProperty: "product_id" وينتهي الأمر.
السبب الوحيد للعودة إلى كيان فرعي هو الاستمرارية. جمهور الحدث محدود بأمرين:
- نافذة البحث السابق،
intentLookbackDays. - الاحتفاظ بالأحداث: تحذف TTL الاحتفاظ بالبيانات في مساحة عملك الحدث في النهاية، وبعدها لا يراه وضع الحدث.
توقيت عودة المخزون مفتوح؛ قد يعود العنصر الأسبوع القادم أو بعد ثمانية أشهر. إن تقادم حدث "أبلغني" قبل عودته، يفوت وضع الحدث هذا الشخص، أما صف قائمة الانتظار فيبقى حتى تمسحه. لذلك:
- أفق قصير ومتوقع، مثل حلقات جديدة أو إعادة مخزون سريعة: استخدم وضع الحدث بلا كيان.
- أفق مفتوح، أو قائمة "أبلغ مرة ثم أزل" تريد إدارتها: استخدم كيان قائمة انتظار فرعيًا.
الإعداد
يُضبط على الكيان الأب. في التطبيق: الكيانات -> تعديل الكيان -> الإعدادات -> تنبيه الأشخاص المرتبطين بسجل - فعّل المفتاح فيعرض القسم الحقل المراقب، وما يُعد تغييرًا، والحدث المُصدر، وفترة الانتظار، ومن يستلم التنبيه، وقاعدة "تخطي الأشخاص الذين تصرفوا بالفعل". كل عنصر تحكم يقابل مفتاحًا واحدًا في settings.relationshipAlert، وهو ما يضبطه الـ API والمساعد:
| الحقل | المعنى | المثال |
|---|---|---|
enabled | تفعيل التنبيه | true |
triggerMode | ما يعتبر تشغيلًا على field، راجع أدناه | "restock" |
field | حقل الأب الذي يشغّل انتقاله التنبيه | "available" |
eventName | الحدث الصادر لكل مستخدم | "back_in_stock" |
cooldownDays | نافذة منع لكل شخص/سجل، الافتراضي 7 | 7 |
audienceSource | "child_entity"، الافتراضي، أو "event" | "event" |
childEntity | في وضع الطفل: الاسم الداخلي لكيان الانتظار/المتابعة | "ticket_waitlist" |
childRefField | في وضع الطفل: الحقل في صف الطفل الذي يحمل معرّف سجل الأب | "ticketId" |
intentEvent | في وضع الحدث: حدث النية الذي يحدد الجمهور | "Watched Episode" |
intentRefProperty | في وضع الحدث: خاصية الحدث التي تحمل معرّف سجل الأب | "series_id" |
intentLookbackDays | في وضع الحدث: مقدار الرجوع، الافتراضي 90 | 90 |
minDropPct | في وضع decrease: أقل انخفاض، كنسبة مئوية من القيمة السابقة، لكي يعمل التنبيه، الافتراضي 5 | 5 |
أوضاع المشغّل
restock: ينتقل رقم من ≤ 0 إلى > 0، أي عودة للمخزون. وهو الافتراضي.increase: يزداد الرقم، مثل عدد الحلقات 8 ← 9.changed: تتغير قيمة إلى قيمة جديدة غير فارغة، مثل "معرّف أحدث حلقة".decrease: ينخفض رقم موجب بما لا يقل عنminDropPctبالمئة إلى رقم موجب آخر، مثل سعر غرفة فندق 200 ← 180. وهو نظير انخفاض السعر المدمج للكتالوجات المخصصة؛ راجع المثال 3.
في وضع الكيان الفرعي، يجب أن يعلن الكيان الفرعي User Link، أي الحقل الذي يربط بجهة اتصال عبر user id أو external id أو email أو الهاتف أو سمة؛ بهذه الطريقة يُحل كل صف إلى شخص. وفي وضع الحدث يكون user_id الخاص بحدث النية هو جهة الاتصال. لا تشغّل قيمة سابقة غير معروفة تنبيهًا، في الأوضاع الرقمية، فلا تنتج التعبئات الأولى تنبيهات خاطئة.
المثال 1: تذاكر حفلة تعود للمخزون
الهدف: نفدت تذاكر عرض؛ وعندما تتاح مجددًا، أبلغ كل من طلب الإشعار.
- كيان أب
concert_ticketsيحوي الحقل الرقميavailable. - كيان فرعي
ticket_waitlistيحويticketId، أي العرض/السجل المرجعي، وemail. اضبط User Link علىemail. - في
concert_ticketsاضبط:
{
"relationshipAlert": {
"enabled": true,
"triggerMode": "restock",
"field": "available",
"childEntity": "ticket_waitlist",
"childRefField": "ticketId",
"eventName": "back_in_stock",
"cooldownDays": 30
}
}
- عندما ينقر شخص "Notify me"، يضيف تطبيقك/موقعك صفًا إلى
ticket_waitlist:{ ticketId: "SHOW-A", email: "[email protected]" }. - عندما تنتقل
availableفيconcert_tickets/SHOW-Aمن0إلى50، يصدر Joryio حدثback_in_stockلكل جهة اتصال في قائمة الانتظار.
أنشئ رحلة من خطوة واحدة، أو حملة مشغلة، تدخل بحدث back_in_stock. خصصها بحقول السجل التي تسافر مع الحدث:
{{ event.name }} tickets are back! Grab yours before they sell out again.
يحمل الحدث أيضًا event.record_id وevent.new_value، أي المخزون الجديد، وأي حقل قياسي في السجل.
المثال 2: حلقة جديدة من مسلسل يشاهده شخص، VOD أو بأسلوب Netflix
الهدف: عندما تصدر حلقة جديدة من مسلسل، أبلغ كل من كان يشاهد ذلك المسلسل.
هل أحتاج كيان "متابعات" أم يكفي حدث مشاهدة؟ يمكنك استخدام حدث المشاهدة، وهو الخيار الطبيعي لـ VOD. أنت تصدر مسبقًا حدث Watched Episode، أو watch_series، عند تشغيل حلقة؛ وجّه التنبيه إلى هذا الحدث فيبلغ Joryio كل من شاهد المسلسل مؤخرًا. لا توجد سجلات متابعة لإنشائها أو صيانتها. استخدم كيان المتابعات فقط إذا أردت قائمة قبول صريحة لـ "تابع هذا العرض" منفصلة عن المشاهدة.
هل هذا هو عودة المخزون أم مختلف؟ يستخدم جانب الجمهور هنا السلوك بدل قائمة انتظار، أي audienceSource: "event"، ويختلف المشغّل أيضًا: فالحلقة الجديدة ليست تغير مخزون 0 → >0، بل زيادة في عدد الحلقات أو تغير معرّف أحدث حلقة. المحرك نفسه لكن بإعدادين مختلفين.
ما تحتاجه: كيان واحد فقط
- كيان أب
seriesيتضمن حقل عرض مثلtitle، وحقلًا رقميًاepisodeCountأو سلسلةlatestEpisodeId. لا حاجة لكيان فرعي. - في
seriesاضبط:
{
"relationshipAlert": {
"enabled": true,
"triggerMode": "increase",
"field": "episodeCount",
"audienceSource": "event",
"intentEvent": "Watched Episode",
"intentRefProperty": "series_id",
"intentLookbackDays": 90,
"eventName": "new_episode",
"cooldownDays": 1
}
}
استخدم "triggerMode": "changed" مع "field": "latestEpisodeId" إذا كنت تتتبع الحلقة الأحدث بمعرّف بدل عداد.
- الاتصال هو خاصية الحدث. يرسل المشغل عند كل تشغيل شيئًا مثل:
{ "event": "Watched Episode", "series_id": "S-42", "episode": 12 }
يربط intentRefProperty: "series_id" المشاهدة بسجل series، ويجب أن يطابق معرّف السجل أو قيمة مفتاحه الأساسي، S-42.
4. طريقة التشغيل: عندما ترفع تغذية كتالوجك episodeCount في series/S-42 من 8 إلى 9، يستعلم Joryio عن من أطلق Watched Episode مع series_id = S-42 خلال آخر 90 يومًا ويصدر حدث new_episode لكل منهم.
5. أنشئ رحلة/حملة تدخل بحدث new_episode:
New episode of {{ event.name }} is out now. Pick up where you left off →
إذا فضلت قائمة متابعة صريحة بدل سلوك المشاهدة، أبقِ triggerMode: "increase" واستخدم جمهور الكيان الفرعي: أضف كيان series_follows، يحمل seriesId وuserId وUser Link إلى userId، واضبط audienceSource: "child_entity" وchildEntity: "series_follows" وchildRefField: "seriesId"، ثم أضف صف متابعة عند نقر الشخص Follow.
مقارنة عودة المخزون والحلقة الجديدة
| عودة تذاكر الحفلة | حلقة جديدة، VOD | |
|---|---|---|
| الكيانات المطلوبة | أب + قائمة انتظار فرعية | الأب فقط |
| الجمهور | صفوف ticket_waitlist، قبول | حدث Watched Episode، سلوك |
audienceSource | child_entity | event |
| الحقل المراقب | available، مخزون | episodeCount / latestEpisodeId |
triggerMode | restock، 0 → >0 | increase / changed |
| الحدث الصادر | back_in_stock | new_episode |
المثال 3: "انخفض سعر تواريخك للتو"، أسعار الفنادق
الهدف: بحث نزيل عن إقامة وحفظ التواريخ؛ وعندما ينخفض سعر تلك الغرفة لتلك التواريخ، أبلغه، كما يفعل انخفاض السعر المدمج لمنتجات Shopify وWooCommerce، لكن لكتالوج لا يزامنه Joryio.
-
الكيان الأب
hotel_ratesبمفتاح أساسي تجاريrateId، أي صف لكل نوع غرفة ونطاق تواريخ، وحقل عرضhotel، وحقل رقميrate. -
الجمهور: إما كيان فرعي
saved_searchesبالحقلينrateIdوemailوربط مستخدم علىemail، يُملأ عندما يحفظ النزيل التواريخ؛ أو وضع الحدث على حدثRate Viewedالذي يرسله موقع الحجز لديك أصلًا معrate_id. -
على
hotel_ratesاضبط:{"relationshipAlert": {"enabled": true,"triggerMode": "decrease","minDropPct": 5,"field": "rate","childEntity": "saved_searches","childRefField": "rateId","eventName": "rate_drop","cooldownDays": 3,"excludeEvent": "Booking Completed","excludeRefProperty": "rate_id"}} -
عندما تحدّث تغذية الأسعار
hotel_rates/R-1بحيث ينتقلrateمن200 ← 180، أي انخفاض 10% يتجاوز حد 5%، يصدر Joryio حدثrate_dropلكل نزيل مرتبط بهذا السعر، باستثناء من حجزه بالفعل عبرexcludeEvent. أما التحديث200 ← 195، أي 2.5%، فلا يعمل؛ وكذلك أول سعر على الإطلاق، أو سعر يرتفع، أو سعر يصل إلى0، فهذا نفاد لا عرض. -
ابنِ رحلة يدخلها
rate_drop. إلى جانب حقول السجل، يحمل الحدث زوج القيم الذي قيس منه الانخفاض:{{ event.hotel }} لتواريخك الآن بسعر {{ event.new_value }}، أي أقل بنسبة {{ event.drop_pct }}% من {{ event.old_value }}.
خصائص تشغيل decrease
| الخاصية | المعنى |
|---|---|
old_value | قيمة الحقل قبل التحديث |
new_value | قيمة الحقل بعد التحديث |
drop_pct | الانخفاض كنسبة مئوية من old_value، مقرّبًا إلى منزلة عشرية واحدة، 10 للانتقال 200 ← 180 |
يحمل drop_pct الاسم والمعنى نفسيهما كما في حدث price_drop المدمج، فشرط الرحلة المكتوب لأحدهما يصلح للآخر. أما زوج القيم فهو old_value / new_value لا old_price / new_price، لأن الحقل المراقب هنا قد يكون أي رقم: سعرًا أو رسمًا أو تذكرة أو زمن انتظار.
انخفاض إضافي إلى قيمة جديدة، 180 ← 160، يعد انتقالًا مستقلًا وينبه مجددًا بعد فترة التهدئة؛ أما وصول القيمة نفسها مرة أخرى فلا.
استبعاد من اتخذوا الإجراء بالفعل
إذا أرسلت بعد وقت من الإصدار، فلا تريد غالبًا تذكير من شاهدوا الحلقة الجديدة بالفعل أو اشتروا العنصر المعاد للمخزون. توجد طبقتان، وغالبًا ستستخدم كلتيهما.
1. تخطَّهم وقت التشغيل: excludeEvent
يمكن للتنبيه إزالة كل من أطلق بالفعل حدثًا للقيمة الجديدة لهذا الانتقال من الجمهور. لمثال VOD، أضف إلى الإعداد:
{
"excludeEvent": "Watched Episode",
"excludeRefProperty": "series_id",
"excludeValueProperty": "episode",
"excludeLookbackDays": 30
}
عند إصدار الحلقة 9، يبلغ Joryio من شاهدوا المسلسل لكنه يستبعد من شاهد الحلقة 9 بالفعل، أي series_id للمسلسل وepisode للقيمة الجديدة. يربط excludeValueProperty الاستبعاد بالحلقة الجديدة المحددة. كي يتطابق ذلك، يجب أن تطابق قيمة الحقل الجديدة المعرّف الذي يحمله حدث المشاهدة؛ ويكون ذلك أوضح مع triggerMode: "changed" وlatestEpisodeId أو عندما يساوي رقم الحلقة العداد. يعمل ذلك أيضًا لعودة المخزون: اضبط excludeEvent على حدث الشراء لتخطي المشترين مؤخرًا.
2. أعد الفحص وقت الإرسال: الإجابة الدقيقة للإرسال المؤخر
لا يعرف استبعاد وقت التشغيل إلا من شاهد حتى لحظة إطلاق التنبيه. إن انتظرت يومين عمدًا قبل الإرسال، فقد يشاهد الأشخاص خلال هذين اليومين، ولا يلتقطهم إلا فحص وقت الإرسال. نفذ ذلك في الرحلة:
- مشغّل الدخول:
new_episode. - Wait لمدة يومين.
- Condition / behavior split: لم ينفذ
Watched Episodeحيثepisode={{ trigger.new_value }}في آخر يومين؛ هذا الفرع فقط يتابع إلى الإرسال.
يعاد تقييم كل شخص فورًا قبل الإرسال، فيُستبعد من لحق بالحلقة أثناء الانتظار. استخدم excludeEvent في الطبقة الأولى لإبقاء الجمهور الأولي مركزًا، وشرط الرحلة في الطبقة الثانية لدقة الإرسال المؤخر.
استخدام حدث التنبيه
مهما كان اسمه، يتصرف eventName كأي حدث آخر في Joryio:
- يظهر في منتقي الأحداث كمشغّل دخول للحملة أو الرحلة.
- تتاح خصائصه،
record_idوnew_valueوfieldوحقول السجل القياسية وتسميةname، وفي تنبيهdecreaseأيضًاold_valueوdrop_pct، عبرevent.*في Liquid. - ما زال الإرسال يلتزم بالموافقة والحظر والوقت الهادئ كأي إرسال قناة آخر.
كيف يعمل في الخلفية
يُكتشف الانتقال في مسار تحديث الكيان ويُوزع بعيدًا عن المسار الساخن، فلا يحجب جمهور بطيء كتابة السجل. تُزال تكرارات الإشعارات لكل زوج جهة اتصال/سجل لمدة cooldownDays، ولا يُحسب صف طفل إلا مرة واحدة حتى إن حلت عدة صفوف إلى جهة الاتصال نفسها.
الاستيرادات بالجملة
لا تشغّل استيرادات السجلات بالجملة التنبيهات افتراضيًا، فلا ينبه التحميل الأول الجميع. فعّل ذلك لكل استيراد بإرسال triggerAlerts: true في نقطة النهاية المجمعة. عند التفعيل ووجود مفتاح أساسي تجاري للكيان، يعمل الاستيراد بتحديث وفرق: تُحدَّث السجلات الموجودة وتُشغّل انتقالاتها، مثل تغذية مخزون أو episodeCount ليلية، بينما لا تشغّل الصفوف الجديدة إلا تنبيهات وضع changed، إذ تتطلب الأوضاع الرقمية قيمة سابقة.
بدء الإعداد
ثلاث طرق، وكلها تكتب إعداد relationshipAlert نفسه:
- في منشئ الكيانات - افتح الكيان الأب (الكيانات -> تعديل)، انزل إلى الإعدادات -> تنبيه الأشخاص المرتبطين بسجل، فعّل المفتاح واملأ الحقل والوضع والحدث وفترة الانتظار والجمهور وقاعدة التخطي. لا يعرض المنشئ إلا الحقول الرقمية للأوضاع الرقمية، ويظهر حقل النسبة المئوية في
decreaseفقط، ويرفض حفظ نسبة خارج النطاق. ما زال كيان قائمة الانتظار الفرعي بحاجة إلى ربط جهة الاتصال في إعداداته الخاصة. - عبر الـ API - أرسل
settings.relationshipAlertعلى الكيان بالمفاتيح الواردة في الجدول أعلاه. تسري القواعد نفسها:triggerModeمعروف وminDropPctبين 0 و100. - مع مساعد AI - اطلب كل ذلك في طلب واحد: ينشئ كيان المتابعة/الانتظار الفرعي، ويضبط الإعداد، ويبني رحلة الإشعار.
إيقاف التنبيه في المنشئ يحتفظ بالإعداد مع enabled: false، فعند إعادة تفعيله لاحقًا يجد كل شيء كما كان.