تخطّ إلى المحتوى الرئيسي

تنبيهات علاقات الكيانات

تنبيهات العلاقات هي النسخة العامة من مشغّل عودة المنتج للمخزون، ولكن لأي كيان مخصص، مثل المقاعد والرحلات الجوية والدروس والعروض والمواعيد ومخزون 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نافذة منع لكل شخص/سجل، الافتراضي 77
audienceSource"child_entity"، الافتراضي، أو "event""event"
childEntityفي وضع الطفل: الاسم الداخلي لكيان الانتظار/المتابعة"ticket_waitlist"
childRefFieldفي وضع الطفل: الحقل في صف الطفل الذي يحمل معرّف سجل الأب"ticketId"
intentEventفي وضع الحدث: حدث النية الذي يحدد الجمهور"Watched Episode"
intentRefPropertyفي وضع الحدث: خاصية الحدث التي تحمل معرّف سجل الأب"series_id"
intentLookbackDaysفي وضع الحدث: مقدار الرجوع، الافتراضي 9090
minDropPctفي وضع decrease: أقل انخفاض، كنسبة مئوية من القيمة السابقة، لكي يعمل التنبيه، الافتراضي 55

أوضاع المشغّل

  • restock: ينتقل رقم من ≤ 0 إلى > 0، أي عودة للمخزون. وهو الافتراضي.
  • increase: يزداد الرقم، مثل عدد الحلقات 8 ← 9.
  • changed: تتغير قيمة إلى قيمة جديدة غير فارغة، مثل "معرّف أحدث حلقة".
  • decrease: ينخفض رقم موجب بما لا يقل عن minDropPct بالمئة إلى رقم موجب آخر، مثل سعر غرفة فندق 200 ← 180. وهو نظير انخفاض السعر المدمج للكتالوجات المخصصة؛ راجع المثال 3.

في وضع الكيان الفرعي، يجب أن يعلن الكيان الفرعي User Link، أي الحقل الذي يربط بجهة اتصال عبر user id أو external id أو email أو الهاتف أو سمة؛ بهذه الطريقة يُحل كل صف إلى شخص. وفي وضع الحدث يكون user_id الخاص بحدث النية هو جهة الاتصال. لا تشغّل قيمة سابقة غير معروفة تنبيهًا، في الأوضاع الرقمية، فلا تنتج التعبئات الأولى تنبيهات خاطئة.


المثال 1: تذاكر حفلة تعود للمخزون​

الهدف: نفدت تذاكر عرض؛ وعندما تتاح مجددًا، أبلغ كل من طلب الإشعار.

  1. كيان أب concert_tickets يحوي الحقل الرقمي available.
  2. كيان فرعي ticket_waitlist يحوي ticketId، أي العرض/السجل المرجعي، وemail. اضبط User Link على email.
  3. في concert_tickets اضبط:
{
"relationshipAlert": {
"enabled": true,
"triggerMode": "restock",
"field": "available",
"childEntity": "ticket_waitlist",
"childRefField": "ticketId",
"eventName": "back_in_stock",
"cooldownDays": 30
}
}
  1. عندما ينقر شخص "Notify me"، يضيف تطبيقك/موقعك صفًا إلى ticket_waitlist: { ticketId: "SHOW-A", email: "[email protected]" }.
  2. عندما تنتقل 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، بل زيادة في عدد الحلقات أو تغير معرّف أحدث حلقة. المحرك نفسه لكن بإعدادين مختلفين.

ما تحتاجه: كيان واحد فقط

  1. كيان أب series يتضمن حقل عرض مثل title، وحقلًا رقميًا episodeCount أو سلسلة latestEpisodeId. لا حاجة لكيان فرعي.
  2. في 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" إذا كنت تتتبع الحلقة الأحدث بمعرّف بدل عداد.

  1. الاتصال هو خاصية الحدث. يرسل المشغل عند كل تشغيل شيئًا مثل:
{ "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، سلوك
audienceSourcechild_entityevent
الحقل المراقبavailable، مخزونepisodeCount / latestEpisodeId
triggerModerestock، 0 → >0increase / changed
الحدث الصادرback_in_stocknew_episode

المثال 3: "انخفض سعر تواريخك للتو"، أسعار الفنادق​

الهدف: بحث نزيل عن إقامة وحفظ التواريخ؛ وعندما ينخفض سعر تلك الغرفة لتلك التواريخ، أبلغه، كما يفعل انخفاض السعر المدمج لمنتجات Shopify وWooCommerce، لكن لكتالوج لا يزامنه Joryio.

  1. الكيان الأب hotel_rates بمفتاح أساسي تجاري rateId، أي صف لكل نوع غرفة ونطاق تواريخ، وحقل عرض hotel، وحقل رقمي rate.

  2. الجمهور: إما كيان فرعي saved_searches بالحقلين rateId وemail وربط مستخدم على email، يُملأ عندما يحفظ النزيل التواريخ؛ أو وضع الحدث على حدث Rate Viewed الذي يرسله موقع الحجز لديك أصلًا مع rate_id.

  3. على 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"
    }
    }
  4. عندما تحدّث تغذية الأسعار hotel_rates/R-1 بحيث ينتقل rate من 200 ← 180، أي انخفاض 10% يتجاوز حد 5%، يصدر Joryio حدث rate_drop لكل نزيل مرتبط بهذا السعر، باستثناء من حجزه بالفعل عبر excludeEvent. أما التحديث 200 ← 195، أي 2.5%، فلا يعمل؛ وكذلك أول سعر على الإطلاق، أو سعر يرتفع، أو سعر يصل إلى 0، فهذا نفاد لا عرض.

  5. ابنِ رحلة يدخلها 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. أعد الفحص وقت الإرسال: الإجابة الدقيقة للإرسال المؤخر​

لا يعرف استبعاد وقت التشغيل إلا من شاهد حتى لحظة إطلاق التنبيه. إن انتظرت يومين عمدًا قبل الإرسال، فقد يشاهد الأشخاص خلال هذين اليومين، ولا يلتقطهم إلا فحص وقت الإرسال. نفذ ذلك في الرحلة:

  1. مشغّل الدخول: new_episode.
  2. Wait لمدة يومين.
  3. 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، فعند إعادة تفعيله لاحقًا يجد كل شيء كما كان.