في بداية 2009 كانت Dropbox تدفع على إعلانات البحث بين 233 و388 دولاراً لكل مستخدم جديد، لمنتج سعره 99 دولاراً في السنة، كما ذكر مؤسسها Drew Houston في عرض Startup Lessons Learned. وبعد ذلك أطلقت برنامج إحالة يعطي مساحة تخزين إضافية للطرفين، الداعي والمدعو، فارتفعت التسجيلات بشكل دائم بنسبة 60% كما يذكر نفس العرض، وأصبحت الإحالات تجلب 35% من التسجيلات اليومية، وفي أبريل 2010 أرسل المستخدمون 2.8 مليون دعوة مباشرة خلال ثلاثين يوماً.
هذه القصة تتكرر في كل مقال عن النمو، ولكن الذي لا يتكرر معها هو الحساب: متى يجلب برنامج الإحالة نمواً حقيقياً، ومتى يكون مجرد خصم تدفعه لمن كان سيأتي على أي حال، وكيف تمنع من يسجل عشرة حسابات وهمية ليأخذ المكافأة. وفي هذا المقال سوف نتناول:
- لماذا تعمل الإحالة، ومتى لا تعمل.
- أنواع المكافآت Incentives: من طرف واحد أو من الطرفين، ومن المنتج أو نقداً.
- معامل الانتشار K Viral Coefficient بأرقام محسوبة، وزمن الدورة Cycle Time.
- الاحتيال Fraud: الأنماط المعروفة وكيف تفحصها قبل أن تدفع.
- تصميم الجداول وقواعد الفحص بـ SQL، مع تشغيل فعلي في Docker.
- الإحالة والموافقة في نظام حماية البيانات الشخصية.
لماذا تعمل الإحالة؟
الإحالة Referral هي أن يجلب المستخدم الحالي مستخدماً جديداً، برابط خاص به، وغالباً مقابل مكافأة. وهي تعمل لثلاثة أسباب: الثقة، فالتوصية من زميل يعرف عملك أقوى من أي إعلان، والملاءمة، لأن الزميل يعرف هل يحتاج صديقه هذا المنتج قبل أن يرسل الرابط، والتكلفة، لأنك تدفع فقط عندما يأتي مستخدم فعلاً. وقد رأينا في تجربة مقال قمع التسويق كيف جلبت الإحالات 4% من الزوار و26% من العملاء.
ولكن هناك شرطاً قبل كل ذلك: لا أحد يوصي بمنتج لم يجد فيه قيمة، لذلك فبرنامج الإحالة يأتي بعد التفعيل والاحتفاظ لا قبلهما، وإذا كان منحنى الاحتفاظ عندك ينزل إلى الصفر كما شرحنا في مقال التفعيل والاحتفاظ، فالمكافأة لن تقنع أحداً بأن يرسل رابطاً لزميله، وإذا أقنعته فسوف يغادر زميله أيضاً. والصورة التالية تبين حلقة الإحالة كاملة:

وفي الصورة أعلاه لاحظ أن الإحالة حلقة نمو Growth Loop وليست قمعاً، فالمستخدم الجديد يدخل الحلقة من جديد كداع، وهذا هو الفرق الذي شرحناه في مقال تسويق النمو بين القمع الذي يتوقف عند الشراء والحلقة التي تعيد استثمار ما تنتجه.
أنواع المكافآت
المكافأة تجيب عن سؤال واحد: لماذا يتعب المستخدم في إرسال الرابط؟ والخيارات الأساسية كما يلي:
| النوع | مثال موثق | نقاط القوة | نقاط الضعف |
|---|---|---|---|
| من الطرفين، من المنتج نفسه Two-sided, in-product | Dropbox: 500 MB للداعي في الخطة المجانية Basic حتى 16 GB، و1 GB في الخطط المدفوعة حتى 32 GB، و500 MB للمدعو، كما في صفحة المساعدة | المكافأة تزيد استخدام المنتج نفسه، وتكلفتها الفعلية أقل من قيمتها عند المستخدم، والمدعو يبدأ بشيء إضافي | لا تناسب منتجاً لا توجد فيه وحدة يريد المستخدم المزيد منها |
| من طرف واحد، نقداً أو عمولة Affiliate | Notion: حتى 50 دولاراً لكل تسجيل مفعل و20% من إيراد السنة الأولى، كما في صفحة برنامج الشركاء | يجذب المؤثرين وكتاب المحتوى الذين يملكون جمهوراً | يتحول إلى قناة مدفوعة تحتاج إدارة، ويجذب الاحتيال أكثر لأن المال نقد |
| خصم على الاشتراك | شهر مجاني للطرفين | سهل الفهم، ولا يكلف قبل أن يدفع المدعو | لا يعني شيئاً للمستخدم المجاني |
| بدون مكافأة، مشاركة طبيعية | دعوة زميل إلى مساحة عمل مشتركة | أصدق أنواع الإحالة، ولا تكلف شيئاً | تعتمد على أن المنتج يحتاج أكثر من شخص أصلاً |
ولاحظ أن برنامج Notion في الجدول يعلن حالياً أنه لا يقبل شركاء جدداً، وهذا تذكير بأن برامج الإحالة والعمولات تتغير وتتوقف، فلا تعد بمكافأة لا تستطيع أن تستمر في دفعها.
وقد يتساءل البعض: هل الأفضل أن تكون المكافأة للطرفين أم للداعي وحده؟ والإجابة أن مكافأة الطرفين تجعل الرابط هدية لا طلباً، فالداعي يقول لصديقه «خذ مساحة إضافية» بدل «سجل لكي أربح أنا»، وهذا ما أشار إليه عرض Dropbox عندما ذكر أن البرنامج استلهم فكرته من مكافأة التسجيل في PayPal، ولكنه أعطى الطرفين مساحة بدل المال.
معامل الانتشار K Viral Coefficient
معامل الانتشار K يقيس كم مستخدماً جديداً يجلب كل مستخدم، ويحسب بضرب رقمين: متوسط عدد الدعوات التي يرسلها المستخدم i، في نسبة الدعوات التي تتحول إلى مستخدمين نشطين c. فإذا أرسل كل مستخدم 5 دعوات في المتوسط، وتحول 16% منها إلى مستخدمين نشطين، فإن K تساوي 0.8. والرقم المهم هو 1: فإذا كانت K أكبر من 1 فكل دورة أكبر من التي قبلها وينمو المنتج من نفسه، وإذا كانت أقل من 1 فالإحالة لا تنمو وحدها، ولكنها تضاعف كل ما تجلبه القنوات الأخرى.
ولكي نرى الفرق بالأرقام كتبنا سكربت Python صغيراً يحسب النمو دورة بعد دورة من 1000 مستخدم جاؤوا من قنوات أخرى، ويحسب أثر زمن الدورة، وتكلفة المكافأة مع الاحتيال. وكل المدخلات في السكربت أرقام افترضناها للتمرين:
# Viral coefficient K: how many extra users a referral program brings, cycle by cycle.
# python k_factor.py
# K = invites sent per user x share of invites that become active users.
# All inputs are example numbers for the exercise, not benchmarks.
SEED = 1000 # users who joined from other channels this month
CYCLES = 8 # referral cycles (one cycle = time from joining to the invited friend joining)
def grow(k, seed=SEED, cycles=CYCLES):
rows, new, total = [], seed, seed
for c in range(1, cycles + 1):
new = new * k # each new cohort invites the next one
total += new
rows.append((c, new, total))
return rows
print("K = invites per user x invite conversion")
for invites, conv in [(4, 0.10), (5, 0.16), (6, 0.20)]:
print(f" {invites} invites x {conv:.0%} = K {invites * conv:.2f}")
print()
print(f"Users from a seed of {SEED}, cycle by cycle (new users in the cycle / running total)")
ks = [0.4, 0.8, 1.2]
print(f"{'cycle':<7}" + "".join(f"{'K=' + str(k):>20}" for k in ks))
table = {k: grow(k) for k in ks}
for i in range(CYCLES):
print(f"{i + 1:<7}" + "".join(f"{table[k][i][1]:>9.0f} /{table[k][i][2]:>8.0f} " for k in ks))
print()
for k in ks[:2]:
print(f"K={k}: total never exceeds seed / (1 - K) = {SEED / (1 - k):.0f}, a {1 / (1 - k):.2f}x multiplier on every channel")
print()
# Cycle time matters as much as K: same K, different speed
for days in (3, 14):
cycles_in_90 = 90 // days
total = SEED * sum(0.8 ** c for c in range(cycles_in_90 + 1))
print(f"K=0.8, cycle {days:>2} days: {cycles_in_90:>2} cycles in 90 days -> {total:.0f} users")
print()
# Two-sided reward: what does each referred user cost, and when does fraud eat the budget?
reward_each_side = 20 # SAR credit to the inviter and to the friend (example)
paid_conversion = 0.25 # share of referred users who become paying customers (example)
cost_per_referred = 2 * reward_each_side
print(f"Two-sided reward {reward_each_side} SAR each side -> {cost_per_referred} SAR per referred signup")
print(f" cost per paying customer from referrals = {cost_per_referred / paid_conversion:.0f} SAR")
for fake in (0.10, 0.30):
real = 1 - fake
print(f" with {fake:.0%} fake signups rewarded: {cost_per_referred / (paid_conversion * real):.0f} SAR per paying customer")ونشغله في Container مؤقت:
docker run --rm --name mki-kfactor -v "$(pwd)":/lab -w /lab python:3.13.17-slim \
sh -c "python --version && python k_factor.py"والمخرج سوف يكون كما يلي:
Python 3.13.17
K = invites per user x invite conversion
4 invites x 10% = K 0.40
5 invites x 16% = K 0.80
6 invites x 20% = K 1.20
Users from a seed of 1000, cycle by cycle (new users in the cycle / running total)
cycle K=0.4 K=0.8 K=1.2
1 400 / 1400 800 / 1800 1200 / 2200
2 160 / 1560 640 / 2440 1440 / 3640
3 64 / 1624 512 / 2952 1728 / 5368
4 26 / 1650 410 / 3362 2074 / 7442
5 10 / 1660 328 / 3689 2488 / 9930
6 4 / 1664 262 / 3951 2986 / 12916
7 2 / 1666 210 / 4161 3583 / 16499
8 1 / 1666 168 / 4329 4300 / 20799
K=0.4: total never exceeds seed / (1 - K) = 1667, a 1.67x multiplier on every channel
K=0.8: total never exceeds seed / (1 - K) = 5000, a 5.00x multiplier on every channel
K=0.8, cycle 3 days: 30 cycles in 90 days -> 4995 users
K=0.8, cycle 14 days: 6 cycles in 90 days -> 3951 users
Two-sided reward 20 SAR each side -> 40 SAR per referred signup
cost per paying customer from referrals = 160 SAR
with 10% fake signups rewarded: 178 SAR per paying customer
with 30% fake signups rewarded: 229 SAR per paying customerوالصورة التالية ترسم جدول الدورات من نفس المخرج:

وفي المخرج أعلاه لاحظ التالي:
- K تحت 1 لها سقف: مع K تساوي 0.8 لا يتجاوز مجموع المستخدمين 1000 ÷ (1 ناقص 0.8)، أي 5000 مستخدم، فالإحالة هنا تضاعف كل قناة خمس مرات على الأكثر. وهذا ممتاز، ولكنه ليس نمواً ذاتياً، ولا تزال تحتاج من يجلب الألف الأولى.
- K فوق 1 نادرة: مع 1.2 يصل المجموع إلى 20799 بعد ثماني دورات ويستمر، ولكن الوصول إليها يعني أن كل مستخدم يجلب أكثر من مستخدم نشط واحد، وهذا يحدث عادة في المنتجات التي لا تعمل إلا مع الآخرين، مثل أدوات التواصل، لا بسبب المكافأة.
- زمن الدورة مهم بقدر K: بنفس K تساوي 0.8، إذا كانت الدورة 3 أيام يصل المنتج إلى 4995 مستخدماً خلال 90 يوماً، وإذا كانت 14 يوماً يصل إلى 3951، لذلك اجعل الدعوة سهلة في اللحظة التي يرى فيها المستخدم القيمة، لا في صفحة إعدادات لا يزورها.
- الاحتيال يرفع التكلفة الحقيقية: مكافأة 20 ريالاً لكل طرف تعني 40 ريالاً لكل تسجيل، و160 ريالاً لكل عميل يدفع إذا كان ربع المدعوين يدفعون، ولكن إذا كان 30% من التسجيلات المكافأة وهمية ترتفع التكلفة إلى 229 ريالاً، وقارن هذا الرقم بتكلفة العميل من القنوات الأخرى قبل أن تقرر.
الاحتيال Fraud: من يربح المكافأة دون أن يجلب أحداً؟
أي مكافأة تدفع مقابل تسجيل سوف يجد أحد طريقة ليحصل عليها دون أن يجلب مستخدماً حقيقياً. والأنماط المعروفة كما يلي:
- الإحالة الذاتية Self-referral: المستخدم يسجل حساباً ثانياً بنفسه من نفس الجهاز، ولذلك تعتبر Dropbox الإحالة غير مؤهلة Ineligible إذا سجل المدعو من نفس الكمبيوتر الذي يستخدمه الداعي، ويمنع برنامج Notion الإحالة الذاتية صراحة.
- البريد المؤقت Disposable Email: عشرات الحسابات من خدمات بريد مؤقت لا يقرؤها أحد.
- التسجيل المتتابع من عنوان واحد: عدة تسجيلات من نفس عنوان IP خلال دقائق.
- حسابات بلا استخدام: تسجيل ثم لا شيء، وهذا أسهل ما تمنعه، بأن تصرف المكافأة بعد التفعيل، فلا تكتمل إحالة Dropbox حتى يثبت المدعو التطبيق ويسجل الدخول فيه ويؤكد بريده.
- الاسترداد بعد المكافأة: المدعو يدفع ثم يسترد ماله بعد أن يأخذ الداعي العمولة، ولذلك يحتفظ برنامج Notion بحق استرجاع المكافأة إذا عاد المدعو إلى الخطة المجانية أو استرد ماله خلال أول شهرين.
وأضف إلى ذلك حداً أعلى للمكافآت لكل مستخدم، مثل حد 16 GB في Dropbox، أي 32 إحالة في الخطة المجانية، لأن الحد يقلل الخسارة إذا نجح الاحتيال رغم الفحوص.
التصميم: جدول واحد وقواعد فحص
برنامج الإحالة في أبسط أشكاله جدول واحد يربط كل مستخدم جديد بمن دعاه، وحالة تنتقل من «معلقة» إلى «مؤهلة» ثم «صرفت». والملف التالي ينشئ الجدول ويضع فيه خمس إحالات مثال، ثم يطبق قواعد الفحص بـ SQL:
-- Referral tracking: who invited whom, and when the reward may be paid.
CREATE TABLE referrals (
id INTEGER PRIMARY KEY,
referrer_id TEXT NOT NULL, -- the user who shared the link
referred_id TEXT NOT NULL UNIQUE, -- one referrer per new user (the link that was used)
signup_at TEXT NOT NULL,
signup_ip TEXT,
device_hash TEXT, -- hashed device fingerprint, not the raw value
email_domain TEXT,
activated_at TEXT, -- reward only after activation, not after signup
status TEXT NOT NULL DEFAULT 'pending' -- pending, qualified, rewarded, rejected
);
INSERT INTO referrals (referrer_id, referred_id, signup_at, signup_ip, device_hash, email_domain, activated_at) VALUES
('u1', 'u20', '2026-10-01 10:00', '198.51.100.7', 'd-aa', 'example.com', '2026-10-02 09:00'),
('u1', 'u21', '2026-10-01 10:04', '198.51.100.7', 'd-u1', 'mailinator.com', NULL),
('u1', 'u22', '2026-10-01 10:06', '198.51.100.7', 'd-u1', 'mailinator.com', NULL),
('u2', 'u23', '2026-10-03 18:30', '203.0.113.40', 'd-bb', 'example.org', '2026-10-05 08:15'),
('u3', 'u24', '2026-10-04 12:00', '192.0.2.15', 'd-cc', 'example.net', NULL);
-- the referrer's own device, recorded at the referrer's signup
CREATE TABLE users (id TEXT PRIMARY KEY, device_hash TEXT);
INSERT INTO users VALUES ('u1', 'd-u1'), ('u2', 'd-u2'), ('u3', 'd-u3');
-- Review before paying: each rule that matches is a reason to hold the reward
SELECT r.referred_id, r.referrer_id,
CASE WHEN r.device_hash = u.device_hash THEN 'same device as referrer'
WHEN r.email_domain IN ('mailinator.com', 'guerrillamail.com') THEN 'disposable email'
WHEN (SELECT COUNT(*) FROM referrals x WHERE x.referrer_id = r.referrer_id AND x.signup_ip = r.signup_ip
AND abs(julianday(x.signup_at) - julianday(r.signup_at)) * 24 < 1) > 1 THEN 'burst from one IP'
WHEN r.activated_at IS NULL THEN 'not activated yet'
ELSE 'ok' END AS decision
FROM referrals r JOIN users u ON u.id = r.referrer_id
ORDER BY r.id;ونشغله بسكربت صغير على SQLite في الذاكرة:
# Runs referrals.sql in an in-memory SQLite database and prints the review decision for each referral.
import sqlite3
con = sqlite3.connect(":memory:")
*setup, query = [s for s in open("referrals.sql").read().split(";") if s.strip()]
for statement in setup:
con.execute(statement)
print(f"{'referred':<10}{'referrer':<10}decision")
for referred, referrer, decision in con.execute(query):
print(f"{referred:<10}{referrer:<10}{decision}")docker run --rm --name mki-referrals -v "$(pwd)":/lab -w /lab python:3.13.17-slim python check_referrals.pyوالمخرج سوف يكون كما يلي:
referred referrer decision
u20 u1 burst from one IP
u21 u1 same device as referrer
u22 u1 same device as referrer
u23 u2 ok
u24 u3 not activated yetفي المخرج أعلاه لاحظ التالي:
- الحسابان
u21وu22سجلا من نفس جهاز الداعيu1وببريد مؤقت، فتظهر القاعدة الأولى التي تنطبق، والقرار هنا واضح. - الحساب
u20سجل من نفس عنوان IP خلال ساعة، ولكنه من جهاز آخر وتفعل في اليوم التالي، وقد يكون زميلاً في نفس المكتب خلف نفس الـ NAT. لذلك فالقواعد توقف المكافأة للمراجعة ولا ترفض الحساب تلقائياً، لأن رفض مستخدم حقيقي يخسرك المستخدم والداعي معاً. - الحساب
u24لم يتفعل بعد، فتبقى المكافأة معلقة حتى يتفعل، وهذا وحده يمنع أغلب الحسابات الوهمية. - عمود
device_hashيحفظ هاش لبصمة الجهاز لا القيمة نفسها، وعنوان IP وبصمة الجهاز بيانات شخصية، فاجمع منها ما تحتاجه للفحص فقط، واحذفها بعد أن تنتهي مدة المراجعة.
وأما الأدوات الجاهزة فالخيار المفتوح المصدر محدود هنا، فمثلاً Dub مرخص بـ AGPL-3.0، ولكن برنامج الشركاء والإحالة فيه موجود في مجلدات النسخة التجارية Enterprise Edition بترخيص منفصل، ونقارن هذه الأدوات في مقال أدوات النمو من نفس المرحلة. ولذلك فأغلب الشركات الصغيرة تبني الإحالة بنفسها بجدول مثل الذي أعلاه، لأنها في النهاية رابط ومعرف وقواعد صرف.
الإحالة والموافقة على الرسائل
بعض المنتجات تطلب من المستخدم بريد أصدقائه أو تقرأ جهات الاتصال، ثم ترسل الدعوة باسم المنتج، وهنا انتبه، فالمادة الخامسة والعشرون من نظام حماية البيانات الشخصية تمنع استخدام وسائل الاتصال الشخصية، ومنها العناوين البريدية والإلكترونية، لإرسال مواد دعائية إلا بموافقة المتلقي ومع آلية واضحة لإيقافها، والصديق الذي أدخل زميله بريده لم يوافق على شيء. لذلك فالأسلم أن يشارك المستخدم رابطه بنفسه، بنسخه أو عبر تطبيق المحادثة الذي يستخدمه، بدل أن يرسل منتجك رسالة إلى عنوان لم يعطك صاحبه إياه، وتفاصيل الموافقة في السعودية في مقال التسويق الرقمي في السعودية من نفس المسار.
أخطاء شائعة
- إطلاق الإحالة قبل أن يستقر الاحتفاظ: المستخدم الذي لم يجد قيمة لن يوصي بالمنتج، والمدعو سوف يغادر مثله.
- المكافأة عند التسجيل: أسهل باب للاحتيال، فاصرفها بعد التفعيل أو بعد أول دفعة.
- رابط الدعوة في مكان لا يزوره أحد: ضعه في اللحظة التي يرى فيها المستخدم النتيجة، مثل بعد أول تنبيه ناجح أو أول تقرير.
- حساب K من التسجيلات لا من المستخدمين النشطين: التسجيل الوهمي يرفع K على الورق ولا يرفع شيئاً في الواقع.
- نسب كل مستخدم جاء برابط إلى البرنامج: بعضهم كان سيأتي على أي حال، والطريقة الوحيدة لمعرفة الأثر الحقيقي للمكافأة أن تختبرها، مثل أن تعرض المكافأة على نصف المستخدمين فقط في تجربة كما في مقال تجارب النمو العملي.
الخلاصة
وصلنا لنهاية الموضوع، وأهم ما فيه:
- الإحالة تعمل عندما يجد المستخدم قيمة حقيقية، فهي تأتي بعد التفعيل والاحتفاظ لا قبلهما.
- مكافأة الطرفين من داخل المنتج، كمساحة Dropbox، تجعل الرابط هدية لا طلباً، وتكلف أقل من قيمتها عند المستخدم.
- K تساوي عدد الدعوات في نسبة التحويل، وتحت 1 تعني مضاعفاً لكل قناة له سقف، فـ 0.8 تعني خمسة أضعاف على الأكثر، وزمن الدورة يغير النتيجة بقدر K.
- اصرف المكافأة بعد التفعيل، وافحص الجهاز والبريد والتسجيل المتتابع، وأوقف المشكوك فيه للمراجعة بدل الرفض التلقائي، وضع حداً أعلى للمكافآت.
- دع المستخدم يشارك رابطه بنفسه بدل أن يرسل المنتج رسائل إلى عناوين لم يوافق أصحابها.
دليلتسويق النمو Growth Marketing: مقاييس AARRR وحلقات النموكيف يعمل فريق النمو على كل مرحلة من مسار المستخدم، ولماذا تنمو الشركات بالحلقات لا بالقمع، وكم تجربة تحتاج.
دليلالتفعيل Activation والاحتفاظ Retention: لماذا يغادر المستخدمون؟كيف تجد اللحظة التي يرى فيها المستخدم قيمة منتجك، وتقرأ منحنى الاحتفاظ والتسرب، مع تجربة تحسبها بـ Python وSQL.
دليلأدوات النمو: Amplitude وMixpanel وبدائلها مفتوحة المصدرمقارنة أدوات تحليلات المنتج والتجارب والإحالة بالترخيص وآخر إصدار والسعر، مع اختبار فعلي للعربية في GrowthBook وUnleash.
دليلتجارب النمو عملياً: من الفرضية إلى القرار بالأرقامنبني مختبر GrowthBook في Docker ونختبر قائمة خطوات البداية بزيارات محاكاة، من حجم العينة إلى قرار نتيجة غير حاسمة.
دليلأنظمة التسويق الرقمي Digital Marketing في السعوديةما تشترطه الأنظمة السعودية في موافقة العميل والرسائل التسويقية والإعلان الإلكتروني وإعلانات المؤثرين، وكيف تطبقه في الكود.
دليلميزانية التسويق وتكلفة العميل CAC والعائد ROIكيف تحسب تكلفة اكتساب العميل وقيمته وفترة الاسترداد والعائد لكل قناة، وكيف تحدد حجم الميزانية من هدفك لا من نسب الشركات الكبيرة.سجل التحديثات
- أكتوبر 2026: كتابة المقال، مع حساب معامل الانتشار وزمن الدورة وتكلفة المكافأة، وقواعد فحص الإحالات بـ SQL، بسكربتات Python 3.13.17 في Docker، وشروط برنامجي Dropbox وNotion كما في صفحاتهما الرسمية.