Skip to main content
حملة لا تتصرّف إلا بما تراه. هي ترى موقعك أصلاً — السكربت يتابع الزيارات والنقرات والسلات وحده. لكنها لا ترى داخل نظامك. حين يدفع أحدهم، أو يلغي اشتراكه، أو يحجز موعداً، أو ينهي درساً، فكل هذا يحدث في قاعدة بياناتك أنت، وحملة لا تعلم عنه شيئاً. حدث حملة هو أن تخبرها: هذا حدث الآن.
هذه هي الفكرة كلها. والباقي على حملة — تجد عمر، تكتب الحدث في سجلّه، تنقله من «تجربة» إلى «عميل»، وإذا كانت هناك حملة تنتظر هذه اللحظة بالذات، تنطلق.

لماذا تستحق عشر دقائق من وقت مبرمجك

الأولى تصلح لنشرة بريدية. الثانية تصلح لاستعادته.

أرسل أول حدث

1

احصل على مفتاح سري

لوحة التحكم ← الإعدادات ← مفاتيح API. المطلوب هو المفتاح السري، ويبدأ بـ sk_live_.احتفظ به على خادمك فقط. هو يستطيع الكتابة في بيانات عملائك، فتعامل معه كأنه كلمة مرور قاعدة البيانات: يجب ألّا يظهر أبداً في صفحة ويب أو تطبيق جوال.
2

أرسل الحدث من مكان حدوثه

في الكود الموجود لديك أصلاً — استقبال الدفع، تأكيد الحجز، تسجيل مستخدم جديد — أضف نداءً واحداً.
وعلى Node.js، حزمة npm install @gethamla/node تعطيك الشيء نفسه مع طابور إرسال وإعادة محاولة جاهزة:
المطلوب شيئان فقط: مَن (identity — بريد أو رقم هاتف أو معرّف المستخدم لديك) وماذا (event — أي اسم تختاره).
3

تأكد من وصوله

افتح صفحة جهة الاتصال في حملة. ستجد الحدث في سجلّها الزمني، بوقت حدوثه.بهذا اكتملت الدورة. وكل ما يلي هو ما تستطيع فعله به الآن.

مَن هو الشخص

يجيب عنه حقل identity، وواحد منه يكفي. لن ترسل الثلاثة أبداً، ولن تحتاج بريداً إلكترونياً أبداً. عيادة لم تسأل أحداً يوماً عن بريده الإلكتروني عميلة من الطراز الأول في حملة: أرسل رقم الهاتف وحده، دائماً. وإن أرسلت أكثر من واحد فلن تحصل على جهتَي اتصال. حملة تدمجها في شخص واحد وتحتفظ بكل منها طريقةً للعثور عليه — فرقم هاتف يصل بعد أشهر ينضم إلى البريد الذي أرسلته أولاً، ويبقى تاريخه كله في مكان واحد. وهذا يستحق كلما توفّر لك الاثنان.
الهوية ليست إذناً. معرفة رقم هاتف أحدهم هي ما يتيح لحملة أن تعرفه، وليست موافقة على إرسال رسالة نصية أو واتساب إليه. تلك موافقة منفصلة، وحملة تفصل بينهما عن قصد.

وبماذا تناديه

الهوية تقول من. ولا تقول بماذا تناديه — وجهة الاتصال بلا اسم هي سبب خروج مرحباً {{contact.firstName}} هكذا: مرحباً صديقي. الأسماء تمرّ عبر identify، المسار الرفيق لـ track:
أرسل الاسم بالشكل الذي تخزّنه به أصلاً: يُقسَّم name عند وصوله: الكلمة الأولى هي الاسم الأول والبقية اسم العائلة، فيُنادى صاحب «سارة آل عتيبي» باسم سارة وصاحب «محمد بن عبد الله» باسم محمد. وإن أرسلت الشكلين معاً غلبت الأجزاء الصريحة، حقلاً حقلاً. نادِه حيثما تعرفهم أصلاً — التسجيل أو الدفع أو تسجيل الدخول. ومناداته عند كل تسجيل دخول آمنة وتستحق: حملة تملأ الناقص ولا تستبدل اسماً موجوداً أبداً، فيبقى أي تصحيح يجريه الشخص في ملفه.
يقبل profile أيضاً country وcity وlanguage وtimezone. وحقل timezone هو ما يُبقي خطوة «بعد يوم» خارج ليل المستلم — حزمة المتصفح تملؤه عنك، وعلى الخادم أن يرسله حين يعرفه.

والآن استخدمه

إرسال الحدث هو الخطوة الأولى فقط. وهذا ما هو لأجله.

١. ابدأ حملة في اللحظة نفسها

افتح حملة ← متى تبدأ الحملة؟حدث في تطبيق ← التطبيق: أحداث تطبيقكاسم الحدث، واكتبه. هذا كل شيء. كل شخص يُطلق هذا الحدث من الآن فصاعداً تصله رسالتك. ليس غداً، ولا في الدفعة التالية — بل في حينه.
يجب أن يطابق الاسم ما يرسله كودك حرفياً: treatment_completed وليس Treatment Completed. وبمجرد وصول الحدث مرة واحدة، يظهر في القائمة فتختاره بدل كتابته.
وتحت الاسم خيار يمكن الدخول مرة أخرى لاحقاً:
  • مغلق — يُسجَّل كل شخص مرة واحدة فقط، للأبد. مناسب لسلسلة الترحيب.
  • مفتوح — يمكن تسجيله مرة أخرى في فترة لاحقة. مناسب للتجديدات والشراء المتكرر والفحص الدوري.

٢. ابنِ منه شريحة

فور وصول أول حدث purchase، يظهر حقلان جديدان في بنّاء الشرائح تحت مجموعة الأحداث: لا أحد ينشئ هذين الحقلين. هما موجودان لأنك أرسلت الحدث. اجمع بينهما وستحصل على أفضل عملائك وقد صمتوا: اشترى 3 مرات فأكثر، وآخر مرة قبل أكثر من 60 يوماً. هذه قائمة استعادة، وتبقى صحيحة إلى الأبد، لأن خادمك يواصل إرسال الأحداث.
مجموعة الأحداث لا تظهر في البنّاء إلا بعد وصول أول حدث من أي نوع. قبل ذلك لا يوجد ما تُصفّي عليه.

٣. اجعله خط النهاية للحملة

يجب أن تتوقف الحملة عن مضايقة الشخص فور أن يفعل ما أردته منه. داخل الحملة ← نهاية التسلسلعند تحقق حدث ← اختر حدثك. الآن كل من يُطلق subscription_started يتوقف عن استقبال بقية الرسائل، ويُفحص ذلك قبل كل إرسال. والحدث نفسه يصبح مقياس نجاح الحملة في تقاريرك.

٤. أو اطلب فحسب

لست مضطراً لبناء أي شيء. اكتب:
«كل من أنهى علاجاً الشهر الماضي ولم يحجز بعدها — أرسل له تذكيراً.»
حملة تقرأ الأحداث نفسها وتنفّذ.

وأمران يحدثان تلقائياً

  • الشخص يتقدّم في رحلته. بعض الأسماء لها معنى محدد: trial_started وsubscription_started وpurchase تنقل الشخص إلى مرحلة القرار، وsubscription_renewed وrepeat_purchase تنقله إلى الاحتفاظ. استخدم هذه الأسماء حين تناسبك وتبقى الرحلة صادقة بلا عمل إضافي. أما أسماؤك الخاصة فتُسجَّل كاملة، لكنها لا تحرّك المرحلة.
  • كل شيء يغذّي الأرقام. التفاعل والتقييم ونسب المصدر تقرأ أحداثك، فتعكس التقارير ما حدث فعلاً في نشاطك التجاري، لا ما حدث في المتصفح وحده.

الأحداث والسمات شيئان مختلفان

هذا هو التمييز الوحيد الذي يستحق الانتباه.
  • ما حدث في لحظة هو حدث. يُحفظ للأبد ولا يُستبدل. «ترقّى إلى Pro يوم الثلاثاء.»
  • ما هو صحيح الآن ويمكن أن يتغير هو سمة. القيمة الأحدث تفوز. «الباقة هي Pro.»
أرسل الاثنين معاً في النداء نفسه:
وأول مرة ترسل فيها مفتاح سمة جديداً، تنشئ حملة الحقل المخصص المقابل تلقائياً، وتستطيع الشرائح التصفية عليه فوراً. المفاتيح تُكتب بصيغة snake_case، والحقل يحتفظ بالنوع الذي وُلد به. قاعدة سريعة: السمات تجيب عن «من هذا الشخص اليوم»، والأحداث تجيب عن «ماذا فعل». وأغلب الشرائح الجيدة تستخدم الاثنين.

مثالان كاملان

عيادة

نظام الحجز لديك يعرف أصلاً متى ينتهي العلاج. أرسله:
الآن، وبلا أي كود إضافي:
  1. مُطلِق — حملة على treatment_completed ترسل رسالة متابعة بعد ساعة، مع تفعيل يمكن الدخول مرة أخرى لاحقاً لتعمل مع كل زيارة.
  2. شريحةtreatment_completed آخر مرة قبل أكثر من 180 يوماً هم كل من حان موعد فحصهم.
  3. خط النهاية — اجعل appointment_booked هو الهدف، فيتوقف التذكير عمّن أعاد الحجز.

شركة برمجيات

خطاف الفوترة لديك يعمل أصلاً. أرسله:
الآن:
  1. مُطلِق — التهيئة تبدأ لحظة الدفع.
  2. شريحةالباقة هي pro تحصر أي حملة في العملاء الدافعين، وتبقى صحيحة مع كل ترقية أو انقطاع.
  3. الرحلةsubscription_started ينقله إلى القرار وحده.
  4. أرسل subscription_expired عند الانقطاع مع traits: { "subscription_status": "expired" }، فتمتلئ شريحة الاستعادة من تلقاء نفسها.

أحضر تاريخك معك

لست مضطراً للبدء من الصفر. POST /api/sdk/track/batch يستقبل حتى 500 حدث سابق في الطلب الواحد — البنية نفسها، داخل مصفوفة events، ولكل حدث تاريخه الحقيقي في occurredAt. دورة واحدة على جدول المستخدمين لديك تعطي معنى من اليوم الأول لشريحة مثل «اشترى سابقاً وصمت 60 يوماً».
التاريخ المستورد لا يرسل شيئاً أبداً. الأحداث المستوردة تملأ الملفات والأعداد والشرائح، لكنها لا تبدأ حملات ولا تُطلق مُطلِقات دخول الشرائح. سنة من المشتريات القديمة يجب ألّا ترسل سنة من الرسائل الليلة.الأحداث الحيّة وحدها — عبر /api/sdk/track أو hamla.track() — هي ما يستطيع بدء حملة.
أعطِ كل صف مفتاح idempotencyKey (رقم الفاتورة أو الطلب لديك) ويصبح تشغيل السكربت كاملاً مرة أخرى آمناً.

أسئلة شائعة

كلٌّ منهما يغطي نصفاً مختلفاً. السكربت يرى المتصفح — الزيارات والمصادر والسلوك على الموقع. والأحداث تعرف قاعدة بياناتك — الباقات والمدفوعات والمحطات المهمة. كلٌّ منهما يعمل وحده، ومعاً ترى حملة الشخص كاملاً.
نعم، لما يحدث فعلاً داخل الصفحة: hamla.track('download_ebook', { asset: 'guide.pdf' }). هذه تُعدّ أحداثاً متعمَّدة وتستطيع بدء حملة، ولا تحتاج أي مفتاح.أما كل ما يتعلق بالمال أو بسجلاتك الخاصة فمكانه الخادم، حيث يوجد المفتاح السري وحيث تكون الوقائع حقيقية.
بنفس idempotencyKey ← يُحتسب مرة واحدة، ويأتي في الرد deduped: true. وبدون مفتاح ← كل إرسال حدث مستقل، لأن الناس أحياناً يشترون مرتين فعلاً.
ما يسمّيها به نشاطك التجاري فعلاً. حملة لا تحتاج معرفة مفرداتك مسبقاً — العيادة ترسل treatment_completed، والمدرسة ترسل lesson_finished.السبب الوحيد لاستعارة أحد أسماء حملة هو مرحلة الرحلة: purchase وtrial_started وsubscription_started وsubscription_renewed وrepeat_purchase وأخواتها تنقل الشخص إلى الأمام تلقائياً.
ثلاثة أسباب معتادة، بالترتيب:
  1. الاسم غير مطابق. المطابقة حرفية تماماً، وتفرّق بين الحروف الكبيرة والصغيرة.
  2. الحدث دخل عبر مسار الدفعات. الاستيراد لا يُطلق شيئاً أبداً.
  3. الشخص مسجَّل من قبل. فعّل يمكن الدخول مرة أخرى لاحقاً للحظات المتكررة.
تفاصيل كل حقل والحدود ورسائل الخطأ في مرجع الأحداث.