أخبر حملة بما حدث. وهي تتولى التسويق الذي يليه.
سطر واحد يرى المتصفح. وطلب HTTP واحد يخبر حملة بما جرى داخل نظامك أنت — دفعة، حجز، اشتراك أُلغي. وكل ما بعد ذلك شأن صاحب العمل، لا شأنك.
Claude Code أو Cursor أو Codex — أو الصقه في Lovable و v0 و Bolt
ثبّت حملة على هذا الموقع وتتبّع التسجيلات والمشتريات
سطر التثبيت
انسخه من الإعدادات ← الموقع في حملة، أو دع لوحة التحكم تعطيك إياه. لا يحمل أي سرّ: معرّف النشاط بداخله ظاهر أصلاً في كل صفحة تُحمّل فيها المكتبة.
<script src="https://app.hamla.io/s/{businessId}.js" async></script>هذا السطر وحده يغطي الزيارات ومصادرها والسلوك داخل الموقع وكل ما تستدعي لأجله hamla.track() في الصفحة — دون مفتاح، لأن حزمة منشورة لا تستطيع حفظ مفتاح.
أما الأحداث القادمة من خادمك فتحتاج مفتاحاً سرّياً: الإعدادات ← مفاتيح API، ويبدأ بـ sk_live_. أبقه على خادمك. يستطيع الكتابة في بيانات العملاء، فعامله معاملة كلمة مرور قاعدة البيانات.
الأحداث
سطر التثبيت لا يرى قاعدة بياناتك. حين يدفع أحدهم أو يحجز أو يلغي أو ينهي درساً، فذلك يقع في نظامك — واستدعاء واحد داخل كود موجود عندك أصلاً هو ما يتيح لحملة أن تتصرّف بناءً عليه.
curl -X POST https://app.hamla.io/api/sdk/track \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"event": "subscription_started",
"type": "purchase",
"identity": { "email": "omar@raqmi.co" },
"value": 29,
"currency": "JOD",
"idempotencyKey": "invoice_9911"
}'| الحقل | ماذا يفعل |
|---|---|
| identityمطلوب | لمن حدث — واحد من email أو phone أو platformCustomerId. وواحد منها يكفي، ولا يلزم أن يكون البريد: عيادة لا تجمع سوى أرقام الهواتف ترسل phone وحده، دائماً. |
| eventمطلوب | اللحظة، بمفرداتك أنت، من حرف إلى 64 حرفاً. عيادة ترسل treatment_completed، ومدرسة ترسل lesson_finished. والمحفّزات والجماهير تطابقه حرفياً. |
| typeاختياري | ما الذي يعنيه الحدث، من الكلمات السبع أدناه. اتركه وستستنتج حملة من المبلغ ومن الأسماء التي تعرفها؛ أرسله ولن يُخمَّن شيء أبداً. |
| value, currencyاختياري | المبلغ وعملته. يُحتسب ضمن إيراد جهة الاتصال بحسب النوع — ومال العيادة مال. |
| occurredAtاختياري | بصيغة ISO 8601 أو ميلي ثانية منذ الحقبة. الماضي مسموح، وهو ما يتيح استيراد السجل؛ وأبعد من خمس دقائق في المستقبل مرفوض. |
| propertiesاختياري | أي JSON يستحق الحفظ مع الحدث، للأبد. حتى 32,768 بايت، تُخزَّن متداخلة لا مفروشة في جذر الحمولة. |
| traitsاختياري | ما هو صحيح الآن — plan و subscription_status. ينشئ حقله المخصص عند أول ظهور وتفوز آخر قيمة، فتستطيع الشرائح الترشيح عليه فوراً. |
| tagsاختياري | تُضاف إلى وسوم جهة الاتصال دون أن تستبدل ما لديها. |
| idempotencyKeyاختياري | رقم فاتورتك أو طلبك. المفتاح نفسه مرتين يُسجَّل مرة واحدة، وهذا ما يجعل إعادة المحاولة — أو إعادة تشغيل الاستيراد كاملاً — بلا تكلفة. |
الكلمات السبع
اسم الحدث يبقى اسمك أنت وبلغتك أنت. و`type` هو كيف تقول ماذا تفعل حملة به — وهو الفرق بين أن تُحتسب مئة دينار في عيادة إيراداً وألّا تُحتسب شيئاً.
| الحقل | المعنى | الأثر |
|---|---|---|
| purchase | مبلغ مستلم | يضيف إلى الإيراد، ويُحتسب طلباً |
| refund | مبلغ مُعاد | يخصم من الإيراد |
| booking | التزام قبل الدفع | بلا إيراد |
| lead | تم التقاط بيانات التواصل | بلا إيراد |
| checkout_started | بدأ ولم يُكمل | بلا إيراد |
| fulfilled | تم التسليم | بلا إيراد |
| cancelled | انتهى | بلا إيراد |
الإرسال مجاني. والوصول إلى الناس هو ما يُدفع مقابله.
الأحداث لا تُحتسب أبداً، في أي خطة — أرسل كل ما لديك، إلى الأبد. و POST /api/sdk/track/batch يستقبل 500 حدث ماضٍ في المرة، فلا يكون يومك الأول يوماً صفرياً، والسجل المستورد لا يرسل رسالة إلى أحد.
ماذا يشتري لك حدث واحد
تكتب الاستدعاء مرة. وكل ما يلي يصبح متاحاً لمن يدير التسويق، دون أي كود إضافي منك.
حملة تنطلق عليه
رسالة متابعة بعد ساعة من treatment_completed. وتهيئة المشترك لحظة أن يدفع. لا غداً ولا في الدفعة التالية — بل حينها.
جمهور يُبنى منه
حقلان يظهران لكل اسم حدث: متى حدث آخر مرة، وكم مرة حدث. و«اشترى ٣ مرات فأكثر وانقطع ٦٠ يوماً» قائمة استرجاع تبقى صحيحة وحدها.
تسلسل ينتهي عليه
من يفعل ما أردته يتوقف عن تلقّي الطلب، ويصير نجاح الحملة يُقاس عليه.
على Node
npm install @gethamla/node
طابور وإعادة محاولة و flush() لبيئات serverless. لا يرمي استثناءً ولا يحجب التنفيذ — والمفتاح الناقص يتحوّل إلى تحذير مسجَّل، لأن بيانات التسويق لا تساوي أبداً إتمام عملية شراء لعميل.
شغّل حملة من مساعدك
https://app.hamla.io/mcp
نقطة OAuth واحدة تكشف الأدوات نفسها التي يعمل عليها وكيل حملة: قراءة التحليلات، وبناء الحملات، وإدارة جهات الاتصال، واستيراد قائمة.
مُدرجة في سجل MCP باسم io.hamla/hamla، ومتاحة كتطبيق في ChatGPT.
إن كنت وكيلاً
كل ما سبق موجود بصيغة تستطيع تحليلها، مولَّدة من السجلات نفسها التي تتحقق بها الواجهة — فلا تستطيع هذه الصفحة أن تصف حقلاً سترفضه النقطة.
hamla.io/llms.txt
كل صفحة في هذا الموقع مع سطر يصفها. و docs.hamla.io/llms.txt يفهرس التوثيق كاملاً.
hamla.io/developers.md
المحتوى نفسه بصيغة markdown — بلا وسوم تُزال ولا تخطيط يُخمَّن.
docs.hamla.io/reference/events
حقلاً حقلاً، مع كل حالة خطأ ومعناها. الصيغة المطوّلة للجدول أعلاه.
GET /developers.md
# Hamla for developers
> Marketing automation a business installs with one script tag.
> Events are free and unmetered on every plan; contacts and sending are what cost.
## Install
Add before `</head>`. The business id comes from Settings → Website in Hamla
and is public — it appears in every page that loads the SDK.
```html
<script src="https://app.hamla.io/s/{businessId}.js" async></script>
```
This covers visits, sources, on-site behaviour, and `hamla.track()` calls made
in the page. No key: a published bundle cannot hold one.
## Events — POST /api/sdk/track
Server-side. Requires a secret key from Settings → API keys.
```
Authorization: Bearer sk_live_...
```
A publishable key (`pk_live_`) is refused with 403 here: it ships in page
source, so honouring it would let any visitor invent revenue.
```bash
curl -X POST https://app.hamla.io/api/sdk/track \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"event": "subscription_started",
"type": "purchase",
"identity": { "email": "omar@raqmi.co" },
"value": 29,
"currency": "JOD",
"idempotencyKey": "invoice_9911"
}'
```
### Fields
- `identity` **(required)** — Who it happened to — one of email, phone or platformCustomerId. Any one is enough, and it does not have to be the email: a clinic that only ever collects phone numbers sends phone, forever.
- `event` **(required)** — The moment, in your own vocabulary, 1–64 characters. A clinic sends treatment_completed, a school sends lesson_finished. Triggers and audiences match it exactly.
- `type` — What the event MEANS, from the seven below. Leave it out and Hamla infers from the amount and from names it recognises; send it and nothing is ever guessed.
- `value, currency` — The amount and its currency. Counted toward the contact's revenue according to the type — a clinic's money is money.
- `occurredAt` — ISO 8601 or epoch milliseconds. The past is allowed, which is what makes backfilling possible; more than five minutes into the future is refused.
- `properties` — Any JSON worth keeping with the event, forever. Up to 32,768 bytes, stored nested rather than spread into the payload root.
- `traits` — What is true NOW — plan, subscription_status. Creates its own custom field on first sight and newest value wins, so segments can filter on it immediately.
- `tags` — Merge-added to the contact, never replacing tags it already carries.
- `idempotencyKey` — Your invoice or order id. The same key twice is recorded once, which is what makes a retry — or a re-run of your whole backfill — free.
### What `type` means
Your `event` name stays yours, in your own language. `type` says what Hamla
should do with it.
- `purchase` — Money received. Adds to revenue, counts as an order.
- `refund` — Money returned. Subtracts from revenue.
- `booking` — Committed, not yet paid. No revenue.
- `lead` — Identity captured. No revenue.
- `checkout_started` — Started, not finished. No revenue.
- `fulfilled` — They received it. No revenue.
- `cancelled` — It ended. No revenue.
### Backfill — POST /api/sdk/track/batch
1–500 past events per request, same field rules, each with its real
`occurredAt`. Backfilled history **never starts a campaign** and never fires a
segment-entry trigger. Give every row an `idempotencyKey` and the job is safe
to re-run.
### Browser
`hamla.track('download_ebook', { asset: 'guide.pdf' })` — no key needed. These
count as deliberate and can start campaigns. Anything involving money or your
own records should come from your server.
## Node
```bash
npm install @gethamla/node
```
Wraps the same HTTP API with queueing and retries. Never throws, never blocks;
call `flush()` before a serverless runtime freezes.
## MCP
```
https://app.hamla.io/mcp
```
OAuth. Registry name `io.hamla/hamla`. Exposes the same tools Hamla's own
agent runs on — analytics, campaigns, contacts, segments, imports.
## More
- https://hamla.io/llms.txt — this site, indexed
- https://docs.hamla.io/llms.txt — the documentation, indexed
- https://docs.hamla.io/reference/events — every field and error status
- https://github.com/usehamla — agent skills and rules
Handles: `usehamla` on GitHub, `@gethamla` on npm, `hamla.io` on the web.