> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hamla.io/llms.txt
> Use this file to discover all available pages before exploring further.

# اربط تطبيقك

> للمطوّرين: اربط موقعاً أو منتج SaaS أو خادم تطبيق جوّال بحملة في نحو خمس عشرة دقيقة، فتطلق لحظاتُ منتجك الحملات، وتملأ الشرائح، وتُحتسب إيراداً.

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

تحتاج ثلاثة أشياء: الدخول إلى لوحة تحكم حملة، وكود HTML لموقعك، وكود الخادم الذي يتم فيه التسجيل والدفع.

> [!NOTE]
>
> **تريد الاختبار أولاً؟** لا يوجد مفتاح اختبار منفصل بعد. كل المفاتيح حيّة، فقد يطلق حدث ترسله حملة حقيقية. ابنِ على نشاط ثانٍ تنشئه للاختبار، وبدّل المفتاح حين تطلق.

> [!NOTE]
>
> **تبني بأداة مثل Lovable أو v0 أو Bolt لشخص ليس لديه حساب في حملة؟** ابدأ بالتثبيت القابل للاستلام في [hamla.io/developers](https://hamla.io/ar/developers)، ثم عُد إلى هنا بعد أن يستلم صاحب النشاط التثبيت، فالمفتاح السري لا يصدر قبل ذلك.

## كيف تتكامل القطع

| القطعة | أين تعمل | ماذا تخبر حملة | المفتاح |
| - | - | - | - |
| وسم السكربت | صفحات موقعك | الزيارات والمصادر والسلال والنقرات والنوافذ | لا شيء، فمعرّف النشاط فيه علني |
| `identify` | خادمك (أو الصفحة) | **مَن** هو الشخص، وبماذا يُنادى | مفتاح سري، من الخادم |
| `track` | خادمك | **ماذا حدث**: تسجيل أو دفع أو حجز | مفتاح سري، مطلوب |

وسم السكربت يرى المتصفح، وخادمك يعرف الوقائع. أرسل الاثنين فترى حملة الشخص كاملاً.

**1. أضف وسم السكربت**

انسخ المقتطف من **الإعدادات ← الموقع** وضعه في كل صفحة، قبل `</head>`:

```html theme={null}
<script src="https://app.hamla.io/s/YOUR_BUSINESS_ID.js" async></script>
```

يسجّل الزيارات ومن أين جاءت، ويعرض النوافذ، ويعطي كل متصفح معرّف زائر. والتطبيق الجوّال الذي لا صفحات ويب له يستطيع تخطّي هذه الخطوة.

**2. أنشئ مفتاحاً سرياً**

**الإعدادات ← مفاتيح API** ← أنشئ مفتاحاً **سرياً**. يبدأ بـ `sk_live_`.

خزّنه باسم `HAMLA_API_KEY` في بيئة خادمك. فهو يستطيع كتابة بيانات العملاء، فعامله ككلمة مرور قاعدة البيانات: لا تضعه أبداً في صفحة ويب، ولا في تطبيق جوّال، ولا في متغيّر بيئة يرسله إطار عملك إلى المتصفح (`NEXT_PUBLIC_…` و`VITE_…`).

على Node.js، ثبّت الحزمة:

```bash theme={null}
npm install @gethamla/node
```

```ts theme={null}
import { Hamla } from '@gethamla/node';
export const hamla = new Hamla(); // يقرأ HAMLA_API_KEY
```

وأي لغة أخرى تعمل عبر HTTP عادي. الحزمة تضيف الطابور وإعادة المحاولة فقط.

**3. عرّف الناس عند تسجيلهم**

هذه الخطوة هي أكثر ما تتخطّاه عمليات الربط، وهي التي تقرّر إن كانت حملة تستطيع مراسلة الشخص يوماً.

استدعِ `identify` من خادمك عند التسجيل، ومرة أخرى عند تسجيل الدخول:

```ts theme={null}
await hamla.identifyNow({
  identity: { email: user.email, platformCustomerId: user.id },
  profile: { name: user.name },
  method: 'signup',
  context: {
    userAgent: request.headers.get('user-agent') ?? undefined,
    country: request.headers.get('x-vercel-ip-country') ?? undefined,
  },
});
```

```bash theme={null}
curl -X POST https://app.hamla.io/api/sdk/identify \
  -H "Authorization: Bearer $HAMLA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "identity": { "email": "omar@raqmi.co", "platformCustomerId": "user_812" },
    "profile": { "name": "Omar Al Saleh" },
    "method": "signup"
  }'
```

ماذا يفعل:

* ينشئ جهة الاتصال، أو يُثري الموجودة. الأسماء والموقع تملأ الناقص ولا تستبدل شيئاً أبداً.
* يسجّل أنك **أنت** من أدخل هذا الشخص إلى حملة، وهذا ما يتيح للحملات مراسلته بالبريد. وبتعريفك الشخص تؤكد أن لديك إذناً بالتسويق له، كما تشترط شروط حملة.
* يربط زياراته المجهولة السابقة، ومنها الإعلان الذي جاء به، حين تمرّر ملف تعريف `visitorId` أو تستدعيه من الصفحة بـ `hamla.identify({ email })`.

> [!WARNING]
>
> **`track` وحده لا يجعل الشخص قابلاً للوصول.** جهة الاتصال التي لم تعرفها حملة إلا من حدث ليس لها إذن مسجَّل، فلن ترسل إليها أي حملة، ولا حتى بريد. استدعِ `identify` أولاً، في لحظة تسجيل الشخص. وتسجيل حملة نفسها يعمل بهذا الترتيب.

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

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

في الكود الذي لديك أصلاً، مثل إشعار الدفع أو تأكيد الحجز أو بدء التجربة، أضف استدعاءً واحداً:

```ts theme={null}
hamla.track({
  event: 'subscription_started',
  type: 'purchase',
  identity: { platformCustomerId: user.id },
  value: 29,
  currency: 'USD',
  idempotencyKey: invoice.id,
  traits: { plan: 'pro' },
});
```

* `event` اسمك أنت للحظة، بأي لغة. والمحفّزات والشرائح تطابقه حرفياً.
* `type` يقول ماذا **يعني** الحدث (`purchase` و`refund` و`booking` و`signup` و`trial`…)، فيُحتسب الدفع إيراداً. انظر [القائمة كاملة](https://docs.hamla.io/ar/reference/events.md).
* `idempotencyKey` رقم فاتورتك أو طلبك. فإشعار الدفع المُعاد يُحتسب مرة واحدة.
* `traits` تصف الشخص **الآن** (خطته وحالته). والحدث هو ما فعله.

لا يرمي `track` و`identify` أخطاءً ولا يعطّلان شيئاً أبداً، فلا يستطيع استدعاء تسويقي أن يكسر عملية دفع. وعلى المنصات الخالية من الخوادم، استدعِ `await hamla.flush()` قبل أن تعيد الدالة، كي يُرسَل الطابور.

**5. تأكد من وصوله**

استخدم `trackNow` مرة واحدة، لتقرأ الجواب:

```ts theme={null}
const result = await hamla.trackNow({ event: 'subscription_started', type: 'purchase', identity: { email: 'you@yourcompany.com' }, value: 29, currency: 'USD' });
console.log(result);
```

تخبرك النتيجة إن كان الحدث قد وصل، وبماذا قرّرت حملة:

```json theme={null}
{
  "ok": true,
  "status": 200,
  "data": {
    "contactId": "cm4x...",
    "isNew": false,
    "deduped": false,
    "interpreted": { "type": "purchase", "countedRevenue": 29 }
  }
}
```

وحين يكون `ok` هو `false`، يقول `reason` لماذا (`config` أو `invalid_input` أو `http` أو `network` أو `timeout`)، ويحمل `status` رمز HTTP. وعبر HTTP العادي تحصل على `data` نفسها داخل `{ "success": true, "data": … }`.

ثم افتح ذلك الشخص في **جهات الاتصال**: الحدث في سجله مع وقت حدوثه. ويسرد `warnings` ما لم تستطع حملة تطبيقه، مثل سمة من نوع خاطئ، ولا يظهر إلا حين يكون هناك ما يقال. اقرأه في أول طلب. وإن قال **campaigns will not reach this contact** فالشخص لم يُعرَّف قط: عُد إلى الخطوة الثالثة.

**6. حوّل الحدث إلى رسالة**

سلّمه لصاحب النشاط، أو افعلها بنفسك:

* **اطلب من حملة:** «حين يُطلق أحد `subscription_started`، أرسل له بريد ترحيب بأفضل ثلاث نصائح لدينا.»
* **أو ابنِها:** افتح حملة ← **متى تبدأ الحملة؟** ← **حدث في تطبيق** ← **أحداث تطبيقك** ← اكتب اسم الحدث.

من الآن فصاعداً، كل من يُطلق ذلك الحدث ويمكن الوصول إليه تصله الرسالة، في لحظة حدوثه.

## أحضر تاريخك

أرسل التسجيلات والمدفوعات السابقة عبر `POST /api/sdk/track/batch`، حتى 500 في الطلب الواحد، كلٌّ بوقته الحقيقي `occurredAt` ومفتاح `idempotencyKey`. التاريخ يملأ الملفات والإيرادات والشرائح، ولا يرسل رسالة **أبداً**. التفاصيل في [مرجع الأحداث](https://docs.hamla.io/ar/reference/events.md).

## قبل الإطلاق

* [ ] المفتاح السري على خادمك فقط.
* [ ] `identify` يعمل عند التسجيل وتسجيل الدخول، قبل أول `track` أو معه.
* [ ] كل حدث فيه مال له `type` و`idempotencyKey`.
* [ ] الدوال الخالية من الخوادم تستدعي `await hamla.flush()` قبل أن تعيد.
* [ ] بدّلت مفتاح نشاط الاختبار بالمفتاح الحقيقي.

## حين لا يسير شيء كما يجب

| ما تراه | السبب المعتاد |
| - | - |
| `401` | لا توجد ترويسة `Authorization`، أو أُلغي المفتاح. ورسالة الخطأ تقول أيّهما. |
| `403` | مفتاح منشور (`pk_live_…`) على مسار خادم، أو `businessId` لا يطابق المفتاح. |
| `429` | أكثر من 120 طلباً في الدقيقة لنشاط واحد. انتظر النافذة المذكورة في ترويسات الرد، أو أرسل دفعات. |
| الحدث في السجل، لكن لم تبدأ أي حملة | لم يُعرَّف الشخص قط، فلا إذن بمراسلته (ويقول رد `track` ذلك في `warnings`)؛ أو يختلف اسم الحدث بحرف؛ أو جاء الحدث عبر مسار الدفعات؛ أو أنه مسجَّل من قبل و**يمكن الدخول مرة أخرى لاحقاً** مغلق. |
| الإيراد 0 | لم يحمل الحدث `type: "purchase"` واسمه غير معروف لحملة. افحص `interpreted` في الرد. |

كل حقل وحد وخطأ في [مرجع الأحداث](https://docs.hamla.io/ar/reference/events.md). والشرح الأطول للأحداث، مع مثالين لعيادة ولمنتج SaaS، في [أحداث حملة](https://docs.hamla.io/ar/how-to/hamla-events.md).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.