الإعداد هو حيث تخسر معظم منتجات SaaS المستخدمين قبل أن يروا القيمة. المعمارية الصحيحة لعزل مساحة العمل والتحقق من البريد وإدارة الفترة التجريبية تحدد الفرق.
الإعداد هو أول تفاعل حقيقي للمستخدم مع الخلفية. وهو أيضاً حيث تخسر معظم منتجات SaaS المستخدمين بصمت، ليس لأن المنتج سيء، بل لأن تدفق الإعداد يفقد الحالة أو يرسل رسائل بريد إلكتروني مكررة أو يُنشئ مساحة عمل في حالة غير متسقة تُفسد البيانات لاحقاً.
ما الذي يتضمنه الإعداد فعلياً
تدفق إعداد نموذجي لمنتج SaaS موجه للشركات يغطي:
- المستخدم يرسل نموذج التسجيل (البريد الإلكتروني، الاسم، الشركة، كلمة المرور)
- النظام يُنشئ حساباً ومساحة عمل
- النظام يرسل بريد التحقق من البريد الإلكتروني
- المستخدم يتحقق من بريده الإلكتروني
- النظام يُفعل الحساب ويبدأ الفترة التجريبية
- المستخدم يُكمل خطوات الإعداد (دعوة الزملاء، ربط التكاملات، إلخ)
- النظام يُعلم الإعداد كمكتمل
كل خطوة من هذه الخطوات لها حالات فشل. البريد قد لا يُرسل. المستخدم قد يُغلق التبويب في منتصف الطريق. قد يفشل تهيئة مساحة العمل بعد إنشاء سجل المستخدم. معالجة كل هذه الحالات بشكل صحيح هو ما يُميز الإعداد على مستوى الإنتاج عن النماذج الأولية السريعة.
نموذج البيانات: فصل الحساب ومساحة العمل وحالة الإعداد
أول قرار تصميمي هو كيفية نمذجة الكيانات. خطأ شائع هو حشو الكثير على سجل المستخدم. النموذج الأنظف يفصل المخاوف:
- accounts: البريد الإلكتروني وكلمة المرور
- email_verifications: رمز التحقق وحالته
- workspaces: اسم مساحة العمل والخطة وتاريخ انتهاء الفترة التجريبية
- workspace_members: عضوية المستخدم في مساحة العمل مع الدور
- onboarding_progress: الخطوات المكتملة لكل مساحة عمل
هذا يمنحك فصلاً نظيفاً. حالة الإعداد تعيش على مساحة العمل. حالة الفترة التجريبية تعيش على مساحة العمل. التحقق من البريد يعيش على الحساب.
التسجيل: الحد المعاملاتي
التسجيل يجب أن يكون ذرياً. إذا فشلت أي خطوة، لا ينبغي الاحتفاظ بأي شيء. في Go مع database/sql، هذا يعني تغليف التسجيل بالكامل في معاملة:
tx, err := s.db.BeginTx(ctx, nil)
defer tx.Rollback()
// 1. إنشاء الحساب
// 2. إنشاء مساحة العمل
// 3. إضافة عضوية المالك
// 4. تهيئة تقدم الإعداد
// 5. إنشاء رمز التحقق
tx.Commit()
// إرسال البريد بعد الالتزام
s.mailer.SendVerification(ctx, input.Email, token)
لاحظ أن إرسال البريد يحدث بعد tx.Commit(). إرسال البريد داخل المعاملة خطأ كلاسيكي: إذا نجح إرسال البريد لكن فشل الالتزام، أرسلت بريد تحقق لحساب غير موجود.
التحقق من البريد الإلكتروني: تصميم الرمز والإعادة
رموز التحقق يجب أن تمتلك انتهاء صلاحية واضح وضماناً للاستخدام لمرة واحدة. النهج الشائع هو تخزين تجزئة الرمز وتمييز الصف كمستخدم عند التحقق:
UPDATE email_verifications
SET verified_at = now()
WHERE token = $1
AND verified_at IS NULL
AND expires_at > now()
RETURNING account_id
UPDATE ... RETURNING ذري: يتحقق ويستهلك الرمز في عملية واحدة. لا يوجد خطأ التحقق ثم التحديث.
إدارة الفترة التجريبية: متى تبدأ الساعة
معظم منتجات SaaS تخطئ هنا: الفترة التجريبية تبدأ عند التحقق من البريد وليس عند التسجيل. مستخدم لم يتحقق من بريده ليس مستخدماً حقيقياً للمنتج.
الحماية المهمة هنا: AND w.trial_ends_at IS NULL. إذا تشغيلت هذه الدالة مرتين (لضمان التوحيد)، لا تُعيد ضبط ساعة الفترة التجريبية.
تتبع خطوات الإعداد
للإعداد متعدد الخطوات، النهج الأنظف هو تخزين الخطوات المكتملة كمصفوفة في PostgreSQL وإضافتها ذرياً:
UPDATE onboarding_progress
SET completed_steps = array_append(
array_remove(completed_steps, $2), $2
)
WHERE workspace_id = $1
array_remove قبل array_append يجعل العملية توحيدية: إذا كانت الخطوة موجودة بالفعل في المصفوفة، تُزال وتُضاف من جديد، لا تتراكم التكرارات.
الحالات الطارئة التي تكسر الإعداد في الإنتاج
التسجيلات المكررة: مستخدم يرسل النموذج مرتين لأن الطلب الأول كان بطيئاً. قيد UNIQUE على accounts.email يعالج هذا، لكن معالجة الأخطاء تحتاج إلى إرجاع رسالة صديقة للمستخدم.
الدعوة إلى حساب موجود: مستخدم مدعو إلى مساحة عمل لكنه يمتلك حساباً بالفعل. يحتاج التدفق إلى اكتشاف هذا وتخطي إنشاء الحساب وإضافة العضوية فقط.
إعادة استخدام الرمز المنتهي الصلاحية: المستخدمون كثيراً ما ينقرون على رابط تحقق قديم يجدونه في صندوق الوارد. الحراسة AND expires_at > now() تعالج هذا.
هل تريد مساعدة في بنية إعداد منتجك؟
Voxire تُصمم وتبني خلفيات SaaS بـ Go و PostgreSQL للفرق التي تطلق منتجات في لبنان ومنطقة MENA. إذا كنت تبدأ منتج SaaS جديداً أو تُعيد هيكلة تدفق إعداد موجود، تواصل معنا.
https://voxire.com/get-a-quote/



