> ## Content Index
> Fetch the complete content index at: https://arabroot.io/llms.txt
> Use this file to discover other available public pages before exploring further.

# منظومة تسويق كاملة على سيرفرك: من الرابط إلى العميل
- URL: https://arabroot.io/articles/منظومة-تسويق-كاملة-على-سيرفرك-من-الرابط-الى-العميل/
- Published: 2026-10-25T05:22:00.000Z
- Updated: 2026-10-25T14:23:30.000Z
- Description: نجمع Umami وShlink وMautic في ملف Compose واحد، ونتتبع عميلاً من رابط مختصر في منشور حتى يظهر تحويله ومصدره في التقارير.
- Author: فريق عرب رووت
- Tags: الأدلة التقنية, التسويق والمبيعات, الاستضافة الذاتية, Mautic

كل أداة في مقالات هذا المسار جربناها وحدها: الرابط المختصر يعد النقرات، وأداة التحليلات تعد الزيارات، وأداة الأتمتة ترسل الرسائل. ولكن السؤال الذي يسأله مدير الشركة لا تجيب عنه أداة واحدة: «العميل الذي فعل حسابه اليوم، من أين جاء؟». ولكي تجيب عنه يجب أن تمر معلومة المصدر من أداة إلى أخرى دون أن تضيع. وفي هذا الدليل سوف نجمع الأدوات في ملف Compose واحد على سيرفرنا، ثم نمر بمسار عميل كامل: رابط مختصر في منشور، ثم صفحة هبوط، ثم نموذج، ثم جهة اتصال في Mautic، ثم رسالة تفعيل، ثم تحويل Conversion يظهر في التقارير مع مصدره.

ولن نعيد شرح ما سبق، فمعنى معاملات UTM والتحويل ونماذج الإسناد Attribution في المقال الأول من القائمة التالية، وكل أداة لها مقالها:

[![](https://arabroot.io/content/images/2026/10/marketing-analytics-cover-cover.webp)دليلقياس التسويق: روابط UTM والإسناد Attributionكيف تعرف القناة التي جاءت بكل عميل: روابط UTM بقواعد تسمية ثابتة، وتحويل تعرفه أنت، ونموذج إسناد تفهم ما يحسبه.](https://arabroot.io/articles/%D9%82%D9%8A%D8%A7%D8%B3-%D8%A7%D9%84%D8%AA%D8%B3%D9%88%D9%8A%D9%82-%D8%B1%D9%88%D8%A7%D8%A8%D8%B7-utm-%D9%88%D8%A7%D9%84%D8%A7%D8%B3%D9%86%D8%A7%D8%AF-attribution/)[![](https://arabroot.io/content/images/2026/10/short-links-cover-cover.webp)دليلالروابط المختصرة وتتبع النقرات: Bitly وبدائلهBitly وDub أمام Shlink وYOURLS على نطاقك، مع تجربة Shlink في Docker تبين لماذا لا يساوي عدد النقرات عدد الزوار.](https://arabroot.io/articles/%D8%A7%D9%84%D8%B1%D9%88%D8%A7%D8%A8%D8%B7-%D8%A7%D9%84%D9%85%D8%AE%D8%AA%D8%B5%D8%B1%D8%A9-%D9%88%D8%AA%D8%AA%D8%A8%D8%B9-%D8%A7%D9%84%D9%86%D9%82%D8%B1%D8%A7%D8%AA-bitly-%D9%88%D8%A8%D8%AF%D8%A7%D8%A6%D9%84%D9%87/)[![](https://arabroot.io/content/images/2026/10/web-analytics-tools-cover-cover.webp)دليلتحليلات الموقع دون Google Analytics: مقارنة عمليةشغلنا Umami وPlausible وMatomo على نفس الموقع وقارناها بـ Google Analytics في حجم السكربت والـ Cookies والعربية وملكية البيانات.](https://arabroot.io/articles/%D8%AA%D8%AD%D9%84%D9%8A%D9%84%D8%A7%D8%AA-%D8%A7%D9%84%D9%85%D9%88%D9%82%D8%B9-%D8%AF%D9%88%D9%86-google-analytics-%D9%85%D9%82%D8%A7%D8%B1%D9%86%D8%A9-%D8%B9%D9%85%D9%84%D9%8A%D8%A9/)[![](https://arabroot.io/content/images/2026/10/mautic-lab-cover-cover.webp)دليلMautic على سيرفرك: حملة مؤتمتة من النموذج إلى البريدنشغل Mautic في Docker ونبني نموذجاً عربياً ونقاطاً للتقييم وحملة ترسل الترحيب وتنبه المبيعات، ونختبرها بزائرين تجريبيين.](https://arabroot.io/articles/mautic-%D8%B9%D9%84%D9%89-%D8%B3%D9%8A%D8%B1%D9%81%D8%B1%D9%83-%D8%AD%D9%85%D9%84%D8%A9-%D9%85%D8%A4%D8%AA%D9%85%D8%AA%D8%A9-%D9%85%D9%86-%D8%A7%D9%84%D9%86%D9%85%D9%88%D8%B0%D8%AC-%D8%A7%D9%84%D9%89-%D8%A7%D9%84%D8%A8%D8%B1%D9%8A%D8%AF/)

وفي هذا الدليل سوف نقوم بما يلي:

- نشغل Umami وShlink وMautic وMailpit وصفحة هبوط في ملف Compose واحد بإصدارات مثبتة.
- ننشئ رابطين مختصرين لحملة واحدة، أحدهما لمنشور في X والآخر لمنشور في LinkedIn.
- نمر بزائرين: الأول يطلب نسخة تجريبية ويفعل حسابه من الرسالة، والثاني يفتح الصفحة ويغادر.
- نتتبع المعلومة في كل أداة بالأرقام، ونرى أين ضاعت معاملات UTM وأين وصلت.
- نقارن الإسناد للنقرة الأولى First Click والأخيرة Last Click، ونرى لماذا يعطيان جوابين مختلفين للعميل نفسه.

والصورة التالية تبين المسار وأين تسجل كل خطوة:

![سبع خطوات: منشور في X فيه الرابط المختصر localhost:18796/launch، ثم Shlink يحسب النقرة ويحول برمز 302، ثم صفحة الهبوط فيها سكربت Umami وسكربت Mautic وترسل الزيارة وحدث trial-request إلى Umami، ثم إرسال النموذج إلى Mautic الذي ينشئ جهة اتصال ونقاطاً ويرسل رسالة فورية، ثم الرسالة في Mailpit بمعاملات utm_source=mautic، ثم صفحة التفعيل activate.html، ثم حدث activate يعود إلى Umami ويجيب تقرير الإسناد عن مصدر العميل](https://arabroot.io/content/images/2026/10/marketing-stack-lab-01-journey.webp)

كل أداة تسجل جزءاً من المسار، والرابط بينها معاملات UTM

## المتطلبات

- سيرفر Linux عليه Docker وDocker Compose، وقد اختبرنا على Docker Engine 29.8.0.
- ذاكرة: بعد التجربة كانت الخدمات العشر تستهلك حوالي 2.1 جيجابايت، أكبرها قاعدة بيانات Mautic بـ 544 ميجابايت، ثم Shlink بـ 500، ثم الـ Worker الخاص بـ Mautic بـ 372، ثم Umami بـ 303، لذلك خطط لسيرفر بذاكرة 4 جيجابايت على الأقل.
- مساحة القرص: حوالي 3.2 جيجابايت لـ Image الخاصة بـ Mautic، و1.36 لـ Umami، و1.1 لـ MySQL، و650 ميجابايت لـ PostgreSQL، و465 لـ Shlink.
- في الإنتاج: نطاق فرعي لكل أداة بشهادة TLS، مثل `stats.example.com` و`go.example.com` و`m.example.com`، خلف Reverse Proxy مثل [Caddy](https://arabroot.io/articles/%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-caddy-reverse-proxy/).

## ملف Compose واحد للمنظومة

الملف التالي يجمع أربع مجموعات، ولكل منها قاعدة بياناتها، ولا يوجد بينها اعتماد في التشغيل، فإذا توقفت Umami مثلاً بقيت النماذج والرسائل تعمل:

```yaml
name: mke-stack

x-mautic: &mautic
  image: mautic/mautic:7.2.1-apache
  restart: unless-stopped
  env_file: .mautic_env
  volumes:
    - mautic-config:/var/www/html/config
    - mautic-logs:/var/www/html/var/logs
    - mautic-media:/var/www/html/docroot/media

services:
  # 1) web analytics
  umami-db:
    image: postgres:18.6
    restart: unless-stopped
    environment:
      POSTGRES_DB: umami
      POSTGRES_USER: umami
      POSTGRES_PASSWORD: ${UMAMI_DB_PASSWORD}
    volumes:
      - umami-db:/var/lib/postgresql
    healthcheck:
      test: pg_isready -U umami -d umami
      interval: 5s
      retries: 30
      start_period: 120s

  umami:
    image: ghcr.io/umami-software/umami:3.4.1
    restart: unless-stopped
    environment:
      DATABASE_URL: postgresql://umami:${UMAMI_DB_PASSWORD}@umami-db:5432/umami
      APP_SECRET: ${UMAMI_APP_SECRET}
    ports:
      - "127.0.0.1:18795:3000"
    depends_on:
      umami-db:
        condition: service_healthy

  # 2) short links
  shlink:
    image: shlinkio/shlink:5.1.8
    restart: unless-stopped
    environment:
      DEFAULT_DOMAIN: localhost:18796
      IS_HTTPS_ENABLED: "false"
      INITIAL_API_KEY: ${SHLINK_API_KEY}
      TIMEZONE: Asia/Riyadh
    volumes:
      - shlink-data:/etc/shlink/data
    ports:
      - "127.0.0.1:18796:8080"

  shlink-web:
    image: shlinkio/shlink-web-client:4.8.1
    ports:
      - "127.0.0.1:18797:8080"

  # 3) marketing automation
  mautic-db:
    image: mysql:8.4.11
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: mautic
      MYSQL_USER: mautic
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
    volumes:
      - mysql-data:/var/lib/mysql
    healthcheck:
      test: mysqladmin --user=mautic --password=$$MYSQL_PASSWORD ping
      interval: 5s
      timeout: 5s
      retries: 60
      start_period: 300s

  mautic_web:
    <<: *mautic
    ports:
      - "127.0.0.1:18799:80"
    healthcheck:
      test: curl -fs http://localhost/ -o /dev/null || exit 1
      interval: 10s
      timeout: 5s
      retries: 60
      start_period: 300s
    depends_on:
      mautic-db:
        condition: service_healthy

  mautic_cron:
    <<: *mautic
    environment:
      DOCKER_MAUTIC_ROLE: mautic_cron
    depends_on:
      mautic_web:
        condition: service_healthy

  mautic_worker:
    <<: *mautic
    environment:
      DOCKER_MAUTIC_ROLE: mautic_worker
    depends_on:
      mautic_web:
        condition: service_healthy

  # 4) mail sink and the landing page
  mailpit:
    image: axllent/mailpit:v1.31.5
    ports:
      - "127.0.0.1:18800:8025"

  site:
    image: nginx:1.31.6-alpine
    volumes:
      - ./site:/usr/share/nginx/html:ro
    ports:
      - "127.0.0.1:18798:80"

volumes:
  umami-db:
  shlink-data:
  mysql-data:
  mautic-config:
  mautic-logs:
  mautic-media:
```

والملف `.mautic_env` هو نفسه في [دليل Mautic](#series) مع تغيير اسم قاعدة البيانات إلى `mautic-db`. وننشئ الأسرار الخمسة ثم نشغل:

```bash
printf 'UMAMI_DB_PASSWORD=%s\nUMAMI_APP_SECRET=%s\nSHLINK_API_KEY=%s\nMYSQL_PASSWORD=%s\nMYSQL_ROOT_PASSWORD=%s\n' \
  "$(openssl rand -hex 16)" "$(openssl rand -hex 32)" "$(openssl rand -hex 16)" "$(openssl rand -hex 16)" "$(openssl rand -hex 16)" > .env
chmod 600 .env
docker compose up -d
```

في الإعداد أعلاه لاحظ التالي:

- Shlink يستخدم SQLite داخل الـ Volume المسمى `shlink-data` لأننا لم نعطه قاعدة بيانات، وهذا يكفي لتجربة أو لعدد قليل من الروابط، أما في الإنتاج فالأفضل PostgreSQL كما في [توثيق Shlink](https://shlink.io/documentation/install-docker-image/?ref=arabroot.io).
- القيمة `INITIAL_API_KEY` تنشئ أول مفتاح API عند أول تشغيل فقط، فاحفظها في مدير كلمات المرور.
- الخدمة `shlink-web` واجهة رسومية تعمل في المتصفح بالكامل، أي أن مفتاح الـ API يحفظ في متصفحك وليس على السيرفر، ويمكنك الاستغناء عنها والعمل بالـ API.

## تجهيز كل أداة

شرحنا تثبيت كل أداة في مقالها، وهنا ما أضفناه لهذا المسار فقط:

- Umami: غيرنا كلمة مرور المستخدم الافتراضي `admin` فوراً، ثم أنشأنا موقعاً باسم «منصة الفواتير» فأعطانا معرف الموقع Website ID.
- Mautic: ثبتناه بالأمر `mautic:install`، وضبطنا البريد إلى Mailpit، والمنطقة الزمنية، و`cors_valid_domains` لصفحة الهبوط، ثم أعدنا تشغيل الـ Worker والـ Cron، والسبب في [دليل Mautic](#series).
- Mautic: أنشأنا رسالة «تفعيل الحساب التجريبي» بمعاملات UTM ثابتة `utm_source=mautic` و`utm_medium=email` و`utm_campaign=launch-oct`، ونموذجاً بثلاثة حقول وثلاثة إجراءات: 20 نقطة، وحفظ معاملات UTM Record UTM Tags، وإرسال الرسالة فوراً Send email to contact.

واخترنا إرسال الرسالة من إجراء في النموذج وليس من حملة، لأن الحملة تنتظر الـ Cron كل 15 دقيقة، بينما رسالة التفعيل يجب أن تصل والعميل ما زال أمام الشاشة.

ثم أنشأنا الرابطين المختصرين من [الـ API الخاصة بـ Shlink](https://shlink.io/documentation/api-docs/?ref=arabroot.io)، ولاحظ أن معاملات UTM جزء من الرابط الطويل، أي أن من يكتب المنشور يأخذ رابطاً قصيراً لا يستطيع أن يخطئ فيه:

```json
{"longUrl":"http://localhost:18798/?utm_source=x&utm_medium=social&utm_campaign=launch-oct&utm_content=post-1","customSlug":"launch","title":"إطلاق منصة الفواتير: منشور X","tags":["launch-oct"],"findIfExists":true}
```

```bash
curl -s -X POST http://localhost:18796/rest/v3/short-urls -H "X-Api-Key: $SHLINK_API_KEY" \
  -H 'Content-Type: application/json' --data-binary @short.json
```

والرابط الثاني مثله بالاسم `launch-in` والقيمة `utm_source=linkedin`، وكلاهما يحول برمز 302:

```text
302 -> http://localhost:18798/?utm_source=x&utm_medium=social&utm_campaign=launch-oct&utm_content=post-1
```

![واجهة Shlink فيها رابطان مختصران أنشئا في 2026-10-25: localhost:18796/launch-in بعنوان إطلاق منصة الفواتير منشور LinkedIn، وlocalhost:18796/launch بعنوان إطلاق منصة الفواتير منشور X، وكلاهما بالوسم launch-oct وعلى كل منهما زيارة واحدة](https://arabroot.io/content/images/2026/10/marketing-stack-lab-02-short-links.webp)

الرابطان المختصران في Shlink، لكل منهما زيارة واحدة بعد التجربة

## صفحة الهبوط: سكربتان وحدثان

في صفحة الهبوط نضع سكربت Umami لعد الزيارات، وسكربت Mautic لربط الزيارة بجهة الاتصال، ثم النموذج، ثم سطر يرسل حدثاً إلى Umami عند إرسال النموذج بالدالة `umami.track` الموثقة في [دوال التتبع](https://umami.is/docs/tracker-functions?ref=arabroot.io):

```html
<script defer src="http://localhost:18795/script.js" data-website-id="999dfc10-3ae8-45a5-b50e-e8feb3266f09"></script>
<script>
  (function(w,d,t,u,n,a,m){w["MauticTrackingObject"]=n;
    w[n]=w[n]||function(){(w[n].q=w[n].q||[]).push(arguments)},a=d.createElement(t),
    m=d.getElementsByTagName(t)[0];a.async=1;a.src=u;m.parentNode.insertBefore(a,m)
  })(window,document,"script","http://localhost:18799/mtc.js","mt");
  mt("send", "pageview");
</script>

<script src="http://localhost:18799/form/generate.js?id=1"></script>

<script>
  // conversion event in Umami when the trial form is sent
  document.addEventListener('submit', function (e) {
    if (e.target.matches('form[data-mautic-form]') && window.umami) umami.track('trial-request');
  }, true);
</script>
```

وفي صفحة التفعيل `activate.html` نفس السكربتين، ومعهما حدث `activate` بعد التحميل، وهو التحويل الذي نريد أن نعرف مصدره:

```html
<script>
  window.addEventListener('load', function () { setTimeout(function () { if (window.umami) umami.track('activate'); }, 500); });
</script>
```

والسبب في التأخير القصير أن سكربت Umami محمل بالخاصية `defer`، فقد لا تكون الدالة `umami` جاهزة في نفس لحظة التحميل.

## المسار بزائرين

الزائر الأول فتح الرابط `launch-in` من هاتف iPhone، فرأى الصفحة وغادر. والزائرة الثانية سارة فتحت الرابط `launch` من متصفح Chrome على جهاز مكتبي، وكتبت بياناتها في النموذج:

![صفحة الهبوط العربية جرب منصة الفواتير 14 يوماً، وفي النموذج الاسم سارة والبريد sara@example.com والشركة متجر سارة للعطور، وزر أرسل الطلب](https://arabroot.io/content/images/2026/10/marketing-stack-lab-03-landing.webp)

صفحة الهبوط وصلت إليها سارة من الرابط المختصر

ووصلت رسالة التفعيل إلى Mailpit في أقل من ثانيتين من إرسال النموذج، لأنها خرجت من إجراء النموذج مباشرة إلى طابور الـ Worker دون انتظار الـ Cron:

![Mailpit يعرض رسالة من فريق منصة الفواتير إلى سارة بعنوان سارة، حسابك التجريبي جاهز للتفعيل، والمحتوى من اليمين إلى اليسار مع زر تفعيل الحساب ورابط إلغاء الاشتراك](https://arabroot.io/content/images/2026/10/marketing-stack-lab-04-mail.webp)

رسالة التفعيل خرجت من إجراء النموذج فوراً

ثم ضغطت سارة زر التفعيل، فمر الرابط على Mautic ليسجل النقرة، ووصلت إلى:

```text
http://localhost:18798/activate.html?utm_source=mautic&utm_medium=email&utm_campaign=launch-oct&utm_content=activate
```

![صفحة عربية عنوانها تم تفعيل حسابك وتحتها يمكنك الآن رفع أول فاتورة](https://arabroot.io/content/images/2026/10/marketing-stack-lab-05-activate.webp)

صفحة التفعيل: هنا يقع التحويل

## ماذا سجلت كل أداة؟

الآن نسأل كل أداة عما رأته. Shlink سجل نقرة واحدة على كل رابط، ومعها الوقت والمتصفح والصفحة المحالة منها Referer إذا وجدت، ويمكن قراءتها من الـ API:

```bash
curl -s "http://localhost:18796/rest/v3/short-urls/launch/visits" -H "X-Api-Key: $SHLINK_API_KEY"
```

وMautic أنشأ جهة اتصال لسارة بـ 20 نقطة، وسجل معاملات UTM مرتين، مرة لزيارة صفحة الهبوط ومرة لصفحة التفعيل:

```text
+---------+------------+------------+--------------+-------------+---------------------+
| lead_id | utm_source | utm_medium | utm_campaign | utm_content | date_added          |
+---------+------------+------------+--------------+-------------+---------------------+
|       8 | linkedin   | social     | launch-oct   | post-1      | 2026-10-25 10:55:18 |
|       9 | x          | social     | launch-oct   | post-1      | 2026-10-25 10:55:26 |
|       9 | mautic     | email      | launch-oct   | activate    | 2026-10-25 10:55:38 |
|       9 | mautic     | email      | launch-oct   | activate    | 2026-10-25 10:55:39 |
+---------+------------+------------+--------------+-------------+---------------------+
```

في المخرج أعلاه لاحظ التالي:

- جهة الاتصال رقم 8 هي زائر LinkedIn، وهو زائر مجهول Anonymous Visitor لم يكتب بريده، ولكن Mautic يحتفظ بمصدره، فإذا عاد بعد أسبوع وأرسل النموذج من نفس المتصفح ارتبط هذا السطر بجهة الاتصال.
- سطر سارة الأول جاء من سكربت التتبع `mtc.js` عند فتح الصفحة، وليس من إجراء النموذج Record UTM Tags، والسبب في قسم [أين ضاعت المعلومة](#utm-lost).
- سطرا التفعيل أحدهما من نقرة الرابط في الرسالة والآخر من زيارة الصفحة.

وسجل سارة في Mautic يرتب كل ذلك زمنياً، من الزيارة الأولى بمعاملات `launch-oct` حتى صفحة التفعيل:

![سجل جهة الاتصال سارة في Mautic بأربعة عشر حدثاً: Contact created وAccessed from IP وUTM tags recorded وPage hit لصفحة الهبوط وForm submitted وContact identified وPoint gained بعشرين نقطة وEmail sent وEmail read ثم Page hit لصفحة التفعيل مع UTM tags recorded](https://arabroot.io/content/images/2026/10/marketing-stack-lab-06-contact-timeline.webp)

سجل سارة في Mautic: 14 حدثاً في دقيقة واحدة

وفي Umami ظهر زائران وثلاث مشاهدات Views، ونسبة ارتداد Bounce Rate بخمسين في المائة، وهي زيارة LinkedIn التي لم تتجاوز الصفحة الأولى:

![لوحة Umami لموقع منصة الفواتير: Visitors 2 وVisits 2 وViews 3 وBounce rate 50% وVisit duration 6s](https://arabroot.io/content/images/2026/10/marketing-stack-lab-07-umami-overview.webp)

Umami: زائران وثلاث مشاهدات

والقمع Funnel من ثلاث خطوات، طلبناه من الـ API: فتح الصفحة، ثم حدث `trial-request`، ثم حدث `activate`:

```text
[{"type":"path","value":"/","visitors":2,"dropped":0},
 {"type":"event","value":"trial-request","visitors":1,"previous":2,"dropped":1,"dropoff":0.5},
 {"type":"event","value":"activate","visitors":1,"previous":1,"dropped":0,"dropoff":0}]
```

أي أن نسبة التحويل في هذه التجربة 50 في المائة، وهو رقم لا معنى له مع زائرين، ولكن نفس الاستعلام يعمل مع ألف زائر.

## من يأخذ الفضل في التحويل؟

في تقرير الإسناد Attribution في Umami، الموثق في [صفحة الإسناد](https://umami.is/docs/attribution?ref=arabroot.io)، اخترنا نوع الخطوة Triggered event والحدث `activate`. ومع نموذج النقرة الأولى First Click كان الجواب X:

![تقرير Attribution في Umami بنموذج First click ونوع Triggered event والخطوة activate: زائر واحد، والمصادر x والوسيط social والحملة launch-oct والمحتوى post-1 بنسبة 100%](https://arabroot.io/content/images/2026/10/marketing-stack-lab-08-attribution-first.webp)

النقرة الأولى: التحويل لمنشور X

ومع نموذج النقرة الأخيرة Last Click تغير الجواب إلى البريد:

![نفس التقرير بنموذج Last click: المصدر mautic والوسيط email والحملة launch-oct والمحتوى activate بنسبة 100%](https://arabroot.io/content/images/2026/10/marketing-stack-lab-09-attribution-last.webp)

النقرة الأخيرة: التحويل لرسالة Mautic

وكلا الجوابين صحيح، فالمنشور جاء بسارة، والرسالة هي التي جعلتها تفعل الحساب. والذي يجمعهما أن الحملة `launch-oct` واحدة في الخطوتين، لأننا كتبناها بنفس القيمة في الرابط المختصر وفي إعدادات الرسالة، فإذا سألت «كم تحويلاً جلبت حملة الإطلاق؟» فالجواب واحد في النموذجين. لذلك اتفق مع فريقك على أسماء الحملات قبل الإطلاق، واجعل `utm_campaign` في رسائل Mautic هو نفس اسم الحملة التي جاء منها العميل، وإلا ظهر البريد في التقارير كأنه مصدر مستقل يأخذ الفضل من القنوات التي جلبت الناس فعلاً. والفرق بين النماذج بالتفصيل في [مقال قياس التسويق](#series).

## أين ضاعت المعلومة؟

هذه أربعة أشياء ظهرت لنا أثناء التجربة، وكل منها قد يجعل أرقامك خاطئة دون أي رسالة خطأ.

### المتصفحات الآلية لا تحسب

شغلنا التجربة أول مرة بمتصفح Chrome الآلي Headless، فوصل الزائران ووصلت الرسالة وفعلت سارة حسابها، ولكن Umami أظهر صفراً في كل شيء. والسبب أن Umami يفحص نوع المتصفح User-Agent بمكتبة `isbot`، فإذا كان آلياً رد بهذا الجواب ولم يسجل شيئاً، كما في [كود الاستقبال](https://github.com/umami-software/umami/blob/v3.4.1/src/app/api/send/route.ts?ref=arabroot.io):

```text
{"beep":"boop"}
```

وفي نفس الوقت سجل Shlink الزيارتين ولكنه علمهما `"potentialBot": true` بحسب ميزة [كشف البوتات](https://shlink.io/documentation/some-features/?ref=arabroot.io). وهذا سلوك صحيح للزوار الحقيقيين، فهو يبعد البوتات عن تقاريرك، ولكن انتبه له إذا كنت تختبر المنظومة باختبارات آلية End-to-End: إما أن تعطي المتصفح User-Agent عادياً كما فعلنا في التشغيل الثاني، أو تفعل `DISABLE_BOT_CHECK` في [إعدادات Umami](https://umami.is/docs/environment-variables?ref=arabroot.io) على بيئة الاختبار فقط.

### زائران من نفس الجهاز يظهران زائراً واحداً

في التشغيل الثاني أعطينا المتصفحين نفس User-Agent، فظهر في Umami زائر واحد وزيارة واحدة. والسبب أن Umami لا يستخدم Cookies، ويحسب معرف الجلسة Session من الموقع وعنوان IP ونوع المتصفح وقيمة سرية تتغير كل شهر افتراضياً، فزائران خلف نفس العنوان وبنفس المتصفح ونفس الإصدار يصبحان زائراً واحداً. وعندما جعلنا الزائر الأول iPhone ظهر زائران. وفي الواقع هذا يحدث في شركة كل موظفيها خلف عنوان واحد وبنفس المتصفح، فاعتبر عدد الزوار في أي أداة دون Cookies تقديراً وليس عداً دقيقاً.

### إجراء Record UTM Tags في النموذج لم يسجل شيئاً

هذا الإجراء يقرأ معاملات UTM من عنوان الصفحة التي أرسلت النموذج، أي من ترويسة Referer. ولكن صفحة الهبوط على عنوان وMautic على عنوان آخر، والمتصفحات افتراضياً تطبق سياسة `strict-origin-when-cross-origin` الموضحة في [توثيق Referrer-Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Referrer-Policy?ref=arabroot.io)، فترسل للموقع الآخر أصل الصفحة فقط دون المسار والمعاملات، وقد وجدنا في جدول Mautic أن الـ Referer المحفوظ هو `http://localhost:18798/` فقط. لذلك لم يسجل الإجراء سطراً، وجاءت المعاملات من سكربت التتبع `mtc.js` الذي يرسل عنوان الصفحة كاملاً. والدرس أن تبقي سكربت التتبع في كل صفحة فيها نموذج، أو أن تضيف حقولاً مخفية Hidden Fields في النموذج تملؤها من عنوان الصفحة.

### رسائل البريد تغير المصدر

كما رأينا في تقرير الإسناد، أي رابط في رسالة Mautic يحمل `utm_source=mautic`، فإذا لم تنتبه لاسم الحملة فيه صار البريد مصدراً جديداً في كل تقرير بالنقرة الأخيرة، وهو ما يحدث أيضاً مع أداة النشرات مثل [listmonk](https://arabroot.io/articles/%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-listmonk-%D9%84%D9%84%D9%86%D8%B4%D8%B1%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%B1%D9%8A%D8%AF%D9%8A%D8%A9/) إذا أضافت معاملاتها.

## الموافقة وبيانات الزوار

هذه المنظومة تجمع بيانات شخصية: البريد والاسم في Mautic، وسجل الزيارات المرتبط بها. وعلى سيرفرك تبقى هذه البيانات عندك ولا تذهب لطرف آخر، ولكن هذا لا يغني عن الموافقة، فالمادة الخامسة والعشرون من [نظام حماية البيانات الشخصية](https://laws.boe.gov.sa/BoeLaws/Laws/LawDetails/b7cfae89-828e-4994-b167-adaa00e37188/1?ref=arabroot.io) تشترط موافقة المتلقي على المواد الدعائية وآلية واضحة لإيقافها. لذلك ضع في النموذج موافقة صريحة على الرسائل التسويقية منفصلة عن طلب التجربة، واذكر في سياسة الخصوصية أن الموقع يستخدم Mautic لتتبع الزيارات بعد التعرف على الزائر. أما Umami فلا يستخدم Cookies كما في [أسئلته الشائعة](https://umami.is/docs/faq?ref=arabroot.io)، ولا يربط الزيارة باسم أو بريد.

## التحقق من النجاح

- الرابط المختصر يرجع 302 إلى صفحة الهبوط ومعاملات UTM كاملة: `curl -s -o /dev/null -w '%{http_code} %{redirect_url}' http://localhost:18796/launch`.
- صفحة UTM في Umami تظهر قيم `utm_source` التي استخدمتها، والأحداث `trial-request` و`activate` تظهر في صفحة Events.
- في Mautic تظهر جهة الاتصال الجديدة ومعها سطر UTM بمصدر الحملة، وليس فقط بمصدر البريد.
- رسالة التفعيل تصل خلال ثوان من إرسال النموذج.
- تقرير الإسناد للحدث `activate` يعطي مصدراً في النقرة الأولى وآخر في الأخيرة، كما في [القسم السابق](#attribution).

## النسخ الاحتياطي Backup

في المنظومة ثلاث قواعد بيانات، ولكل منها أمرها:

```bash
docker exec mke-stack-umami-db-1 pg_dump -U umami umami | gzip > umami-$(date +%F).sql.gz
docker exec mke-stack-mautic-db-1 sh -c 'mysqldump --single-transaction --no-tablespaces -umautic -p"$MYSQL_PASSWORD" mautic' | gzip > mautic-$(date +%F).sql.gz
docker run --rm -v mke-stack_shlink-data:/d -v "$PWD":/backup nginx:1.31.6-alpine tar czf /backup/shlink-$(date +%F).tar.gz -C /d .
```

ومعها الـ Volumes الخاصة بإعدادات Mautic وملفاته كما في [دليل Mautic](#series)، والملف `.env` ففيه كل الأسرار. ونسخ Shlink هنا نسخ لملف SQLite وهو يعمل، لذلك خذه في وقت هادئ أو أوقف Shlink لثوان، أو انقله إلى PostgreSQL في الإنتاج.

## مشكلات شائعة وحلولها

### Umami يظهر صفراً والصفحة فيها السكربت

افتح أدوات المطور في المتصفح وابحث عن الطلب `/api/send`، فإذا كان الرد `{"beep":"boop"}` فالمتصفح مصنف بوتاً، وإذا فشل الطلب فراجع أن عنوان Umami يعمل على HTTPS عندما يكون موقعك على HTTPS، وأن أداة حجب الإعلانات لا تحجبه.

### زيارات Shlink كلها potentialBot

إذا كانت من اختبار آلي أو من أداة مثل `curl` فهذا متوقع، أما إذا كانت من زوار حقيقيين فراجع أن الـ Reverse Proxy يمرر ترويسة User-Agent كما هي.

### جهة الاتصال في Mautic بلا معاملات UTM

تأكد أن سكربت `mtc.js` موجود في صفحة الهبوط نفسها، وأن الرابط المختصر يحول إلى نفس الصفحة التي فيها النموذج، ولا تعتمد على إجراء Record UTM Tags وحده لما ذكرناه في [قسم الـ Referer](#referrer).

### الحملة تظهر باسمين في التقارير

السبب اختلاف القيمة بين الرابط المختصر والرسالة، مثل `launch-oct` و`Launch_Oct`، فاكتب أسماء الحملات بحروف صغيرة وشرطة، واحفظها في جدول مشترك قبل الإطلاق.

## إزالة التجربة

```bash
docker compose down -v
docker rmi mautic/mautic:7.2.1-apache ghcr.io/umami-software/umami:3.4.1 shlinkio/shlink:5.1.8 \
  shlinkio/shlink-web-client:4.8.1 mysql:8.4.11 postgres:18.6 axllent/mailpit:v1.31.5 nginx:1.31.6-alpine
```

## الخلاصة

وصلنا لنهاية الموضوع، وأهم ما فيه:

- أربع أدوات مفتوحة المصدر في ملف Compose واحد، بحوالي 2.1 جيجابايت من الذاكرة، تجيب معاً عن سؤال لا تجيب عنه أي منها وحدها: من أين جاء العميل الذي فعل حسابه؟
- الرابط بين الأدوات هو معاملات UTM، فاكتبها مرة واحدة في الرابط المختصر، واجعل اسم الحملة نفسه في رسائل البريد.
- في تجربتنا أعطى نموذج النقرة الأولى الفضل لمنشور X، والنقرة الأخيرة لرسالة Mautic، وكلاهما صحيح لسؤال مختلف.
- أربع مشكلات تعطيك أرقاماً خاطئة دون خطأ ظاهر: المتصفحات الآلية لا تحسب، والزوار خلف نفس العنوان والمتصفح يظهرون زائراً واحداً، وإجراء UTM في النموذج يفقد المعاملات بسبب سياسة الـ Referer، وروابط البريد تغير المصدر.
- أرسل الرسائل العاجلة من إجراء النموذج، فقد وصلت رسالة التفعيل في أقل من ثانيتين.

والمقالات التي بنينا عليها هذا الدليل:

[![](https://arabroot.io/content/images/2026/10/marketing-analytics-cover-cover.webp)دليلقياس التسويق: روابط UTM والإسناد Attributionكيف تعرف القناة التي جاءت بكل عميل: روابط UTM بقواعد تسمية ثابتة، وتحويل تعرفه أنت، ونموذج إسناد تفهم ما يحسبه.](https://arabroot.io/articles/%D9%82%D9%8A%D8%A7%D8%B3-%D8%A7%D9%84%D8%AA%D8%B3%D9%88%D9%8A%D9%82-%D8%B1%D9%88%D8%A7%D8%A8%D8%B7-utm-%D9%88%D8%A7%D9%84%D8%A7%D8%B3%D9%86%D8%A7%D8%AF-attribution/)[![](https://arabroot.io/content/images/2026/10/mautic-lab-cover-cover.webp)دليلMautic على سيرفرك: حملة مؤتمتة من النموذج إلى البريدنشغل Mautic في Docker ونبني نموذجاً عربياً ونقاطاً للتقييم وحملة ترسل الترحيب وتنبه المبيعات، ونختبرها بزائرين تجريبيين.](https://arabroot.io/articles/mautic-%D8%B9%D9%84%D9%89-%D8%B3%D9%8A%D8%B1%D9%81%D8%B1%D9%83-%D8%AD%D9%85%D9%84%D8%A9-%D9%85%D8%A4%D8%AA%D9%85%D8%AA%D8%A9-%D9%85%D9%86-%D8%A7%D9%84%D9%86%D9%85%D9%88%D8%B0%D8%AC-%D8%A7%D9%84%D9%89-%D8%A7%D9%84%D8%A8%D8%B1%D9%8A%D8%AF/)[![](https://arabroot.io/content/images/2026/10/short-links-cover-cover.webp)دليلالروابط المختصرة وتتبع النقرات: Bitly وبدائلهBitly وDub أمام Shlink وYOURLS على نطاقك، مع تجربة Shlink في Docker تبين لماذا لا يساوي عدد النقرات عدد الزوار.](https://arabroot.io/articles/%D8%A7%D9%84%D8%B1%D9%88%D8%A7%D8%A8%D8%B7-%D8%A7%D9%84%D9%85%D8%AE%D8%AA%D8%B5%D8%B1%D8%A9-%D9%88%D8%AA%D8%AA%D8%A8%D8%B9-%D8%A7%D9%84%D9%86%D9%82%D8%B1%D8%A7%D8%AA-bitly-%D9%88%D8%A8%D8%AF%D8%A7%D8%A6%D9%84%D9%87/)[![](https://arabroot.io/content/images/2026/10/web-analytics-tools-cover-cover.webp)دليلتحليلات الموقع دون Google Analytics: مقارنة عمليةشغلنا Umami وPlausible وMatomo على نفس الموقع وقارناها بـ Google Analytics في حجم السكربت والـ Cookies والعربية وملكية البيانات.](https://arabroot.io/articles/%D8%AA%D8%AD%D9%84%D9%8A%D9%84%D8%A7%D8%AA-%D8%A7%D9%84%D9%85%D9%88%D9%82%D8%B9-%D8%AF%D9%88%D9%86-google-analytics-%D9%85%D9%82%D8%A7%D8%B1%D9%86%D8%A9-%D8%B9%D9%85%D9%84%D9%8A%D8%A9/)[![](https://arabroot.io/content/images/2026/10/marketing-automation-cover-cover.webp)دليلأتمتة التسويق Marketing Automation وتقييم العملاء Lead Scoringكيف تتابع كل عميل محتمل في وقته بقواعد من محفز وشرط وإجراء، وكيف تقيمه بالنقاط لكي يبدأ فريق المبيعات بالأقرب للشراء.](https://arabroot.io/articles/%D8%A7%D8%AA%D9%85%D8%AA%D8%A9-%D8%A7%D9%84%D8%AA%D8%B3%D9%88%D9%8A%D9%82-marketing-automation-%D9%88%D8%AA%D9%82%D9%8A%D9%8A%D9%85-%D8%A7%D9%84%D8%B9%D9%85%D9%84%D8%A7%D8%A1-lead-scoring/)

## سجل التحديثات

- أكتوبر 2026: كتابة الدليل واختباره على Umami 3.4.1 (ghcr.io/umami-software/umami:3.4.1 مع postgres:18.6) وShlink 5.1.8 مع shlink-web-client 4.8.1 وMautic 7.2.1 (mautic/mautic:7.2.1-apache مع mysql:8.4.11) وaxllent/mailpit:v1.31.5 وnginx:1.31.6-alpine على Docker Engine 29.8.0.