التسويق والمبيعات الأدلة التقنية

الروابط المختصرة وتتبع النقرات: Bitly وبدائله

Bitly وDub أمام Shlink وYOURLS على نطاقك، مع تجربة Shlink في Docker تبين لماذا لا يساوي عدد النقرات عدد الزوار.

الروابط المختصرة وتتبع النقرات: Bitly وبدائله

في مقال قياس التسويق كتبنا روابط بمعاملات UTM مثل https://example.com/features/backup?utm_source=newsletter&utm_medium=email&utm_campaign=launch-2026-10، وهذا الرابط صحيح ولكنه طويل، ولا يصلح لمنشور في X أو لرسالة نصية أو لرمز QR على مطبوعة في معرض. والحل المعروف هو الرابط المختصر Short Link: عنوان قصير مثل s.example.com/launch يحول الزائر إلى الرابط الطويل، ويعد النقرات في الطريق. والخدمة الأشهر Bitly، ولكن الرابط المختصر يعيش في منشوراتك ومطبوعاتك سنوات، فإذا أغلقت الخدمة أو غيرت أسعارها أو حجبت حسابك تعطلت كل روابطك القديمة، لذلك من المنطقي أن يكون الرابط على نطاقك أنت.

دليلقياس التسويق: روابط UTM والإسناد Attributionكيف تعرف القناة التي جاءت بكل عميل: روابط UTM بقواعد تسمية ثابتة، وتحويل تعرفه أنت، ونموذج إسناد تفهم ما يحسبه.دليلتحليلات الموقع دون Google Analytics: مقارنة عمليةشغلنا Umami وPlausible وMatomo على نفس الموقع وقارناها بـ Google Analytics في حجم السكربت والـ Cookies والعربية وملكية البيانات.

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

  • ماذا يحدث عند الضغط على رابط مختصر، ولماذا لا يتطابق عدد النقرات مع عدد الزوار.
  • Bitly وDub بأسعارهما، وShlink وYOURLS كبديلين تستضيفهما بنفسك.
  • تجربة عملية على Shlink في Docker: رابط بمعاملات UTM، ورابط باسم عربي، وزيارات من متصفحات وتطبيقات، وكيف ميز Shlink الـ Bots.
  • من يختار ماذا.

ماذا يحدث عند الضغط على رابط مختصر؟

الرابط المختصر طلب HTTP عادي تجيب عنه الخدمة بتحويل Redirect إلى الرابط الطويل، وقبل أن تجيب تسجل الزيارة. والصورة التالية تبين الخطوتين، والأرقام فيها من تجربتنا في آخر المقال:

الزائر يضغط على s.example.com/launch فيصل الطلب إلى خدمة الروابط المختصرة Shlink التي تسجل الزيارة بوقتها ومتصفحها ومصدرها وهل هي Bot، ثم تجيب HTTP 302 بعنوان الرابط الطويل مع utm_source=newsletter، فيصل الزائر إلى example.com حيث تقرأ أداة التحليلات UTM، وتحتها ملاحظة أن Shlink عد 5 زيارات منها 3 لأشخاص و2 Bots هما Slackbot وWhatsApp طلبا الرابط لعرض معاينته
الخدمة تعد النقرات، وUTM يحمل المصدر إلى أداة التحليلات

ولاحظ أن الرابط المختصر لا يغني عن UTM، فهو يعطيك عدد من ضغطوا، أما أداة التحليلات في موقعك فلا تعرف أن الزائر جاء من رابط مختصر إلا من معاملات UTM في الرابط الطويل. لذلك ضع UTM في الرابط الطويل دائماً، والرابط المختصر يخفيها عن القارئ فقط. وعندما تقارن الرقمين سوف تجد أن نقرات الرابط المختصر أكبر من زيارات الحملة في أداة التحليلات، والسبب أن تطبيقات مثل WhatsApp وSlack وLinkedIn تطلب الرابط لتعرض معاينته Link Preview قبل أن يضغط أحد، وأن بعض من يضغط يغلق الصفحة قبل أن يحمل كود التتبع.

وهناك قرار تقني واحد مهم: نوع التحويل. فالتحويل الدائم 301 تحفظه المتصفحات، فإذا غيرت وجهة الرابط لاحقاً قد لا يرى الزائر الوجهة الجديدة ولا تسجل الخدمة زيارته، أما المؤقت 302 فيمر بالخدمة في كل مرة. وShlink يستخدم 302 افتراضياً ويسمح بتغييره بالمتغير REDIRECT_STATUS_CODE كما في توثيق متغيراته، ولروابط الحملات أبقه 302.

الخدمات التجارية: Bitly وDub

Bitly أشهر الخدمات، ويجمع الروابط المختصرة ورموز QR وصفحات هبوط بسيطة. وهذه أسعاره كما ظهرت في 25 أكتوبر 2026:

الخطةالسعرما تحصل عليه
Free05 روابط و2 رمز QR شهرياً، مع إعلانات
Core10 دولارات شهرياً بالدفع السنوي (120 دولاراً)100 رابط شهرياً، وبيانات النقرات لثلاثين يوماً، وأداة لبناء UTM
Growth29 دولاراً شهرياً بالدفع السنوي (348 دولاراً)500 رابط شهرياً، ونطاق خاص Custom Domain، وبيانات لأربعة أشهر

ولاحظ حدود الخطط: عدد روابط شهري، وبيانات النقرات تحفظ لفترة محددة، والنطاق الخاص في الخطط الأعلى فقط، أي أن روابط الخطة المجانية على bit.ly لا على نطاقك.

Dub خدمة أحدث تقدم نفسها كمنصة لإسناد الروابط Link Attribution، وفيها بناء UTM بقوالب وتتبع التحويلات وبرامج الشركاء، وصفحة أسعارها تعرض خطط Business وAdvanced وEnterprise بتجربة 14 يوماً. وكودها مفتوح على GitHub، ولكن ترخيصه بحسب ملف الترخيص مزدوج: AGPL-3.0 لأغلب الكود، وترخيص تجاري منفصل لمجلدات ee. وأما الاستضافة الذاتية فدليلها في توثيق Dub يمر بخدمات سحابية عدة: Tinybird لـ ClickHouse وUpstash لـ Redis وPlanetScale لـ MySQL وCloudflare R2 والنشر على Vercel، أي أنها ليست استضافة على سيرفرك بالمعنى الذي نقصده هنا.

Shlink خدمة روابط مختصرة مكتوبة بـ PHP وتعمل بخادم RoadRunner، بترخيص MIT، وصدر الإصدار 5.1.8 في 21 أكتوبر 2026. وهي مبنية حول REST API، أي أن كل شيء من إنشاء الرابط إلى قراءة الزيارات يتم من الـ API، والواجهة الرسومية تطبيق منفصل اسمه Shlink Web Client يعمل في المتصفح ويتصل بالخادم بمفتاح API. وتدعم نطاقات متعددة، والوسوم Tags، وقواعد تحويل حسب الجهاز واللغة، وتمييز الـ Bots، وتحديد الموقع الجغرافي إذا أعطيتها مفتاح GeoLite2.

YOURLS أقدم المشاريع، بترخيص MIT، وآخر إصداراته 1.10.6 في 30 أغسطس 2026. ويعمل بـ PHP وMySQL مع واجهة إدارة مدمجة، وقوته في الإضافات Plugins الكثيرة التي كتبها مجتمعه، وفي بساطته لمن يستضيف موقع PHP أصلاً. ولم نشغله في هذه التجربة، فما نذكره عنه من توثيقه ومستودعه.

  • نقاط القوة في Shlink: API كامل يسهل ربطه بنظامك أو بأداة النشرات، وتمييز الـ Bots، ونطاقات متعددة، وتحديثات شهرية، وDocker Image رسمية.
  • نقاط الضعف في Shlink: الواجهة تطبيق منفصل، ولم يعد الخادم ينشئ رموز QR منذ الإصدار 5.0 فانتقلت هذه الميزة إلى الواجهة كما في سجل التغييرات، والموقع الجغرافي يحتاج مفتاح GeoLite2 من MaxMind.
  • نقاط القوة في YOURLS: الأبسط تثبيتاً لمن لديه استضافة PHP، وواجهة إدارة مدمجة، ومكتبة إضافات كبيرة.
  • نقاط الضعف في YOURLS: ميزات مثل تمييز الـ Bots ونطاقات متعددة تأتي من الإضافات لا من النواة، وجودة الإضافات تختلف من واحدة لأخرى.

شغلنا Shlink مع PostgreSQL والواجهة في ملف Compose واحد. وShlink يقبل SQLite افتراضياً، ولكن PostgreSQL أنسب للإنتاج لأنه يتحمل الكتابة المتزامنة للزيارات ويسهل نسخه احتياطياً:

name: mkd-sl

services:
  shlink:
    image: shlinkio/shlink:5.1.8
    ports: ["127.0.0.1:18780:8080"]
    environment:
      DEFAULT_DOMAIN: s.example.test:18780
      IS_HTTPS_ENABLED: "false"
      INITIAL_API_KEY: ${SHLINK_API_KEY}
      DB_DRIVER: postgres
      DB_HOST: db
      DB_NAME: shlink
      DB_USER: shlink
      DB_PASSWORD: ${SHLINK_DB_PASSWORD}
      TIMEZONE: Asia/Riyadh
    depends_on:
      db: { condition: service_healthy }
  db:
    image: postgres:18.6
    environment:
      POSTGRES_DB: shlink
      POSTGRES_USER: shlink
      POSTGRES_PASSWORD: ${SHLINK_DB_PASSWORD}
    volumes: ["db:/var/lib/postgresql"]
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U shlink -d shlink"]
      interval: 5s
      start_period: 2m
      retries: 30
  web-client:
    image: shlinkio/shlink-web-client:4.8.1
    ports: ["127.0.0.1:18781:8080"]

volumes:
  db:

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

  • DEFAULT_DOMAIN هو النطاق الذي تظهر به الروابط، وفي الإنتاج يكون نطاقاً قصيراً لك مثل s.example.com خلف Reverse Proxy بشهادة TLS، ومعه IS_HTTPS_ENABLED: "true".
  • INITIAL_API_KEY ينشئ أول مفتاح API عند أول تشغيل، وولدناه بـ openssl rand -hex 24 في ملف .env لا يرفع إلى المستودع.
  • المنفذان على 127.0.0.1 فقط، ولا تنشر الواجهة على الإنترنت إلا خلف دخول، لأن من يملك المفتاح يملك كل الروابط.

إنشاء الروابط

بعد التشغيل كتبنا سكربتاً بـ Node.js يستدعي الـ API، فأنشأ رابطاً باسم launch يحول إلى صفحة الميزة بمعاملات UTM للنشرة، ورابطاً ثانياً باسم عربي إطلاق بمعاملات UTM لواتساب، ثم حاول إنشاء launch مرة ثانية. والطلب الأول كان كما يلي:

curl -s -X POST http://127.0.0.1:18780/rest/v3/short-urls \
  -H "X-Api-Key: $SHLINK_API_KEY" -H "Content-Type: application/json" \
  -d '{"longUrl":"https://example.com/features/backup?utm_source=newsletter&utm_medium=email&utm_campaign=launch-2026-10","customSlug":"launch","tags":["launch-2026-10"],"title":"Backup launch (newsletter)"}'

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

200 http://s.example.test:18780/launch
200 http://s.example.test:18780/إطلاق
400 Provided slug "launch" is already in use.

ولاحظ أن الاسم العربي قبل كما هو، وظهر في قائمة الواجهة بشكل صحيح. ولكن قبل أن تستخدم أسماء عربية في روابطك تذكر أن الرابط ينسخ ويلصق في أماكن كثيرة، وبعضها يحوله إلى ترميز طويل مثل %D8%A5%D8%B7%D9%84%D8%A7%D9%82، فيفقد الرابط القصير قصره، لذلك الأسماء الإنجليزية القصيرة أسلم للمطبوعات والرسائل النصية.

قائمة الروابط في Shlink Web Client فيها رابطان بوسم launch-2026-10: الأول s.example.test:18780/إطلاق إلى رابط طويل بمعاملات utm_source=whatsapp وعدد زياراته 1، والثاني s.example.test:18780/launch بعنوان Backup launch (newsletter) وعدد زياراته 5
Shlink Web Client 4.8.1: الرابط العربي والإنجليزي بنفس الوسم

الزيارات: من الإنسان ومن الـ Bot؟

بعد ذلك طلبنا الرابطين ست مرات بمتصفحات مختلفة: iPhone قادم من LinkedIn، وChrome على Windows، وAndroid أضاف إلى الرابط utm_content=qr، ثم Slackbot وWhatsApp كما يطلبانه عند عرض معاينة الرابط، ثم iPhone على الرابط العربي. والمخرج سوف يكون كما يلي:

302 launch -> https://example.com/features/backup?utm_source=newsletter&utm_medium=email&utm_campaign=launch-2026-10 | Mozilla/5.0 (iPhone; CPU iPhon
302 launch -> https://example.com/features/backup?utm_source=newsletter&utm_medium=email&utm_campaign=launch-2026-10 | Mozilla/5.0 (Windows NT 10.0;
302 launch?utm_content=qr -> https://example.com/features/backup?utm_source=newsletter&utm_medium=email&utm_campaign=launch-2026-10&utm_content=qr | Mozilla/5.0 (Linux; Android 15
302 launch -> https://example.com/features/backup?utm_source=newsletter&utm_medium=email&utm_campaign=launch-2026-10 | Slackbot-LinkExpanding 1.0 (+h
302 launch -> https://example.com/features/backup?utm_source=newsletter&utm_medium=email&utm_campaign=launch-2026-10 | WhatsApp/2.24.6.77 A
302 إطلاق -> https://example.com/features/backup?utm_source=whatsapp&utm_medium=social&utm_campaign=launch-2026-10 | Mozilla/5.0 (iPhone; CPU iPhon

ثم قرأنا زيارات launch من الـ API:

15:43:45 human https://www.linkedin.com/  (no geolocation) | Mozilla/5.0 (iPhone; CPU iPhone OS 18_6
15:43:46 human -                          (no geolocation) | Mozilla/5.0 (Windows NT 10.0; Win64; x64
15:43:47 human -                          (no geolocation) | Mozilla/5.0 (Linux; Android 15) Chrome/1
15:43:47 bot  -                          (no geolocation) | Slackbot-LinkExpanding 1.0 (+https://api
15:43:48 bot  -                          (no geolocation) | WhatsApp/2.24.6.77 A
visitsSummary {"total":5,"nonBots":3,"bots":2}

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

  • كل التحويلات 302 كما في الإعداد الافتراضي.
  • المعامل الذي أضفناه إلى الرابط المختصر ?utm_content=qr انتقل إلى الرابط الطويل وأضيف إلى معاملاته، وهذا يعني أنك تستطيع أن تطبع نفس الرابط على أكثر من مطبوعة وتفرق بينها بمعامل واحد دون أن تنشئ رابطاً لكل واحدة.
  • Shlink سجل Slackbot وWhatsApp كـ Bot، فأعطانا 5 زيارات منها 3 لأشخاص. وهذا هو الفرق الذي تحدثنا عنه بين عدد النقرات وعدد الزوار، فإذا عرضت على فريقك «5 نقرات» فقد ضاعفت الحملة دون قصد.
  • الـ Referrer وصل في الزيارة الأولى فقط لأننا أرسلناه، وفي الواقع ستجده فارغاً في أغلب الزيارات القادمة من التطبيقات كما شرحنا في مقال قياس التسويق.
  • لا يوجد موقع جغرافي، لأننا لم نعط Shlink مفتاح GEOLITE_LICENSE_KEY، وبحسب التوثيق فغيابه يعطل تحديد الموقع تماماً.

وهذه صفحة زيارات نفس الرابط في الواجهة:

صفحة Visits for http://s.example.test:18780/launch في Shlink Web Client بعنوان Backup launch (newsletter) وعدد الزيارات 5، مع تبويبات By time وBy context وBy location وList وOptions، ورسم Visits over time
صفحة زيارات الرابط في الواجهة، والتفصيل حسب المتصفح والمصدر في تبويب By context

وأما الموارد فكان Shlink بعد التجربة يستهلك 507 MiB من الذاكرة، وهذا أكبر مما توقعنا لخدمة روابط، والسبب أن خادم RoadRunner يشغل عدة Workers من PHP مسبقاً. وكانت قاعدة البيانات 42 MiB والواجهة 8 MiB.

قبل أن تعتمد عليه في الإنتاج

  • النسخ الاحتياطي Backup: كل الروابط والزيارات في قاعدة PostgreSQL، فانسخها بـ pg_dump مع بقية قواعدك، وتذكر أن خسارة هذه القاعدة تعني أن كل رابط مطبوع يتعطل.
  • النطاق: اختر نطاقاً قصيراً لا تغيره أبداً، والسبب أن الروابط المطبوعة لا يمكن تحديثها.
  • التحديث Upgrade: ثبت رقم الإصدار في Compose، واقرأ سجل التغييرات قبل الانتقال إلى إصدار رئيسي، فالإصدار 5.0 مثلاً أزال رموز QR من الخادم.
  • الواجهة: لا تنشرها للعامة، أو ضعها خلف دخول، لأن المفتاح يخزن في متصفح من يستخدمها.

من يختار ماذا؟

  • فريق ينشر عدداً قليلاً من الروابط ولا يريد أي إدارة: Bitly، وانتبه إلى أن النطاق الخاص في الخطط الأعلى فقط.
  • فريق نمو يريد ربط الروابط بالتحويلات وبرامج الشركاء: Dub كخدمة سحابية.
  • شركة تقنية تريد الروابط على نطاقها وتربطها بأنظمتها عبر API: Shlink، وهو ما جربناه هنا.
  • موقع على استضافة PHP يريد أبسط حل بواجهة مدمجة: YOURLS مع ما يحتاجه من إضافات.

الخلاصة

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

  • الرابط المختصر يعد النقرات، وUTM في الرابط الطويل هو ما يخبر أداة التحليلات بالمصدر، فاستخدمهما معاً.
  • عدد النقرات أكبر من عدد الزوار، ففي تجربتنا كان 2 من 5 زيارات معاينات من Slackbot وWhatsApp ميزها Shlink كـ Bots.
  • أبق التحويل 302 لروابط الحملات حتى تمر كل نقرة بالخدمة وتستطيع تغيير الوجهة.
  • Shlink نقل المعاملات المضافة إلى الرابط المختصر إلى الرابط الطويل، وقبل اسماً عربياً، ورفض تكرار الاسم.
  • الرابط المطبوع يعيش سنوات، فضعه على نطاقك وانسخ قاعدة الروابط احتياطياً.

وأقرب المقالات إلى هذا الموضوع:

دليلقياس التسويق: روابط UTM والإسناد Attributionكيف تعرف القناة التي جاءت بكل عميل: روابط UTM بقواعد تسمية ثابتة، وتحويل تعرفه أنت، ونموذج إسناد تفهم ما يحسبه.دليلتحليلات الموقع دون Google Analytics: مقارنة عمليةشغلنا Umami وPlausible وMatomo على نفس الموقع وقارناها بـ Google Analytics في حجم السكربت والـ Cookies والعربية وملكية البيانات.دليلأنظمة التسويق الرقمي Digital Marketing في السعوديةما تشترطه الأنظمة السعودية في موافقة العميل والرسائل التسويقية والإعلان الإلكتروني وإعلانات المؤثرين، وكيف تطبقه في الكود.

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

  • أكتوبر 2026: كتابة المقال واختبار Shlink 5.1.8 مع Shlink Web Client 4.8.1 وPostgreSQL 18.6 في Docker Engine 29.8.0، والأسعار كما ظهرت في 25 أكتوبر 2026.
نشرة عرب رووت | ArabRoot

معرفة تستحق مكاناً في بريدك.

مقالات مختارة وأدوات مفيدة وأفكار لمشروعك القادم، في رسالة واحدة كل أسبوع.

يمكنك إلغاء الاشتراك متى شئت. الخصوصية

تم استلام طلبك. افتح بريدك واضغط رابط التأكيد لإتمام الاشتراك.