من أهم مزايا خدمة العمال (من منظور الأداء على الأقل) هي قدرتها على التحكّم بشكل استباقي في تخزين مواد العرض المؤقت. من المفترض أن يتم تحميل تطبيق الويب الذي يمكنه تخزين جميع موارده الضرورية بشكل أسرع بكثير للزوار المتكررين. ولكن كيف تبدو هذه المكاسب في الواقع للمستخدمين الحقيقيين؟ وكيف يتم قياس ذلك؟
تطبيق الويب Google I/O (يُشار إليه اختصارًا باسم IOWA) هو تطبيق ويب تقدّمي استفاد من معظم الإمكانات الجديدة التي يوفّرها مهام الخدمة لتقديم تجربة غنية تشبه تجربة استخدام التطبيق للمستخدمين. واستخدمت الشركة أيضًا "إحصاءات Google" لتسجيل بيانات الأداء الرئيسية وأنماط الاستخدام من جمهور المستخدمين الكبير والمتنوّع.
تستكشف هذه الدراسة الحالة كيفية استخدام IOWA لخدمة "إحصاءات Google" للإجابة عن أسئلة الأداء الرئيسية وإعداد تقارير عن التأثير الفعلي لعمال الخدمة.
البدء بالأسئلة
في أي وقت تقوم فيه بتنفيذ تحليلات في موقع ويب أو تطبيق، من المهم أن تبدأ بتحديد الأسئلة التي تحاول الإجابة عنها من البيانات التي ستجمعها.
على الرغم من أنّنا أردنا الإجابة عن عدة أسئلة، سنركّز في هذه الدراسة على سؤالَين من أكثر الأسئلة إثارة للاهتمام.
1. هل يحقّق التخزين المؤقت لعامل الخدمة أداءً أفضل من آليات التخزين المؤقت الحالية لبروتوكول HTTP المتوفّرة في جميع المتصفّحات؟
نتوقع أن يتم تحميل الصفحات بشكل أسرع للزوار المتكررين مقارنةً بالزوار الجدد، لأنّ المتصفحات يمكنها تخزين الطلبات مؤقتًا وعرضها على الفور عند تكرار الزيارات.
توفّر مشغّلات الخدمات إمكانات ذاكرة تخزين مؤقت بديلة تمنح المطوّرين إمكانية التحكّم بشكل دقيق في ما يتم تخزينه مؤقتًا وكيفية تخزينه. في آيوا، حسّنا عملية تنفيذ الخدمة العاملة لكي يتم تخزين كل مادة عرض مؤقتًا، ما يتيح للزوّار المتكرّرين استخدام التطبيق بلا اتصال بالإنترنت تمامًا.
ولكن هل سيكون هذا الجهد أفضل مما يفعله المتصفّح حاليًا بشكلٍ تلقائي؟ وإذا كان الأمر كذلك، ما هو مقدار التحسين؟ 1
2- كيف يؤثر موظّف الخدمة في تجربة تحميل الموقع الإلكتروني؟
بعبارة أخرى، ما مدى سرعة الشعور بأنّ الموقع الإلكتروني يتم تحميله، بغض النظر عن مدد التحميل الفعلية كما يتم قياسها من خلال مقاييس تحميل الصفحة التقليدية؟
من الواضح أنّ الإجابة عن أسئلة حول شعورك بالتجربة ليست مهمة سهلة، ولن يمثّل أي مقياس هذا الشعور الذاتي بشكلٍ كامل. ومع ذلك، هناك بالتأكيد بعض المقاييس التي تُعدّ أفضل من غيرها، لذا من المهم اختيار المقاييس المناسبة.
اختيار المقياس الصحيح
تتتبّع "إحصاءات Google" تلقائيًا أوقات تحميل الصفحات (من خلال Navigation Timing API) لنسبة% 1 من زوّار الموقع الإلكتروني، وتوفّر هذه البيانات من خلال مقاييس مثل "متوسط وقت تحميل الصفحة".
متوسط وقت تحميل الصفحة هو مقياس جيد للإجابة عن سؤالنا الأول، ولكنه ليس مقياسًا جيدًا بشكل خاص للإجابة عن السؤال الثاني. على سبيل المثال، لا يتطابق حدث load
بالضرورة مع اللحظة التي يمكن فيها للمستخدم التفاعل مع التطبيق. بالإضافة إلى ذلك، قد يبدو أنّ وقت تحميل تطبيقَين متطابقَين تمامًا يختلف كثيرًا. على سبيل المثال، إذا كان الموقع الإلكتروني يعرض شاشة بداية أو مؤشر تحميل، يبدو أنّه يتم تحميله بسرعة أكبر بكثير مقارنةً بالموقع الذي لا يعرض سوى صفحة فارغة لعدة ثوانٍ.
في IOWA، عرضنا صورة متحركة للعد التنازلي على شاشة البداية، وقد نجحت (في رأيي) في تسلية المستخدم بينما يتم تحميل باقي التطبيق في الخلفية. ولهذا السبب، يبدو تتبُّع الوقت الذي تستغرقه شاشة البداية للظهور منطقيًا أكثر كطريقة لقياس أداء التحميل الذي يتم رصده. اخترنا المقياس الوقت المستغرَق لعرض اللوحة الأولى للحصول على هذه القيمة.
بعد أن قرّرنا الأسئلة التي أردنا الإجابة عنها وتحديد المقاييس التي ستكون مفيدة في الإجابة عنها، حان الوقت لبدء استخدام "إحصاءات Google" وبدء القياس.
تنفيذ التحليلات
إذا كنت قد استخدمت "إحصاءات Google" من قبل، فمن المحتمل أن تكون على دراية بمقتطف تتبُّع JavaScript الذي يُنصح به. يظهر الإجراء على النحو التالي:
<script>
window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
ga('create', 'UA-XXXXX-Y', 'auto');
ga('send', 'pageview');
</script>
<script async src="https://www.google-analytics.com/analytics.js"></script>
يعمل السطر الأول في الرمز البرمجي أعلاه على إعداد دالة ga()
عالمية (إذا لم تكن متوفّرة)، وينزِّل السطر الأخير مكتبة analytics.js
بشكل غير متزامن.
يحتوي الجزء الأوسط على السطرَين التاليَين:
ga('create', 'UA-XXXXX-Y', 'auto');
ga('send', 'pageview');
يتتبّع هذان الأمران الصفحات التي زارها الأشخاص الذين يزورون موقعك الإلكتروني، ولكن ليس أكثر. إذا كنت تريد تتبُّع تفاعلات إضافية للمستخدمين، عليك إجراء ذلك بنفسك.
بالنسبة إلى IOWA، أردنا تتبُّع شيئَين إضافيَين:
- الوقت المنقضي بين وقت بدء تحميل الصفحة لأول مرة ووقت ظهور وحدات البكسل على الشاشة.
- ما إذا كان مشغّل الخدمات يتحكّم في الصفحة أم لا باستخدام هذه المعلومات، يمكننا تقسيم تقاريرنا لمقارنة النتائج مع وبدون "عامل الخدمة".
جارٍ تسجيل الوقت اللازم لطلاء المنتج لأول مرة
تسجِّل بعض المتصفّحات الوقت الدقيق الذي يتم فيه عرض أول بكسل على الشاشة، وتوفّر هذا الوقت للمطوّرين. وتوفّر لنا هذه القيمة، مقارنةً بقيمة navigationStart
المعروضة من خلال Navigation Timing API، حسابًا دقيقًا جدًا للوقت الذي مضى بين طلب المستخدم للصفحة في البداية ووقت ظهور محتوى معيّن لأول مرة.
كما سبق وذكرنا، فإنّ "وقت عرض أول بكسل" هو مقياس مهم يجب قياسه لأنّه يمثّل أول نقطة يلاحظ فيها المستخدم سرعة تحميل موقعك الإلكتروني. إنّه الانطباع الأول الذي يحصل عليه المستخدمون، ويمكن أن يؤثّر الانطباع الأول الجيد بشكل إيجابي في بقية تجربة المستخدم.2
للحصول على قيمة الطلاء الأولى في المتصفّحات التي تعرضها، أنشأنا دالة المساعدة getTimeToFirstPaintIfSupported
:
function getTimeToFirstPaintIfSupported() {
// Ignores browsers that don't support the Performance Timing API.
if (window.performance && window.performance.timing) {
var navTiming = window.performance.timing;
var navStart = navTiming.navigationStart;
var fpTime;
// If chrome, get first paint time from `chrome.loadTimes`.
if (window.chrome && window.chrome.loadTimes) {
fpTime = window.chrome.loadTimes().firstPaintTime * 1000;
}
// If IE/Edge, use the prefixed `msFirstPaint` property.
// See http://msdn.microsoft.com/ff974719
else if (navTiming.msFirstPaint) {
fpTime = navTiming.msFirstPaint;
}
if (fpTime && navStart) {
return fpTime - navStart;
}
}
}
باستخدام ذلك، يمكننا الآن كتابة دالة أخرى تُرسِل حدث عدم تفاعل مع تحديد وقت الرسم الأول كقيمة له:3
function sendTimeToFirstPaint() {
var timeToFirstPaint = getTimeToFirstPaintIfSupported();
if (timeToFirstPaint) {
ga('send', 'event', {
eventCategory: 'Performance',
eventAction: 'firstpaint',
// Rounds to the nearest millisecond since
// event values in Google Analytics must be integers.
eventValue: Math.round(timeToFirstPaint)
// Sends this as a non-interaction event,
// so it doesn't affect bounce rate.
nonInteraction: true
});
}
}
بعد كتابة كلتا الدالتَين، سيظهر رمز التتبّع على النحو التالي:
// Creates the tracker object.
ga('create', 'UA-XXXXX-Y', 'auto');
// Sends a pageview for the initial pageload.
ga('send', 'pageview');
// Sends an event with the time to first paint data.
sendTimeToFirstPaint();
يُرجى العلم أنّه استنادًا إلى وقت تشغيل الرمز أعلاه، قد يكون قد تمّ رسم البكسل على الشاشة أو لم يتمّ ذلك. لضمان تشغيل هذا الرمز دائمًا بعد ظهور أول سرعة، أجّلنا الاتصال بـ sendTimeToFirstPaint()
إلى ما بعد حدث load
. في الواقع، قررنا تأجيل إرسال جميع بيانات الإحصاءات إلى أن يتم تحميل الصفحة لضمان عدم تنافس هذه الطلبات مع تحميل الموارد الأخرى.
// Creates the tracker object.
ga('create', 'UA-XXXXX-Y', 'auto');
// Postpones sending any hits until after the page has fully loaded.
// This prevents analytics requests from delaying the loading of the page.
window.addEventListener('load', function() {
// Sends a pageview for the initial pageload.
ga('send', 'pageview');
// Sends an event with the time to first paint data.
sendTimeToFirstPaint();
});
يُبلغ الرمز أعلاه عن firstpaint
مرة إلى "إحصاءات Google"، ولكنّ هذا ليس سوى نصف القصة. كان لا يزال علينا تتبُّع حالة مشغّل الخدمات، وإلا لن نتمكّن من مقارنة أوقات الرسم الأولى لصفحة يتحكم فيها مشغّل خدمات وصفح غير خاضعة للتحكم.
تحديد حالة عامل الخدمة
لتحديد الحالة الحالية لخدمة Worker، أنشأنا دالة مساعدة تعرض إحدى القيم الثلاث التالية:
- تتم إدارتها: يتحكّم مشغّل خدمات في الصفحة. في ما يتعلّق بـ IOWA، يعني ذلك أيضًا أنّه تم تخزين جميع مواد العرض في ذاكرة التخزين المؤقت وأنّ الصفحة تعمل بلا اتصال بالإنترنت.
- متوافق: يدعم المتصفح عامل الخدمة، ولكن عامل الخدمة لا يتحكم في الصفحة بعد. هذه هي الحالة المتوقّعة للزائرين لأول مرة.
- غير متوافق: لا يتيح متصفّح المستخدم استخدام الخدمة العاملة.
function getServiceWorkerStatus() {
if ('serviceWorker' in navigator) {
return navigator.serviceWorker.controller ? 'controlled' : 'supported';
} else {
return 'unsupported';
}
}
حصلت هذه الدالة على حالة عامل الخدمة، وكانت الخطوة التالية هي ربط هذه الحالة بالبيانات التي نرسلها إلى "إحصاءات Google".
تتبُّع البيانات المخصّصة باستخدام السمات المخصّصة
تقدّم لك "إحصاءات Google" تلقائيًا العديد من الطرق لتقسيم إجمالي عدد الزيارات إلى مجموعات استنادًا إلى سمات المستخدِم أو الجلسة أو التفاعل. تُعرف هذه السمات باسم السمات. تشمل السمات الشائعة التي يهتم بها مطوّرو الويب المتصفّح أو نظام التشغيل أو فئة الجهاز.
إنّ حالة عامل الخدمة ليست سمة تقدّمها "إحصاءات Google" تلقائيًا، ولكنّ "إحصاءات Google" تمنحك إمكانية إنشاء سمات مخصّصة وتحديدها كيفما تريد.
بالنسبة إلى IOWA، أنشأنا سمة مخصّصة تُسمى حالة الخدمة وضبطنا نطاقها على النتيجة (أي لكلّ تفاعل).4 تحصل كلّ سمة مخصّصة تنشئها في "إحصاءات Google" على فهرس فريد ضمن هذا الموقع، ويمكنك الإشارة إلى هذه السمة في رمز التتبّع حسب فهرسها. على سبيل المثال، إذا كان فهرس البُعد الذي أنشأناه للتو يساوي 1، يمكننا تعديل منطقنا على النحو التالي لإرسال حدث firstpaint
لتضمين حالة مشغّل الخدمات:
ga('send', 'event', {
eventCategory: 'Performance',
eventAction: 'firstpaint',
// Rounds to the nearest millisecond since
// event values in Google Analytics must be integers.
eventValue: Math.round(timeToFirstPaint)
// Sends this as a non-interaction event,
// so it doesn't affect bounce rate.
nonInteraction: true,
// Sets the current service worker status as the value of
// `dimension1` for this event.
dimension1: getServiceWorkerStatus()
});
يعمل هذا الإجراء، ولكنّه لن يربط حالة عامل الخدمة إلا بهذا الحدث المحدّد. بما أنّ حالة مشغّل الخدمات هي معلومات قد يكون من المفيد معرفتها في أي تفاعل، لذا من الأفضل تضمينها مع جميع البيانات المرسلة إلى "إحصاءات Google".
لتضمين هذه المعلومات في جميع النتائج (مثل جميع مشاهدات الصفحة والأحداث وما إلى ذلك)، نُجري عملية ضبط لقيمة السمة المخصّصة في عنصر التتبُّع نفسه، قبل إرسال أي بيانات إلى "إحصاءات Google".
ga('set', 'dimension1', getServiceWorkerStatus());
وبعد الضبط، يتم إرسال هذه القيمة مع جميع النتائج اللاحقة لتحميل الصفحة الحالي. إذا حمّل المستخدم الصفحة مرة أخرى لاحقًا، من المرجّح أن يتم عرض قيمة جديدة من الدالة getServiceWorkerStatus()
، وسيتم ضبط هذه القيمة على عنصر التتبُّع.
ملاحظة سريعة حول وضوح الرمز وسهولة قراءته: بما أنّ المستخدمين الآخرين الذين ينظرون إلى هذا الرمز قد لا يعرفون ما يشير إليه الرمز dimension1
، من الأفضل دائمًا إنشاء متغيّر يربط أسماء السمات ذات المعنى بالقيم التي ستستخدمها analytics.js.
// Creates a map between custom dimension names and their index.
// This is particularly useful if you define lots of custom dimensions.
var customDimensions = {
SERVICE_WORKER_STATUS: 'dimension1'
};
// Creates the tracker object.
ga('create', 'UA-XXXXX-Y', 'auto');
// Sets the service worker status on the tracker,
// so its value is included in all future hits.
ga('set', customDimensions.SERVICE_WORKER_STATUS, getServiceWorkerStatus());
// Postpones sending any hits until after the page has fully loaded.
// This prevents analytics requests from delaying the loading of the page.
window.addEventListener('load', function() {
// Sends a pageview for the initial pageload.
ga('send', 'pageview');
// Sends an event with the time to first paint data.
sendTimeToFirstPaint();
});
كما ذكرت سابقًا، يسمح لنا إرسال سمة حالة الخدمة العاملة مع كل نتيجة باستخدامها عند إعداد تقارير عن أي مقياس.
كما هو موضّح، تشكّل المتصفّحات التي تتوافق مع مهام الخدمة نسبة% 85 تقريبًا من جميع مشاهدات الصفحة في آيوا.
النتائج: الإجابة عن أسئلتنا
بعد أن بدأنا بجمع البيانات للإجابة عن أسئلتنا، أصبح بإمكاننا إعداد تقارير عن هذه البيانات للاطّلاع على النتائج. (ملاحظة: جميع بيانات "إحصاءات Google" المعروضة هنا تمثّل عدد الزيارات الفعلية إلى موقع IOWA الإلكتروني في الفترة من 16 إلى 22 أيار (مايو) 2016).
كان السؤال الأول الذي طرحناه هو: هل يؤدي ذاكرة التخزين المؤقت لعامل الخدمة إلى أداء أفضل من آليات التخزين المؤقت الحالية لبروتوكول HTTP المتوفّرة في جميع المتصفّحات؟
للإجابة عن هذا السؤال، أنشأنا تقريرًا مخصّصًا يعرض المقياس متوسط أوقات تحميل الصفحات على مستوى سمات مختلفة. هذا المقياس مناسب تمامًا للإجابة عن هذا السؤال لأنّ الحدث load
لا يتم تشغيله إلا بعد تنزيل جميع الموارد الأولية. وبالتالي، يعكس هذا المقياس مباشرةً إجمالي وقت التحميل لجميع الموارد المهمة للموقع الإلكتروني.5
كانت السمات التي اخترناها هي:
- سمة حالة الخدمة المخصّصة
- نوع المستخدِم، الذي يشير إلى ما إذا كانت هذه هي الزيارة الأولى للمستخدِم إلى الموقع الإلكتروني أو ما إذا كان يعود إليه. (ملاحظة: لن يتم تخزين أي موارد في ذاكرة التخزين المؤقت للزائر الجديد، ولكن قد يتم تخزينها للزائر المتكرر).
- فئة الجهاز، التي تتيح لنا مقارنة النتائج على الأجهزة الجوّالة وأجهزة الكمبيوتر المكتبي
للتأكّد من أنّ النتائج التي نحصل عليها عن وقت التحميل ليست متأثرة بعوامل غير متعلّقة بعامل الخدمة، اقتصرنا في طلب البحث على تضمين المتصفّحات التي تتيح استخدام عامل الخدمة.
كما ترى، كانت زيارات تطبيقنا التي يتم التحكّم فيها من خلال مشغّل خدمات أسرع بكثير من الزيارات غير الخاضعة للتحكّم، حتى تلك التي أجراها المستخدمون المتكرّرون الذين من المحتمل أن يكونوا قد خزّنوا معظم موارد الصفحة. من المثير للاهتمام أيضًا ملاحظة أنّ الزائرين على الأجهزة الجوّالة الذين يستخدمون الخدمة العاملة حقّقوا في المتوسّط عمليات تحميل أسرع من الزائرين الجدد على أجهزة الكمبيوتر المكتبي.
"…كانت زيارات تطبيقنا التي يتم التحكّم فيها من خلال مشغّل خدمات يتم تحميلها بشكل أسرع بكثير من الزيارات التي لا يتم التحكّم فيها…"
يمكنك الاطّلاع على مزيد من التفاصيل في الجدولَين التاليَين:
متوسّط وقت تحميل الصفحة (أجهزة الكمبيوتر المكتبي) | |||
---|---|---|---|
حالة مشغّل الخدمات | نوع المستخدِم | متوسط وقت تحميل الصفحة (بالميلي ثانية) | حجم العيّنة |
تم التحكم فيه | الزائر مكرر الزيارة | 2568 | 30860 |
معلومات معتمَدة | الزائر مكرر الزيارة | 3612 | 1289 |
معلومات معتمَدة | زائر جديد | 4664 | 21991 |
متوسط وقت تحميل الصفحة (الأجهزة الجوّالة) | |||
---|---|---|---|
حالة مشغّل الخدمات | نوع المستخدِم | متوسط وقت تحميل الصفحة (بالميلي ثانية) | حجم العيّنة |
تم التحكم فيه | الزائر مكرر الزيارة | 3760 | 8162 |
معلومات معتمَدة | الزائر مكرر الزيارة | 4843 | 676 |
معلومات معتمَدة | زائر جديد | 6158 | 5779 |
قد تتساءل كيف يمكن أن يكون الزائر المتكرّر الذي يتوفّر في متصفّحه مشغّل خدمات في حالة غير خاضعة للرقابة. هناك بضعة أسباب محتملة لذلك:
- غادر المستخدم الصفحة في الزيارة الأولى قبل أن يتمكن مشغّل الخدمة من إكمال عملية الإعداد.
- ألغى المستخدم تثبيت الخدمة العاملة من خلال أدوات المطوّرين.
إنّ كلا الحالتَين نادرتَان نسبيًا. يمكننا الاطّلاع على ذلك في البيانات من خلال الاطّلاع على قيم عيّنة تحميل الصفحة في العمود الرابع. لاحظ أنّ الصفوف الوسطى تحتوي على عيّنة أصغر بكثير من الصفوف الأخرى.
كان سؤالنا الثاني: كيف يؤثر موظّف الخدمة في تجربة تحميل الموقع الإلكتروني؟
للإجابة عن هذا السؤال، أنشأنا تقريرًا مخصّصًا آخر للمقياس متوسط قيمة الحدث وفلترَنا النتائج لتضمين أحداث firstpaint
فقط. لقد استخدمنا السمتَين فئة الجهاز والسمة المخصّصة حالة الخدمة العاملة.
على عكس ما كنت أتوقعه، كان لعامل الخدمة على الأجهزة الجوّالة تأثير أقل بكثير في وقت عرض اللوحة الأولى مقارنةً بتأثيره في إجمالي وقت تحميل الصفحة.
"...كان تأثير عامل الخدمة على الأجهزة الجوّالة في وقت عرض محتوى الصفحة أقل بكثير من تأثيره في إجمالي تحميل الصفحة".
لمعرفة سبب ذلك، علينا التعمّق في البيانات. يمكن أن تكون المتوسطات مفيدة للنظرة العامة العامة والضربات الواسعة، ولكن لمعرفة كيفية تقسيم هذه الأرقام على مستوى مجموعة من المستخدمين، نحتاج إلى الاطّلاع على توزيع firstpaint
مرة.
الحصول على توزيع مقياس في "إحصاءات Google"
للحصول على توزيع firstpaint
مرة، نحتاج إلى الوصول إلى النتائج الفردية لكل حدث. لا تسهّل "إحصاءات Google" إجراء ذلك.
تتيح لنا خدمة "إحصاءات Google" تقسيم أي تقرير حسب المكوّن الذي نريده، ولكنها لا تسمح باستخدام هذا التقرير حسب المقاييس. لا يعني ذلك أنّه مستحيل، بل يعني فقط أنّنا اضطررنا إلى تخصيص عملية التنفيذ قليلاً للحصول على النتيجة المطلوبة.
بما أنّه لا يمكن تقسيم نتائج التقرير إلا حسب السمات، كان علينا ضبط قيمة المقياس (في هذه الحالة firstpaint
time) كسمة مخصّصة للحدث. لإجراء ذلك، أنشأنا سمة مخصّصة أخرى تُسمى قيمة المقياس وعدّلنا منطق تتبُّع firstpaint
على النحو التالي:
var customDimensions = {
SERVICE_WORKER_STATUS: 'dimension1',
<strong>METRIC_VALUE: 'dimension2'</strong>
};
// ...
function sendTimeToFirstPaint() {
var timeToFirstPaint = getTimeToFirstPaintIfSupported();
if (timeToFirstPaint) {
var fields = {
eventCategory: 'Performance',
eventAction: 'firstpaint',
// Rounds to the nearest millisecond since
// event values in Google Analytics must be integers.
eventValue: Math.round(timeToFirstPaint)
// Sends this as a non-interaction event,
// so it doesn't affect bounce rate.
nonInteraction: true
}
<strong>// Sets the event value as a dimension to allow for breaking down the
// results by individual metric values at reporting time.
fields[customDimensions.METRIC_VALUE] = String(fields.eventValue);</strong>
ga('send', 'event', fields);
}
}
لا توفّر واجهة الويب في "إحصاءات Google" حاليًا طريقة لعرض توزيع قيم المقاييس التعسّفية، ولكن بمساعدة Google Analytics Core Reporting API ومكتبة Google Charts، يمكننا البحث عن النتائج الأوّلية ثم إنشاء رسم بياني هرمي أنفسنا.
على سبيل المثال، تم استخدام الإعدادات التالية لطلب واجهة برمجة التطبيقات للحصول على توزيع قيم firstpaint
على أجهزة الكمبيوتر المكتبي باستخدام عامل خدمة غير خاضع للرقابة.
{
dateRanges: [{startDate: '2016-05-16', endDate: '2016-05-22'}],
metrics: [{expression: 'ga:totalEvents'}],
dimensions: [{name: 'ga:dimension2'}],
dimensionFilterClauses: [
{
operator: 'AND',
filters: [
{
dimensionName: 'ga:eventAction',
operator: 'EXACT',
expressions: ['firstpaint']
},
{
dimensionName: 'ga:dimension1',
operator: 'EXACT',
expressions: ['supported']
},
{
dimensionName: 'ga:deviceCategory',
operator: 'EXACT',
expressions: ['desktop']
}
],
}
],
orderBys: [
{
fieldName: 'ga:dimension2',
orderType: 'DIMENSION_AS_INTEGER'
}
]
}
يعرض طلب واجهة برمجة التطبيقات هذا صفيفًا من القيم التي تبدو على النحو التالي (ملاحظة: هذه هي النتائج الخمس الأولى فقط). يتم فرز النتائج من الأصغر إلى الأكبر، لذا فإن هذه الصفوف تمثل أسرع الأوقات.
نتائج ردّ واجهة برمجة التطبيقات (الصفوف الخمسة الأولى) | |
---|---|
ga:dimension2 | ga:totalEvents |
4 | 3 |
5 | 2 |
6 | 10 |
7 | 8 |
8 | 10 |
في ما يلي معنى هذه النتائج باللغة العربية:
- كان هناك 3 أحداث كانت قيمة
firstpaint
فيها 4 ملي ثانية. - حدثَ حدثان كانت فيهما قيمة
firstpaint
هي 5 ملي ثانية - كان هناك 10 أحداث كانت قيمة
firstpaint
فيها 6 ملي ثانية. - كان هناك 8 أحداث كانت قيمة
firstpaint
فيها 7 ملي ثانية. - حدثت 10 أحداث كان فيها
firstpaint
value
8 ملي ثانية - إلخ
من هذه النتائج، يمكننا استنتاج قيمة firstpaint
لكل حدث فردي وإنشاء رسم بياني شريطي للتوزيع. وقد أجرينا ذلك لكل طلب بحث أجريناه.
وفي ما يلي شكل التوزيع على أجهزة الكمبيوتر المكتبي مع مشغّل خدمات غير متحكّم (ولكنه متوافق):
متوسّط وقت firstpaint
للتوزيع أعلاه هو 912 ملي ثانية.
إنّ شكل هذا المنحنى شائع جدًا في توزيعات وقت التحميل. قارِن ذلك بالمخطّط التكراري أدناه الذي يعرض توزيع أحداث العرض الأول للزيارات التي كان فيها عامل خدمة يتحكّم في الصفحة.
يُرجى العلم أنّه عندما كان مشغّل الخدمات يتحكّم في الصفحة، شهد العديد من الزوّار ظهور العناصر الأولى على الشاشة بشكلٍ شبه فوري، بمتوسط 583 ملي ثانية.
"…عندما كان أحد مشغّلي الخدمات يتحكّم في الصفحة، لاحظ العديد من الزوّار ظهور المحتوى الأول على الشاشة بشكل شبه فوري…"
للحصول على فكرة أفضل عن مستوى مقارنة هذين التوزيعَين ببعضهما، يعرض الرسم البياني التالي عرضًا مدمجًا للتوزيعَين. يتمّ وضع المخطّط البياني التكراري الذي يعرض زيارات عمال الخدمة غير الخاضعة للتحكّم فوق المخطّط البياني التكراري الذي يعرض الزيارات الخاضعة للتحكّم، ويتمّ وضع كليهما فوق مخطّط بياني تكراري يعرض كليهما معًا.
من بين الأمور المثيرة للاهتمام في هذه النتائج أنّ التوزيع الذي يتضمّن عامل خدمة خاضعًا للرقابة لا يزال يتضمّن منحنى على شكل جرس بعد الارتفاع المفاجئ الأولي. كنت أتوقع ارتفاعًا كبيرًا في البداية ثم انخفاضًا تدريجيًا، ولم أكن أتوقع ارتفاعًا ثانيًا في المنحنى.
عندما نظرت في سبب ذلك، علمت أنّه على الرغم من أنّ عامل الخدمة يتحكّم في صفحة ما، قد تكون سلسلة المحادثات غير نشطة. يفعل المتصفّح ذلك لتوفير الموارد، فمن الواضح أنّك لا تحتاج إلى كلّ عامل خدمة لكلّ موقع إلكتروني زرته من قبل ليكون نشطًا وجاهزًا في أيّ وقت. يوضّح ذلك أطراف التوزيع. بالنسبة إلى بعض المستخدمين، حدث تأخير أثناء بدء سلسلة مهام الخدمة.
وكما هو واضح من التوزيع، حتى مع هذا التأخير الأولي، أظهرت المتصفّحات التي تستخدم مهام الخدمة سرعة أكبر في عرض المحتوى مقارنةً بالمتصفّحات التي تتصل بالشبكة.
في ما يلي كيفية ظهور المحتوى على الأجهزة الجوّالة:
بينما لا تزال لدينا زيادة كبيرة في أوقات الطلاء الأولى شبه الفورية، كان الذيل أكبر وأطول قليلاً. ويعود السبب في ذلك على الأرجح إلى أنّ بدء سلسلة محادثات عامل الخدمة غير النشط يستغرق وقتًا أطول على الأجهزة الجوّالة مقارنةً بأجهزة الكمبيوتر المكتبي. ويوضّح ذلك أيضًا سبب عدم اختلاف متوسط وقت firstpaint
كثيرًا عن ما كنت أتوقعه (كما هو موضّح أعلاه).
"…على الأجهزة الجوّالة، يستغرق بدء سلسلة مهام عامل الخدمة غير النشط وقتًا أطول مما يستغرقه على أجهزة الكمبيوتر المكتبي".
في ما يلي تفاصيل هذه الاختلافات لمتوسط وقت عرض الإعلانات على الأجهزة الجوّالة والكمبيوتر المكتبي مجمّعة حسب حالة مشغّل الخدمات:
متوسّط مدّة عرض الصفحة (بالملّي ثانية) | ||
---|---|---|
حالة مشغّل الخدمات | أجهزة الكمبيوتر المكتبية | الجهاز الجوّال |
تم التحكم فيه | 583 | 1634 |
متوفّرة (غير خاضعة للرقابة) | 912 | 1933 |
على الرغم من أنّ إنشاء الرسومات البيانية للتوزيع هذه استغرق وقتًا وجهدًا أكبر قليلاً من إنشاء تقرير مخصّص في "إحصاءات Google"، إلا أنّها تمنحنا فكرة أفضل بكثير عن مدى تأثير مهام الخدمة في أداء موقعنا الإلكتروني مقارنةً بالمتوسّطات وحدها.
تأثير آخر لمشغّلي الخدمات
بالإضافة إلى تأثير الأداء، يؤثر عاملو الخدمة أيضًا في تجربة المستخدم بعدة طرق أخرى قابلة للقياس باستخدام "إحصاءات Google".
الوصول إلى المحتوى بلا إنترنت
تسمح مشغّلات الخدمات للمستخدمين بالتفاعل مع موقعك الإلكتروني بلا إنترنت، ومع أنّ توفير نوع من الدعم بلا إنترنت قد يكون أمرًا بالغ الأهمية لأي تطبيق ويب تدريجي، يعتمد تحديد مدى أهميته في حالتك إلى حد كبير على مقدار الاستخدام بلا إنترنت. ولكن كيف نقيس ذلك؟
يتطلب إرسال البيانات إلى "إحصاءات Google" اتصالاً بالإنترنت، ولكنه لا يتطلب إرسال البيانات في الوقت المحدّد الذي حدث فيه التفاعل. تتيح "إحصاءات Google" إرسال بيانات التفاعل بعد حدوثها من خلال تحديد تقدّم زمني (من خلال المَعلمة qt
).
على مدار العامَين الماضيَين، استخدمت شركة IOWA نصّ برمجي لعامل الخدمة يرصد النتائج غير الناجحة التي تصل إلى "إحصاءات Google" عندما يكون المستخدم غير متصل بالإنترنت ويعيد تشغيلها لاحقًا باستخدام المَعلمة qt
.
لتتبُّع ما إذا كان المستخدِم متصلاً بالإنترنت أم لا، أنشأنا سمة مخصّصة باسم على الإنترنت وضبطناها على القيمة navigator.onLine
، ثمّ استمعنا إلى حدثَي online
وoffline
وعدّلنا السمة وفقًا لذلك.
وللتعرّف على مدى شيوع استخدام المستخدمين لتطبيق IOWA بلا إنترنت، أنشأنا شريحة استهدفت المستخدمين الذين أجروا تفاعلًا واحدًا على الأقل بلا إنترنت. تبيّن أنّ هذه النسبة تبلغ 5% تقريبًا من المستخدمين.
الإشعارات الفورية
يتيح مشغّلو الخدمات للمستخدمين إمكانية تلقّي إشعارات فورية. في آيوا، تم إشعار المستخدمين عند اقتراب موعد بدء جلسة في جدولهم الزمني.
كما هو الحال مع أي شكل من الإشعارات، من المهم إيجاد التوازن بين تقديم قيمة للمستخدم وإزعاجه. لفهم ما يحدث بشكل أفضل، من المهم تتبُّع ما إذا كان المستخدمون يوافقون على تلقّي هذه الإشعارات، وما إذا كانوا يتفاعلون معها عند وصولها، وما إذا كان أي مستخدمين وافقوا في السابق على تلقّيها يغيّرون إعداداتهم المفضّلة ويوقفون تلقّيها.
في أيوا، لم نرسل سوى إشعارات متعلّقة بالجدول الزمني المخصّص للمستخدم، وهو أمر لا يمكن إنشاؤه إلا للمستخدمين الذين سجّلوا الدخول. وقد أدّى ذلك إلى حصر مجموعة المستخدمين الذين يمكنهم تلقّي الإشعارات بالمستخدمين الذين سجّلوا الدخول (يتم تتبُّعهم من خلال سمة مخصّصة تُسمى تم تسجيل الدخول) الذين تتيح متصفّحاتهم الإشعارات الفورية (يتم تتبُّعهم من خلال سمة مخصّصة أخرى تُسمى إذن الإشعار).
يستند التقرير التالي إلى المقياس المستخدِمون والسمة المخصّصة "إذن الإشعارات"، مقسّمة حسب المستخدِمين الذين سجّلوا الدخول في وقت معيّن ومتصفّحاتهم تتيح الإشعارات الفورية.
يسرّنا معرفة أنّ أكثر من نصف المستخدمين الذين سجّلوا الدخول فعّلوا تلقّي الإشعارات الفورية.
إعلانات البانر لعمليات تثبيت التطبيقات
إذا كان تطبيق ويب تقدّمي يستوفي المعايير ويستخدمه المستخدم بشكل متكرّر، قد يظهر له بانر لتثبيت التطبيق يطلب منه إضافة التطبيق إلى الشاشة الرئيسية.
في IOWA، تم تتبُّع عدد مرات ظهور هذه الطلبات للمستخدم (وما إذا تم قبولها) باستخدام الرمز التالي:
window.addEventListener('beforeinstallprompt', function(event) {
// Tracks that the user saw a prompt.
ga('send', 'event', {
eventCategory: 'installprompt',
eventAction: 'fired'
});
event.userChoice.then(function(choiceResult) {
// Tracks the users choice.
ga('send', 'event', {
eventCategory: 'installprompt',
// `choiceResult.outcome` will be 'accepted' or 'dismissed'.
eventAction: choiceResult.outcome,
// `choiceResult.platform` will be 'web' or 'android' if the prompt was
// accepted, or '' if the prompt was dismissed.
eventLabel: choiceResult.platform
});
});
});
من بين المستخدمين الذين شاهدوا بانر تثبيت التطبيق، اختار حوالي% 10 إضافته إلى الشاشة الرئيسية.
تحسينات التتبّع المحتمَلة (للمرّة القادمة)
كانت بيانات الإحصاءات التي جمعناها من IOWA هذا العام قيّمة للغاية. ولكنّ النظرة إلى الوراء تُظهر دائمًا الثغرات وفرص تحسين الأداء في المرة القادمة. بعد الانتهاء من تحليل هذا العام، إليك أمران أتمنى أن نكون قد نفّذناهما بشكل مختلف، وهما أمران قد يرغب القرّاء الذين يريدون تنفيذ استراتيجية مشابهة في أخذهما في الاعتبار:
1. تتبُّع المزيد من الأحداث ذات الصلة بتجربة التحميل
لقد تتبّعنا العديد من الأحداث التي تتوافق مع مقياس فني (مثل HTMLImportsLoaded وWebComponentsReady وما إلى ذلك)، ولكن بما أنّ الكثير من عمليات التحميل تمّت بشكل غير متزامن، لم تكن النقطة التي تمّ فيها تشغيل هذه الأحداث تتوافق بالضرورة مع لحظة معيّنة في تجربة التحميل العامة.
الحدث الأساسي المرتبط بالتحميل الذي لم نتتبّعه (لكننا نتمنّى أن نكون قد فعلنا ذلك) هو النقطة التي اختفت فيها شاشة البداية وأصبح بإمكان المستخدم رؤية محتوى الصفحة.
2- تخزين معرّف عميل "إحصاءات Google" في IndexedDB
يخزِّن ملف analytics.js تلقائيًا حقل معرّف العميل في ملفات تعريف الارتباط للمتصفّح، ولكن لا يمكن للنصوص البرمجية لمشغّل الخدمات الوصول إلى ملفات تعريف الارتباط.
وقد واجهنا مشكلة عند محاولة تنفيذ ميزة تتبُّع الإشعارات. أردنا إرسال حدث من الخدمة العاملة (من خلال Measurement Protocol) في كل مرة يتم فيها إرسال إشعار إلى المستخدم، ثم تتبُّع نجاح إعادة التفاعل مع هذا الإشعار إذا نقر عليه المستخدم وعاد إلى التطبيق.
على الرغم من أنّنا تمكّنا من تتبُّع نجاح الإشعارات بشكل عام من خلال utm_source
مَعلمة الحملة، لم نتمكّن من ربط جلسة إعادة التفاعل مع مستخدم معيّن.
ما كان بإمكاننا فعله للتغلب على هذا القيد هو تخزين معرّف العميل من خلال IndexedDB في رمز التتبع لدينا، ومن ثم يمكن الوصول إلى هذه القيمة من خلال النص البرمجي لعامل الخدمة.
3. السماح لعامل الخدمة بالإبلاغ عن حالة الاتصال بالإنترنت أو عدم الاتصال بالإنترنت
سيُعلمك فحص navigator.onLine
إذا كان بإمكان المتصفّح الاتصال بجهاز التوجيه أو بشبكة المنطقة المحلية، ولكنّه لن يُعلمك بالضرورة ما إذا كان المستخدم متصلاً فعليًا. وبما أنّ النص البرمجي لعامل تشغيل خدمة التحليلات بلا اتصال بالإنترنت أعاد تشغيل النتائج غير الناجحة (بدون تعديلها أو وضع علامة عليها كـ "تعذّر")، لم نرصد استخدامنا بلا اتصال بالإنترنت بشكل كافٍ.
في المستقبل، يجب تتبُّع حالة navigator.onLine
بالإضافة إلى ما إذا كان مشغّل الخدمة قد أعاد تشغيل النتيجة بسبب خطأ أولي في الشبكة. سيمنحنا ذلك صورة أكثر دقة للاستخدام الحقيقي بلا إنترنت.
ملخص
أظهرت دراسة الحالة هذه أنّ استخدام مشغّل الخدمات قد أدّى إلى تحسين أداء التحميل لتطبيق الويب Google I/O على مجموعة واسعة من المتصفحات والشبكات والأجهزة. وقد تبيّن أيضًا أنّه عند الاطّلاع على توزيع بيانات التحميل على مجموعة كبيرة من المتصفّحات والشبكات والأجهزة، يمكنك الحصول على إحصاءات أكثر بكثير حول كيفية تعامل هذه التكنولوجيا مع سيناريوهات العالم الواقعي، واكتشاف خصائص الأداء التي لم تكن تتوقّعها.
في ما يلي بعض النقاط الرئيسية من دراسة IOWA:
- في المتوسّط، تم تحميل الصفحات بشكل أسرع بكثير عندما كان مشغّل الخدمات يتحكّم في الصفحة مقارنةً بما كان يحدث بدون مشغّل الخدمات، وذلك لكلّ من الزوّار الجدد والمكرّري الزيارة.
- زيارات الصفحات التي يتحكم فيها مشغّل الخدمات والتي تم تحميلها بشكل فوري تقريبًا للعديد من المستخدمين.
- عندما كان عاملو الخدمة غير نشطين، استغرق بدء تشغيله بعض الوقت. ومع ذلك، يظلّ أداء مشغّل الخدمات غير النشط أفضل من عدم استخدام مشغّل خدمات.
- كان وقت بدء تشغيل مشغّل الخدمات غير النشط أطول على الأجهزة الجوّالة مقارنةً بأجهزة الكمبيوتر المكتبي.
على الرغم من أنّ المكاسب في الأداء التي تم رصدها في تطبيق معيّن مفيدة بشكل عام للإبلاغ عنها لمجتمع المطوّرين الأوسع نطاقًا، من المهم تذكُّر أنّ هذه النتائج مرتبطة بنوع الموقع الإلكتروني الذي يمثّله IOWA (موقع إلكتروني لحدث) ونوع الجمهور الذي يستهدفه (مطوّرون في الغالب).
إذا كنت بصدد تنفيذ مشغّل خدمات في تطبيقك، من المهم تنفيذ استراتيجية القياس الخاصة بك حتى تتمكّن من تقييم أدائك وتجنُّب حدوث أي تراجع في المستقبل. إذا كنت تفعل ذلك، يُرجى مشاركة النتائج حتى يستفيد الجميع.
الحواشي السفلية
- ليس من العدل تمامًا مقارنة أداء تنفيذ ذاكرة التخزين المؤقت لعامل الخدمة بأداء موقعنا الإلكتروني باستخدام ذاكرة التخزين المؤقت لبروتوكول HTTP فقط. ولأنّنا كنا نُجري تحسينات على IOWA لتطبيق الخدمة، لم نضِف الكثير من الوقت في إجراء تحسينات على ذاكرة التخزين المؤقت لبروتوكول HTTP. وإذا كنا قد فعلنا ذلك، كانت النتائج مختلفة على الأرجح. لمعرفة المزيد من المعلومات عن تحسين موقعك الإلكتروني لذاكرة التخزين المؤقت لبروتوكول HTTP، يمكنك الاطّلاع على مقالة تحسين المحتوى بكفاءة.
- بناءً على الطريقة التي يحمِّل بها موقعك الإلكتروني أنماطه ومحتواه، من الممكن أن يتمكّن المتصفّح من الرسم قبل أن يتوفّر المحتوى أو الأنماط. في هذه الحالات، قد يشير الرمز
firstpaint
إلى شاشة بيضاء فارغة. في حال استخدامfirstpaint
، من المهم التأكّد من أنّه يتوافق مع نقطة ذات مغزى في تحميل موارد موقعك الإلكتروني. - من الناحية الفنية، يمكننا إرسال مرّة توقيت (وهي غير تفاعلية تلقائيًا) لتسجيل هذه المعلومات بدلاً من حدث. في الواقع، تمت إضافة نتائج التوقيت إلى "إحصاءات Google" خصيصًا لتتبُّع مقاييس التحميل على هذا النحو، ومع ذلك، يتم أخذ عيّنات من نتائج التوقيت بشكلٍ كبير في وقت المعالجة، ولا يمكن استخدام قيمها في الشرائح. ونظرًا لهذه القيود الحالية، تظلّ الأحداث غير المرتبطة بالتفاعلات هي الأنسب.
- لفهم النطاق الذي يجب منحه لسمة مخصّصة في "إحصاءات Google" بشكل أفضل، يُرجى الرجوع إلى قسم السمة المخصّصة في مركز مساعدة "إحصاءات Google". من المهمّ أيضًا فهم نموذج بيانات "إحصاءات Google" الذي يتألّف من المستخدِمين والجلسات والتفاعلات (النتائج). لمعرفة المزيد من المعلومات، يمكنك مشاهدة درس أكاديمية Analytics عن نموذج بيانات "إحصاءات Google".
- ولا يشمل ذلك الموارد التي يتم تحميلها بشكلٍ كسول بعد حدث التحميل.