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

Landing Pages API

صفحة الهبوط هي صفحة عامة يبنيها فريقك في محرر Joryio (السحب والإفلات أو HTML)، وينشرها على عنوان، ويمكن إضافة نموذج إليها. النموذج المُرسل يحدد الشخص، ويكتب السمات والاشتراكات في القوائم إلى ملفه الشخصي، ويسجل الحدثين Landing Page Viewed وLanding Page Form Submitted، اللذين يمكن للشرائح والقمع والرحلات والحملات المحفَّزة استخدامهما كأي حدث آخر.

كل نقاط النهاية في هذه الصفحة نسبية إلى العنوان الأساسي: https://api-eu1.joryio.com/api - انظر نظرة عامة على API.

الصلاحيات: landing_pages:read وlanding_pages:write وlanding_pages:publish (انظر مفاتيح API).

أين تعيش الصفحة​

تُخدم الصفحة المنشورة على <pages host>/<workspace handle>/<slug>. الـ handle لمساحة العمل هو معرّفها نفسه - مبهم ودائم ولا يُختار ولا يُغيَّر (https://<workspace id>.eu1.jrypages.com/<slug> على نطاق الصفحات)؛ والـ slug فريد داخل مساحة العمل ومشتق من اسم الصفحة ما لم تحدده. يمكن لمساحة العمل بدلًا من ذلك أن تخدم صفحاتها على نطاق فرعي خاص بها (https://pages.yourbrand.com/<slug>) - انظر استخدام نطاقك الخاص. لكل صفحة أيضًا رابط معاينة (?preview=<signature>، من previewUrl): المسودة الحالية، يراها من يملك الرابط دون تسجيل دخول إلى Joryio، لا تُخزَّن مؤقتًا ولا تُفهرس؛ يتوقف عن العمل عند سحب نشر الصفحة.

مخطط النموذج​

form هو ما يتحقق منه مسار الإرسال العام. لا تحمل ترميز الصفحة سوى أسماء الحقول.

{
"fields": [
{ "key": "email", "type": "email", "label": "Email", "required": true },
{ "key": "first_name", "type": "text", "label": "First name", "attribute": "firstName" },
{ "key": "size", "type": "radio", "options": [{ "label": "S", "value": "s" }, { "label": "M", "value": "m" }] },
{ "key": "marketing", "type": "checkbox", "label": "Email me offers", "lists": ["<listId>"] },
{ "key": "lists", "type": "subscriptions", "lists": ["<listId>", "<listId>"] },
{ "key": "src", "type": "hidden", "value": "utm_source" }
],
"submit": { "action": "message", "message": "Thanks - check your inbox." },
"identity": "email"
}
النوعيكتبملاحظات
email, phoneبريد جهة الاتصال / هاتفهاواحد على الأكثر من كل نوع؛ phone مع lists يشترك في تلك القوائم
text, number, date, dropdown, radioالسمة المسماة في attribute (افتراضيًا: المفتاح)dropdown وradio يحتاجان options؛ radio مطلوب دائمًا
checkboxسمة منطقية؛ مع lists يشترك عند التحديدمربعات الموافقة لا تكون محددة مسبقًا أبدًا
checkbox_groupسمة مصفوفةoptions مطلوب
subscriptionsيشترك في القوائم المحددةlists مطلوب
hiddenسمة من value ثابتة، أو utm_source أو utm_medium أو utm_campaign أو utm_content أو utm_term أو referrer أو page

submit.eventName (اختياري) يطلق هذا الحدث المخصص على الشخص إضافة إلى حدث المنصة، مع القيم المُرسلة كخصائص؛ وsubmit.setAttributes (اختياري، { "lead_source": "spring_sale" }) يكتب قيم سمات ثابتة في كل إرسال. يمكن ضبط كليهما أيضًا على زر الإرسال في المحرر. submit.action إما message (عرض message في مكانه) أو redirect (إلى url، https فقط). يحتاج النموذج إلى حقل بريد أو هاتف ليمكن تحديد الشخص؛ يمكن لرابط من رسالة Joryio أن يحمل رمز الشخص بدلًا من ذلك (مخطط له).

نقاط النهاية​

الطريقةالمسارالصلاحيةما تفعله
GET/landing-pageslanding_pages:readقائمة مقسّمة إلى صفحات ({ data, pagination }) مع الحالة والإحصاءات ومن أنشأ ومن عدّل آخر مرة والعنوان العام. ?templates=true يسرد القوالب (قوالبك ثم المدمجة)؛ مرشحات ?status= (مفصولة بفواصل)، ?q=، ?tags=، ?createdBy=، ?editedBy=؛ ترتيب على كامل القائمة عبر ?sortBy= (name, status, views, submissions, createdAt, editedAt, publishedAt) و?sortOrder=؛ ?limit= (حتى 100)، ?offset=
GET/landing-pages/:id/historylanding_pages:readسجل التدقيق لصفحة واحدة، الأحدث أولاً: إنشاء وتحديث ونشر وإزالة وحذف مع الفاعل. ?limit= من 1 إلى 200
POST/landing-pageslanding_pages:writeإنشاء مسودة: name، slug، mode (dnd أو html)، html، css، grapejsData، form، seo (title، description، faviconUrl، ogImageUrl، noIndex)، language، dir، tags، sdkEnabled، personalized
GET/landing-pages/:idlanding_pages:readصفحة واحدة كاملة مع publicUrl وpreviewUrl
PUT/landing-pages/:idlanding_pages:writeتحديث؛ الصفحة الحية لا تتغير إلا عند النشر التالي
DELETE/landing-pages/:idlanding_pages:writeحذف مسودة (اسحب النشر أولًا)
POST/landing-pages/:id/duplicatelanding_pages:writeنسخ صفحة أو إنشاء صفحة من قالب؛ { "asTemplate": true } يحفظ النسخة كقالب
POST/landing-pages/:id/publishlanding_pages:publishتجميد المستند المنقّى وخدمته
POST/landing-pages/:id/unpublishlanding_pages:publishالسحب؛ يتغير رمز التوقيع
GET/landing-pages/:id/previewlanding_pages:readالمسودة معروضة كما ستكون الصفحة الحية (HTML)؛ تُهمَل إرسالاتها
GET/landing-pages/:id/submissionslanding_pages:readسجل الإرسالات، الأحدث أولًا؛ البيانات الشخصية مقنّعة بدون pii:view. ?limit= (حتى 200)، ?before=
GET/landing-pages/:id/submissions.csvlanding_pages:readكل الإرسالات كملف CSV مُتدفق، الأقدم أولًا: submitted_at، عمود لكل حقل في النموذج (كل إجابة، مربوطة بسمة أم لا)، person_id، identified_by، lists_subscribed، referrer وقيم utm_*؛ البيانات الشخصية مقنّعة بدون pii:view
GET/landing-pages/:id/reportlanding_pages:readالمشاهدات والمشاهدات الأولى والإرسالات لكل يوم (UTC)، والإجماليات ومعدل التحويل للمدة، وعدادات كل الوقت. ?days= من 1 إلى 365 (الافتراضي 30)
GET/landing-pages/:id/reviewlanding_pages:readمراجعة الإطلاق: نتائج (code، severity مانع أو توصية، scope، params). الموانع توقف النشر؛ يجيب POST .../publish بـ 400 مع النتائج نفسها
GET/landing-pages/handlelanding_pages:readعنوان صفحات مساحة العمل: { handle, host, example, customHost }. الـ handle هو معرّف مساحة العمل نفسه، أول جزء في كل عنوان صفحة - مبهم ودائم ولا يُختار ولا يُغيَّر؛ وcustomHost هو نطاق مساحة العمل النشط الخاص بها، عندما يكون لها واحد
GET/landing-pages/domainlanding_pages:publishنطاق مساحة العمل الخاص: { domain, limit, used, pagesHost } - domain (أو null) مع id وhostname وstatus (pending أو active أو failed) وverifiedAt وtarget وrecords (سجلات DNS المطلوب إضافتها) وproviderConfigured وlastError؛ ويَعدّ limit وused نطاقات صفحات الهبوط في المؤسسة
POST/landing-pages/domainlanding_pages:publishإضافة نطاقك الخاص: { "hostname": "pages.yourbrand.com" }. يرد بالنطاق بحالة pending مع سجلات DNS الخاصة به. 409 عندما يكون لمساحة العمل نطاق بالفعل أو تكون المؤسسة عند حدها (تذكر الرسالة الحد)
POST/landing-pages/domain/:id/verifylanding_pages:publishإعادة فحص DNS والشهادة على الحافة؛ يرد بالنطاق وحالته الحالية
DELETE/landing-pages/domain/:idlanding_pages:publishإزالة النطاق؛ تعود عناوين الصفحات فورًا إلى نطاق الصفحات
GET/landing-pages/capabilitieslanding_pages:read{ botCheck }: هل يمكن للخادم التحقق من Cloudflare Turnstile، ليتمكن النموذج من ضبط botCheck: true

المسارات العامة (بدون مصادقة)​

الطريقةالمسارما تفعله
GET/p/:handle/:slugالصفحة المنشورة
POST/p/:id/viewإشارة المشاهدة التي ترسلها الصفحة نفسها
POST/p/:id/submitإرسال النموذج؛ يحمل الجسم التوقيع المضمَّن في المستند المنشور، فلا يمكن الإرسال إلا من الصفحة كما نُشرت
GET/p/go/:workspaceId/:slugوجهة {{ 'slug' | landing_page_url }} في رسالة: تحويل 302 إلى العنوان القياسي للصفحة مع سلسلة الاستعلام (رمز الشخص وقيم UTM)
GET/p/confirm/:tokenالرابط في بريد التأكيد المزدوج: يشترك في القوائم التي يسميها الرمز ويعرض صفحة تأكيد

تُحدَّد حدود المعدل حسب من يرسل الطلب، لا حسب عنوان IP - قد يضع مشغل الهاتف المحمول أو مكتب آلاف الأشخاص خلف عنوان واحد. للصفحة وإشارة المشاهدة الخاصة بها و/p/go سقف للإغراق فقط قدره 30,000 طلب في الدقيقة لكل IP. لا يُقيَّد رابط التأكيد الصالح أبدًا؛ أما الروابط غير الصالحة فتُرفض بعد 300 في الدقيقة من IP واحد. إرسال النماذج: 15 في الدقيقة و60 في الساعة من الشخص نفسه (البريد الإلكتروني، وإلا الهاتف) على النموذج نفسه، و3,000 في الدقيقة لكل صفحة، و2,000 في الدقيقة لكل IP؛ ويعرض الإرسال المرفوض رسالة بلغة الصفحة. يقتصر جسم الصفحة على 500 كيلوبايت و50 حقلًا. يحمل كل نموذج حقل honeypot ومدة بقاء دنيا قدرها ثانيتان.

استخدام نطاقك الخاص​

بدلًا من https://<workspace id>.eu1.jrypages.com/<slug>، يمكن لمساحة العمل أن تخدم صفحاتها على نطاق فرعي تملكه - https://pages.yourbrand.com/<slug>. يُعدّ النطاق من الإعدادات -> صفحات الهبوط (بطاقة "نطاقك") أو عبر المسارات الأربعة أعلاه؛ ويحتاج إلى landing_pages:publish.

  1. أضف النطاق الفرعي (POST /landing-pages/domain). نطاق فرعي تملكه، مثل pages.yourbrand.com - ليس نطاقًا جذريًا، ولا نطاقًا لـ Joryio أبدًا. تسجّله Joryio على الحافة وترد بالنطاق بحالة pending مع سجلات DNS المطلوب ضبطها.
  2. أضف سجلات DNS لدى مزوّد DNS الخاص بك: سجل CNAME من النطاق الفرعي إلى الهدف الذي تعطيك إياه Joryio، إضافة إلى سجلات التحقق من الشهادة (TXT). تعرضها الإعدادات -> صفحات الهبوط مع زر نسخ؛ ويحمل records القائمة نفسها.
  3. تحقق (POST /landing-pages/domain/:id/verify). بمجرد تحليل CNAME تُصدر الشهادة خلال بضع دقائق وتصبح الحالة active؛ كما يُعاد فحص النطاقات المعلقة تلقائيًا كل خمس دقائق. التحقق الذي تنتهي مهلته يصبح failed مع السبب في lastError - صحّح السجلات وتحقق مجددًا، أو أزل النطاق وأضفه من جديد.

ما دام النطاق active، يستخدمه كل عنوان صفحة تكتبه Joryio - publicUrl الصفحة، ورابط المعاينة، و{{ 'slug' | landing_page_url }} في الرسائل وإعادة التوجيه /p/go خلفه؛ ويستمر عنوان الصفحات في خدمة الصفحات نفسها، فلا يتعطل شيء قبل ذلك أو بعده. إزالة النطاق (DELETE /landing-pages/domain/:id) تعيد العناوين فورًا إلى عنوان الصفحات؛ وتبقى الصفحات منشورة.

كم عددها. لمساحة العمل نطاق واحد على الأكثر. يجوز للمؤسسة افتراضيًا نطاق واحد لصفحات الهبوط عبر جميع مساحات عملها؛ يبلّغ GET /landing-pages/domain عن limit وكم منها used، والإضافة فوق الحد ترد بـ 409 مع رسالة تذكره. اطلب منا رفع الحد لمزيد من مساحات العمل أو العلامات التجارية.

القائمة التي تتطلب تأكيدًا مزدوجًا (إعدادات القائمة) لا يُشترك فيها مباشرة من نموذج أبدًا. يُكتب الشخص ويُسجَّل الحدث، ويطلب الرد التحقق من البريد الوارد، ويحمل بريد واحد (بلغة الصفحة، عبر إعداد البريد الخاص بمساحة العمل) رابطًا موقعًا صالحًا سبعة أيام؛ يشترك GET /p/confirm/:token في القوائم مع optInSource: double_opt_in ويعرض صفحة تأكيد. يسرد صف السجل تلك القوائم تحت listsPending؛ وتذكر مراجعة الإطلاق أي القوائم ستطلب تأكيدًا.

يعرض form.botCheck: true أداة Cloudflare Turnstile قبل زر الإرسال ويرفض الإرسال الذي لا يتحقق رمزه. متاح فقط عندما يكون الخادم مهيأً لـ Turnstile (GET /landing-pages/capabilities). النماذج داخل الرسائل في التطبيق لا تحتاجه أبدًا: يصادقها SDK.

الزوار وWeb SDK والتخصيص​

تعدّ الصفحة المنشورة بنفسها المشاهدات والمشاهدات الأولى والإرسالات؛ والزائر الذي يصل عبر رابط رسالة يحمل رمزه (?jp=، انظر مرشح Liquid أدناه) يُكتب له Landing Page Viewed في ملفه. مفتاحان لكل صفحة يذهبان أبعد:

  • sdkEnabled يحمّل Web SDK لمساحة العمل على الصفحة الحية (يتطلب تطبيق ويب نشطًا في الإعدادات > التطبيقات، وإلا يُرفض الحفظ). يحصل كل زائر على جلسة وأحداث كأي صفحة فيها SDK؛ يسجل وقت التشغيل Landing Page Viewed عبر SDK، ويُحدَّد الزائر الحامل للرمز عند الوصول، ويحدد النموذج المُرسل الزائر بوصفه الشخص الذي كُتب إليه، فيندمج تاريخه المجهول في الملف الشخصي. يمكن أن تظهر الرسائل داخل التطبيق الموجهة إلى تطبيق الويب على الصفحة. لا تحمّل معاينة المحرر SDK أبدًا.
  • personalized يعرض Liquid الصفحة للزائر الذي يصل برمز، كما تفعل الرسالة ({{ user.firstName | default: "there" }}، السمات، landing_page_url)؛ وبدون رمز تُعرض الصفحة نفسها بشخص فارغ فتظهر القيم الافتراضية. يُقدَّم العرض الشخصي مع Cache-Control: private, no-store؛ ومرشح catalog غير متاح في الصفحات.

القوالب والذكاء الاصطناعي والروابط من الرسائل​

القوالب المدمجة. يسرد ?templates=true قوالب مساحة العمل وخمسة قوالب مدمجة (الاشتراك في النشرة، التسجيل في فعالية، قائمة انتظار منتج، سحب على جائزة، قريبًا). للقالب المدمج معرّف ثابت؛ وPOST /landing-pages/:id/duplicate عليه ينشئ صفحة عادية في مساحة العمل. أي صفحة تصبح قالبًا بـ { "asTemplate": true }.

التصميم والمراجعة بالذكاء الاصطناعي (جلسة لوحة التحكم فقط، landing_pages:write): POST /ai/pages/design مع brief، واختياريًا language وbrandVoiceId وarchetype (bold، editorial، minimal، product، event) وcolorStrategy (restrained، committed، drenched) وgoal (signup، waitlist، event، download، contest، other) يعيد { name, seo, design, html, css, form, language, dir } - يخطط النموذج الأقسام ويكتب النص، وكود حتمي يبني الترميز على مجموعة العلامة التجارية، ولا يُحفظ شيء حتى تحفظ. POST /ai/pages/revise مع source (HTML الصفحة) وinstruction يعيد { source, reply }، المستند المراجَع كاملًا؛ تُرفض مراجعة تحذف النموذج أو تضيف سكريبتًا.

الربط بصفحة من رسالة. في أي نص بريد أو SMS أو WhatsApp، يولّد {{ 'spring-sale' | landing_page_url }} رابطًا إلى الصفحة المنشورة بهذا الـ slug. يحمل الرابط رمز المستلم (?jp=)، فتُكتب المشاهدة وإرسال النموذج إلى ذلك الشخص حتى قبل أن يكتب بريده؛ ويضيف وسيط ثانٍ سلسلة استعلام: {{ 'spring-sale' | landing_page_url: 'utm_campaign=spring' }}. الـ slug غير المنشور يولّد سلسلة فارغة.

الأحداث. يظهر Landing Page Viewed وLanding Page Form Submitted في كل منتقي أحداث (محفزات الرحلات، الحملات المحفَّزة، الشرائح) ضمن أحداث المنصة مع خصائصها.

ما يفعله الإرسال​

  1. يتحقق من القيم مقابل المخطط؛ تُتجاهل الحقول غير المعروفة، وتعود الأخطاء كـ { "ok": false, "errors": [...] }.
  2. يحدد الشخص: يُحدَّث الملف الموجود بنفس البريد، وإلا يُنشأ ملف بمعرّف خارجي مولَّد وsource بقيمة landing_page:<slug>. لا يُملأ البريد أو الهاتف إلا حيث لا يملك الملف أيًا منهما؛ والشخص المحدَّد برمز الرابط (jp) يمكنه تحديث هاتفه، ولا يمكنه تغيير بريده أبدًا.
  3. يكتب السمات المعيَّنة، ويشترك في القوائم المحددة، ويسجل Landing Page Form Submitted مع pageId وpageSlug وpageName ومفاتيح الحقول وlistsSubscribed وreferrer وقيم UTM، وemail وphone من النموذج مع phoneUpdated (true عندما يحمل الملف الآن هاتف النموذج، وfalse عندما احتفظ بهاتف مختلف؛ ويغيب عندما لا يحتوي النموذج على هاتف أو يحتوي على الهاتف نفسه).
  4. يحفظ صفًا في السجل (تبويب الإرسالات) ويزيد عداد submissions للصفحة.
  5. يجيب { "ok": true, "message": "..." } أو { "ok": true, "redirect": "https://..." }.

انظر أيضًا: صفحات الهبوط والنماذج في دليل المستخدم - الميزة نفسها من جهة المسوّق.