مرجع Liquid
تُخصّص Joryio الرسائل باستخدام Liquid: اكتب عناصر نائبة مثل {{ user.firstName }} وفلاتر مثل {{ price | currency }}، ثم تُحلّ لكل مستلم وقت الإرسال. هذه الصفحة هي المرجع الكامل لكل نطاق متغير وكل فلتر مخصص في Joryio، مع أمثلة.
هل هذه أول تجربة لك مع Liquid في Joryio؟ ابدأ بـ قوالب Liquid للتعرّف إلى الأساسيات، ثم عد إلى هنا عندما تحتاج إلى التفاصيل.
تُسجّل جميع الفلاتر أدناه في محرك Liquid مشترك واحد تستخدمه جميع مسارات العرض؛ لذلك يظهر القالب نفسه بالطريقة نفسها في قوالب Email وSMS وWhatsApp وPush وIn-app وWebhook، سواء في الحملات أو الرحلات أو المعاينة. ما تراه في المعاينة هو ما يُرسل عبر كل قناة.
إعدادان افتراضيان متسامحان ينبغي معرفتهما:
- المتغير الذي لا يملك قيمة يظهر كنص فارغ، وليس كخطأ.
- الفلتر غير المعروف يمرر القيمة دون تغيير بدلًا من فشل العرض.
المتغيرات
هذه هي النطاقات المتاحة باختصار. اتبع الروابط للاطلاع على التفاصيل الكاملة لكل نطاق.
| النطاق | ما يحتويه | التفاصيل |
|---|---|---|
user.firstName, user.lastName, user.email, user.phone, user.id, user.externalId, user.whatsappName | السمات الافتراضية لجهة الاتصال | متغيرات الرسائل |
user.custom.<attribute> | أي سمة مخصصة لجهة الاتصال، مثل user.custom.plan | متغيرات الرسائل |
trigger.properties.<field> | كيفية دخولهم إلى الرحلة: حدث الدخول، ويظل ثابتًا طوال التشغيل | متغيرات الرسائل |
event.properties.<field>, event.name | آخر إجراء قاموا به: أحدث حدث دفع الرحلة إلى الأمام | متغيرات الرسائل |
reply.text, reply.type, reply.profile.name | أسماء بديلة سهلة لآخر رد وارد من جهة الاتصال عبر WhatsApp أو SMS | متغيرات الرسائل |
blocks.<slug> | Content Block قابل لإعادة الاستخدام، يُعرض ضمن النص | Content Blocks |
unsubscribe_url, preferences_url, resubscribe_url | روابط اشتراك خاصة بكل مستلم (Email أو SMS أو جلسة WhatsApp) | قوالب Liquid |
cart.items, cart.value, cart.subtotal, cart.currency, cart.checkoutUrl | سلة المتجر المتزامنة لجهة الاتصال - عناصر مع name وquantity وprice وtotal وimageUrl وurl وsku value هو الإجمالي الذي أرسله المتجر (قد يشمل الشحن)؛ وsubtotal هو المجموع الفرعي للعناصر، قبل الشحن والضريبة. | المنتجات |
last_order.items, last_order.total, last_order.currency, last_order.placedAt, last_order.orderUrl | أحدث طلب لهم لم يُلغَ ولم يُسترد - نفس حقول العناصر كما في السلة | المنتجات |
top_products | المنتجات التي يطلبونها أكثر - حتى 5 مع name وsku وimageUrl وurl وtimesOrdered وlastOrderedAt، الأكثر تكرارًا أولًا | المنتجات |
فلاتر products وentity | سجلات كتالوج المنتجات أو الكيانات المخصصة من اختيار محفوظ | خلاصات الكتالوج أدناه |
لا تُحلّ trigger.* وevent.* وreply.* إلا داخل رحلة؛ أما البقية فتعمل في كل مكان.
تكون cart وlast_order وtop_products فارغة لجهة اتصال ليس لديها طلبات في المتجر - غلّفها بـ {% if %}.
الفلاتر
اربط الفلاتر باستخدام |، ومرّر الوسائط بعد :. مثال:
{{ user.firstName | capitalize | default: "there" }}
{{ order.total | currency: "EUR" }}
النص
| الفلتر | وظيفته | مثال ← الناتج |
|---|---|---|
capitalize | يجعل الحرف الأول كبيرًا ويحوّل الباقي إلى أحرف صغيرة | {{ "mAYA" | capitalize }} → Maya |
uppercase | يحوّل السلسلة كاملة إلى أحرف كبيرة | {{ "sale" | uppercase }} → SALE |
lowercase | يحوّل السلسلة كاملة إلى أحرف صغيرة | {{ "SALE" | lowercase }} → sale |
truncate | يقتطع السلسلة عند طول محدد (الافتراضي 50) ويضيف لاحقة (الافتراضي ...). تُضاف اللاحقة بعد موضع الاقتطاع، فوق الطول المحدد | {{ "The quick brown fox jumps" | truncate: 9 }} → The quick... |
strip_html | يزيل وسوم HTML | {{ "<b>Sale</b> today" | strip_html }} → Sale today |
url_encode | يرمّز السلسلة بصيغة URL لبناء الروابط | {{ "red shoes" | url_encode }} → red%20shoes |
pluralize | يتلقى رقمًا ويعيد الكلمة بالمفرد أو الجمع. يكون الجمع افتراضيًا المفرد مع s؛ مرّر وسيطًا ثالثًا لصيغ الجمع غير المنتظمة | 3 {{ 3 | pluralize: "item" }} → 3 items |
default | قيمة بديلة عندما تكون القيمة null أو غير معرّفة أو سلسلة فارغة | {{ user.firstName | default: "there" }} → there (عند الفراغ) |
landing_page_url | رابط إلى صفحة هبوط منشورة بحسب الـ slug. يحمل رمز المستلم فتعرف الصفحة من وصل؛ ووسيط اختياري يضيف سلسلة استعلام. يُبنى الرابط دائمًا؛ والـ slug غير المنشور (أو غير الموجود) يجيب بـ 404 عند إعادة التوجيه. يكون فارغًا فقط عندما يكون الـ slug غير صالح أو عندما لا تكون للعرض مساحة عمل | {{ "spring-sale" | landing_page_url: "utm_campaign=spring" }} → https://api-eu1.joryio.com/api/p/go/<workspace>/spring-sale?jp=…&utm_campaign=spring |
الأرقام والمال
| الفلتر | وظيفته | مثال ← الناتج |
|---|---|---|
currency | ينسّق رقمًا كقيمة مالية. رمز العملة الافتراضي هو USD ويمكن تمرير أي رمز ISO. يستخدم تنسيق en-US (الرمز أولًا وفواصل الآلاف) | {{ 1249.5 | currency }} → $1,249.50 · {{ order.total | currency: "EUR" }} → €49.90 |
التواريخ
| الفلتر | وظيفته | مثال ← الناتج |
|---|---|---|
date_format | ينسّق التاريخ. الأنماط: short (الافتراضي)، long، full. يعود النمط غير المعروف إلى short. أسماء الأشهر والأيام بالإنجليزية (en-US). يُنسَّق في المنطقة الزمنية لمساحة العمل في المعاينة والإرسال على حد سواء؛ ولا تُزاح أبدًا قيمة التاريخ فقط مثل تاريخ الميلاد (1990-05-01). يقبل أيضًا نمط strftime ("%d %b %H:%M")، ويحدد وسيط ثانٍ اختياري منطقة IANA أخرى - وتعود المنطقة غير المعروفة إلى منطقة مساحة العمل | {{ order.createdAt | date_format }} → Jul 12, 2026 · {{ order.createdAt | date_format: "long" }} → July 12, 2026 · "full" → Sunday, July 12, 2026 · {{ order.createdAt | date_format: "%d %b %H:%M", "America/New_York" }} → 12 Jul 05:30 |
add_days | يضيف N أيام إلى تاريخ (رقم سالب للطرح). يعيد طابعًا زمنيًا ISO؛ اربطه بـ date_format لقراءته بسهولة | {{ order.createdAt | add_days: 7 | date_format }} → Jul 19, 2026 |
time_ago | وقت نسبي سهل القراءة (سنة/شهر/أسبوع/يوم/ساعة/دقيقة/ثانية) | {{ user.custom.lastOrderAt | time_ago }} → 3 days ago |
تُعرض التواريخ والأوقات في محتوى الرسائل في المنطقة الزمنية لمساحة العمل، وهي المنطقة نفسها التي يستخدمها باقي التطبيق. ينطبق ذلك على date_format وعلى المرشح القياسي date ({{ order.createdAt | date: "%H:%M" }})؛ مرّر منطقة كآخر وسيط لاستخدام منطقة أخرى.
المصفوفات
| الفلتر | وظيفته | مثال ← الناتج |
|---|---|---|
join | يضم عناصر المصفوفة إلى سلسلة. الفاصل الافتراضي هو , | {{ names | join }} → Ana, Ben, Gal · {{ names | join: " / " }} → Ana / Ben / Gal |
map | يستخرج خاصية واحدة من كل عنصر ويعيد مصفوفة جديدة | {{ items | map: "name" | join }} → Mug, Tee |
first | العنصر الأول | {{ items | first }} |
last | العنصر الأخير | {{ items | last }} |
size | طول مصفوفة أو سلسلة (0 لأي شيء آخر) | {{ cart.items | size }} → 3 |
count | عدد العناصر في مصفوفة (0 إن لم تكن القيمة مصفوفة) | {{ cart.items | count }} → 3 |
التجميع والفلترة
تعمل هذه الفلاتر على مصفوفات السجلات، مثل عناصر السلة أو الطلبات أو اختيارات الكتالوج. يدعم كل وسيط field مسارات نقطية إلى كائنات متداخلة، مثل "price.amount".
| الفلتر | وظيفته | مثال ← الناتج |
|---|---|---|
sum | يجمع حقلاً رقميًا عبر المصفوفة (القيم الناقصة تُحسب 0) | {{ orders | sum: "totalAmount" }} → 540 |
avg | يحسب متوسط حقل رقمي (0 للمصفوفة الفارغة) | {{ orders | avg: "totalAmount" }} → 180 |
max | أكبر قيمة رقمية لحقل (تُتجاهل القيم غير الرقمية؛ و0 إن لم توجد) | {{ products | max: "price" }} → 129.9 |
min | أصغر قيمة رقمية لحقل | {{ products | min: "price" }} → 19.9 |
where | يفلتر المصفوفة. ثلاث صيغ: where: "featured" يحتفظ بالعناصر الصادقة؛ وwhere: "category", "shoes" يحتفظ بالمتساوية؛ وwhere: "price", "gt", 100 يقارن باستخدام eq أو neq أو gt أو gte أو lt أو lte أو contains أو in (وتعمل أيضًا صيغ الرموز == و!= و> و>= و< و<=) | {{ items | where: "category", "shoes" | count }} → 2 |
sort | يرتب وفق حقل باتجاه asc (الافتراضي) أو desc. من دون حقل يرتب القيم نفسها | {{ products | sort: "price", "desc" | first }} → المنتج الأغلى |
مثال عملي: أحدث ثلاثة طلبات للمستلم:
{% assign recent = orders | sort: 'createdAt', 'desc' %}
{% for order in recent limit: 3 %}
- {{ order.createdAt | date_format }}: {{ order.totalAmount | currency }}
{% endfor %}
Total spent: {{ orders | sum: 'totalAmount' | currency }}
خلاصات الكتالوج
يستخرج فلتران مجموعات من السجلات إلى رسالة، وكل منهما يعتمد على اختيار محفوظ ضمن مساحة عملك. يعيد كلاهما مصفوفة؛ استخدمهما في وسم assign ثم نفّذ حلقة عليها.
products - كتالوج منتجات المتجر
يستخرج من كتالوج المنتجات المتزامن (Shopify / WooCommerce / Magento) بواسطة اختيار للمنتجات. يوجد كتالوج منتجات واحد، ولذلك يكون الوسيط هو اسم الاختيار:
{% assign products = 'featured' | products %}
{% for item in products %}
- {{ item.name }}: {{ item.price | currency }}
{% endfor %}
entity - خلاصة كيان مخصص
يستخرج السجلات من كيان مخصص. الوسيط الأول هو اسم الكيان والثاني، وهو اختياري، اسم الاختيار:
{% assign episodes = 'tv_series' | entity: 'latest' %}
{% for item in episodes %}
- {{ item.name }}
{% endfor %}
يمكن تمرير متغيرات إلى اختيار كيان مخصص ذي معاملات؛ مثلًا، لتغذيته بحدث دخول الرحلة:
{% assign items = 'products' | entity: 'product_by_id', trigger %}
ملاحظات حول السلوك:
- تُخزَّن الاختيارات المتماثلة لكل مستلم (التي لا تستخدم فلاتر لسمة مستخدم أو للسياق) مؤقتًا - نحو خمس دقائق في معاينة المحرر، ونحو دقيقة عند الإرسال - لذلك لا تعيد الإرسالات الجماعية الاستعلام لكل مستلم. أما اختيارات الكيانات المخصصة فتُقيَّم من جديد لكل مستلم.
- إن تعذر العثور على اختيار الكيان/المنتج أو فشل الاستعلام، يعيد الفلتر مصفوفة فارغة؛ فتظهر حلقة
forبلا محتوى، لا كخطأ. - تعمل الفلاتر الثلاثة (
productsوentityوالاسم البديلcatalog) في كل مسار عرض وبالأسماء نفسها: معاينة المحرر، وإرسال الحملات، وإرسال الرحلات، وكل عامل قناة. ما تعرضه المعاينة هو ما يصل إلى المستلم. - ينشئ خيارا كتالوج المنتجات والكيان المخصص في منتقي التخصيص مقتطف
assignلك. راجع متغيرات الرسائل.
catalogالفلتر القديم catalog هو اسم بديل متوقف تدريجيًا لـ entity وما زال يعمل كي لا تنكسر القوالب الحالية. استخدم entity للكيانات المخصصة وproducts لكتالوج المتجر مستقبلًا.
التوصيات
recommendations.<slot> مصفوفة من المنتجات الموصى بها للمستلم، من نموذج توصيات. الخانة هي اسم النموذج كمفتاح (For you يصبح for_you)؛ وrecommendations.default هو النموذج الافتراضي لمساحة العمل. لكل عنصر name وprice (منسق) وcompareAtPrice وdiscountPercent وurl وimage وdescription وid. يعمل في كل قناة - Email (الحملات والرحلات) وSMS وWhatsApp وViber والإشعارات الفورية وداخل التطبيق وصفحات الهبوط - وفي معاينات المحرر وإرسالات الاختبار أيضًا:
{% for item in recommendations.for_you limit: 3 %}
{{ item.name }} - {{ item.price }} {{ item.url }}
{% endfor %}
راجعوا خانات Liquid لتسمية الخانات وحقول العناصر، وقائمة الحظر للمنتجات التي لا يُوصى بها أبدًا.
أوجه اختلاف Joryio عن Liquid القياسي
تتعمّد بعض الفلاتر الاختلاف عن نظيراتها في Shopify/LiquidJS:
capitalizeيحوّل باقي السلسلة أيضًا إلى أحرف صغيرة ("mAYA"تصبحMayaلاMAYA).- يعتبر
defaultالسلسلة الفارغة مفقودة، لذا يعود{{ user.firstName | default: "there" }}إلى قيمة بديلة حتى عندما تكون السمة موجودة لكنها فارغة. - يضيف
truncateاللاحقة بعد طول الاقتطاع (بينما يحتسب Liquid القياسي علامة الحذف ضمن الطول). whereوsortامتدادان للفلاتر المضمنة: يقبلان الصيغ القياسية ويضيفان معاملات المقارنة/اتجاه الترتيب وحقول المسارات النقطية.
ما زال Liquid القياسي يعمل
كل ما سبق يضاف فوق LiquidJS القياسي: الوسوم المضمنة مثل {% if %} و{% elsif %} و{% else %} و{% for %} و{% assign %} و{% case %} وغيرها، والفلاتر المضمنة مثل upcase وdowncase وdate وreplace وsplit وplus وtimes وغيرها، كلها تعمل في أي قالب من Joryio. عندما يشترك فلتر Joryio مع فلتر مضمّن بالاسم (capitalize أو default أو where أو sort أو join أو map أو first أو last أو size)، تكون نسخة Joryio المشروحة هنا هي التي تعمل. راجع القائمة الكاملة للفلاتر المضمنة في liquidjs.com/filters/overview.html.
ذو صلة
- قوالب Liquid - مقدمة ومنتقي التخصيص
- متغيرات الرسائل -
trigger.*وevent.*وreply.*في الرحلات - Content Blocks - مقتطفات قابلة لإعادة الاستخدام عبر
blocks.slug - توصيات المنتجات - النماذج والأنواع وخانات
recommendations.*