عندما تنتهي جلسة بتعطل التطبيق، لا تخسر ثقة المستخدم فحسب. بل تخسر كل ظهور إعلاني كان سيُعرض خلال بقية الجلسة، وكل إشعار إرجاع (postback) كان سيُرسل عند انتهائها، وجزءًا ملموسًا من معدل الاحتفاظ بالمستخدمين في اليوم التالي. والحسابات ليست مطمئنة.
سلسلة الخسائر
يتراوح متوسط مدة الجلسة في تطبيق جوال مستقر بين 6 و9 دقائق. ويبلغ متوسط مرات الظهور الإعلاني لكل جلسة، بعد تطبيق حدود التكرار، 2.4. لذا فإن الجلسة التي يتعطل فيها التطبيق عند الدقيقة الثانية تفقد نحو 1.6 ظهور إعلاني في المتوسط، وهي خسارة نهائية لا يمكن استردادها.
وعند احتساب ذلك على معدل تعطل يبلغ 1% و5 ملايين مستخدم نشط يوميًا (DAU)، تصبح الخسارة 80,000 ظهور إعلاني يوميًا. وعند إيراد فعلي لكل ألف ظهور (eCPM) قدره 7 دولارات، تعادل هذه الخسارة 560 دولارًا من الإيرادات كل يوم، بسبب نقطة مئوية واحدة فقط من استقرار التطبيق.
النموذج الكامل لخسارة الإيرادات
المعادلة بسيطة: خسارة الإيرادات اليومية = DAU × معدل التعطل × (مرات الظهور لكل جلسة – مرات الظهور قبل التعطل) × eCPM ÷ 1000. لكن النتيجة تصبح مقلقة عندما تُدخل أرقامًا واقعية.
- مليون DAU × معدل تعطل 1.5% × 1.6 ظهور مفقود × eCPM بقيمة 6 دولارات ≈ 144 دولارًا يوميًا، و52 ألف دولار سنويًا
- 5 ملايين DAU × معدل تعطل 1.0% × 1.6 ظهور مفقود × eCPM بقيمة 7 دولارات ≈ 560 دولارًا يوميًا، و204 آلاف دولار سنويًا
- 25 مليون DAU × معدل تعطل 0.6% × 1.6 ظهور مفقود × eCPM بقيمة 8 دولارات ≈ 1,920 دولارًا يوميًا، و700 ألف دولار سنويًا
- وهذه الأرقام تحتسب مرات الظهور المفقودة فقط، ولا تشمل أثر تراجع الاحتفاظ بالمستخدمين، الذي يكون عادةً أكبر
حالات ANR أعطال أشد ضررًا على تحقيق الدخل
حالة عدم استجابة التطبيق (ANR) على Android هي القاتل الصامت. يرى المستخدم واجهة متجمدة، فيغلق التطبيق قسريًا ثم يزيله، لكن لا يُرسل أي تقرير تعطل، فلا يراها الفريق الذي يتابع Crashlytics. ومن الشائع أن تتجاوز نسبة حالات ANR مستوى 0.5% في التطبيقات التي تُهيّئ SDK الإعلانات على خيط التنفيذ الرئيسي.
ويقابلها على iOS إنهاء التطبيق بواسطة آلية المراقبة (watchdog)، مع رمز خروج 0x8badf00d. وينتج ذلك غالبًا عن السبب الجذري نفسه: تنفيذ عمليات متزامنة على خيط التنفيذ الرئيسي أثناء بدء التشغيل. تعامل مع الحالتين كما تتعامل مع الأعطال: فعّل التنبيهات لهما، واحسب خسارة الإيرادات بالنموذج نفسه، واجعل اجتياز فحوصهما شرطًا لطرح كل إصدار.
أنماط برمجة وقائية لكل منصة
هذه هي الأنماط التي نعتمدها افتراضيًا في كل عملية دمج لـ Apps Kit SDK. لا يتطلب أي منها حيلًا برمجية. ومع ذلك، تغيب جميعها عن معظم قواعد الشيفرة التي نراجعها.
- Android: هيّئ SDK من خلال مهمة WorkManager، وليس داخل Application.onCreate
- Android: احتفظ بعناصر عرض الإعلانات داخل WeakReference، واضبط مراجعها على null في onDestroyView
- iOS: أرسل مهمة تهيئة SDK إلى طابور تنفيذ بمستوى utility ضمن QoS من داخل didFinishLaunching، ولا تحجب خيط التنفيذ أبدًا
- iOS: ألغِ تفعيل مفوّضي الإعلانات (delegates) وفكّ دورات الاحتفاظ بالمراجع في viewWillDisappear، وليس في deinit
- على المنصتين: مرّر كل طلب إعلان عبر آلة حالات تتحقق من حالة موافقة المستخدم، والاتصال بالشبكة، وجاهزية SDK
من أين تأتي الأعطال؟
- تهيئة SDK على خيط التنفيذ الرئيسي، وهي السبب الأكثر شيوعًا الذي نرصده
- تحميل الإعلانات بشكل متزامن داخل onCreate / didFinishLaunching
- الضغط على الذاكرة بسبب الاحتفاظ بعناصر عرض الإعلانات بعد انتهاء الحاجة إليها
- حالات التسابق بين حالة موافقة المستخدم وطلب الإعلان
تنبيهات الأعطال المؤثرة في الإيرادات
عادةً ما تُضبط تنبيهات معدل التعطل على حدّ ثابت للنسبة المئوية، ثم يجري تجاهلها عند صدورها. اربطها بدلًا من ذلك بأثرها على الإيرادات: أرسل تنبيهًا عندما تتجاوز خسارة الإيرادات اليومية المقدّرة لنمط تعطل معيّن مبلغ X دولار. عندها يصبح التنبيه جديرًا بأن يستيقظ المهندس المناوب من أجله. ونوفّر قالب Cloud Function ينفّذ ذلك تحديدًا بالاعتماد على البيانات المصدّرة إلى BigQuery.
النمط الوقائي
هيّئ SDK باستخدام موزّع مهام يعمل في الخلفية، ومرّر كل طلب إعلان عبر آلة حالات لموافقة المستخدم، وحرّر مراجع عناصر عرض الإعلان فور إغلاق موضعه الإعلاني. لا شيء من ذلك جديد. ومع هذا، تغيب هذه الممارسات جميعها عن معظم عمليات الدمج التي نراجعها.
تعامل مع معدل التعطل بوصفه عاملًا مؤثرًا في الإيرادات، لا مجرد مقياس لجودة الممارسات الهندسية، وستختصر كثيرًا النقاش حول إعطاء الأولوية لتحسين الاستقرار.
ما الذي يمكنك فعله هذا الأسبوع؟
افتح لوحة متابعة الأعطال، وطبّق النموذج أعلاه على أكثر ثلاثة أنماط تعطل شيوعًا، ثم دوّن قيمة الخسارة بالدولار بجوار كل منها. الإصدار الذي يعالج النمط الأعلى خسارة سيعوّض تكلفة تطويره قبل إغلاق نافذة المراجعة التالية في App Store.


