قياس تأثير الأداء الفعلي للعاملين في مجال تقديم الخدمات

من أهم مزايا خدمة العمال (من منظور الأداء على الأقل) هي قدرتها على التحكّم بشكل استباقي في تخزين مواد العرض المؤقت. من المفترض أن يتم تحميل تطبيق الويب الذي يمكنه تخزين جميع موارده الضرورية بشكل أسرع بكثير للزوار المتكررين. ولكن كيف تبدو هذه المكاسب للمستخدمين الفعليين؟ وكيف يتم قياس ذلك؟

تطبيق الويب 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()
});

يعمل هذا الإجراء، ولكنّه لن يربط حالة عامل الخدمة إلا بهذا الحدث المحدّد. بما أنّ حالة Worker الخدمة هي معلومات قد تكون مفيدة لمعرفة أي تفاعل، من الأفضل تضمينها مع جميع البيانات المُرسَلة إلى "إحصاءات 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 وعدّلنا السمة وفقًا لذلك.

وللتعرّف على مدى شيوع استخدام المستخدمين لميزة "الاستهداف أثناء عدم الاتصال بالإنترنت"، أنشأنا شريحة استهدفت المستخدمين الذين أجروا تفاعلًا واحدًا على الأقل بلا إنترنت. تبيّن أنّ هذه النسبة تبلغ ‎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 (موقع إلكتروني لحدث) ونوع الجمهور الذي يستهدفه (مطوّرون في الغالب).

إذا كنت بصدد تنفيذ مشغّل خدمات في تطبيقك، من المهم تنفيذ استراتيجية القياس الخاصة بك حتى تتمكّن من تقييم أدائك وتجنُّب حدوث أي تراجع في المستقبل. إذا كنت تفعل ذلك، يُرجى مشاركة النتائج حتى يستفيد الجميع.

الحواشي السفلية

  1. ليس من العدل تمامًا مقارنة أداء تنفيذ ذاكرة التخزين المؤقت لعامل الخدمة بأداء موقعنا الإلكتروني باستخدام ذاكرة التخزين المؤقت لبروتوكول HTTP فقط. ولأنّنا كنا نُجري تحسينات على IOWA لتطبيق الخدمة، لم نضِف الكثير من الوقت في تحسين ذاكرة التخزين المؤقت لبروتوكول HTTP. ولو فعلنا ذلك، كانت النتائج مختلفة على الأرجح. لمعرفة المزيد من المعلومات عن تحسين موقعك الإلكتروني لذاكرة التخزين المؤقت لبروتوكول HTTP، يمكنك الاطّلاع على مقالة تحسين المحتوى بكفاءة.
  2. استنادًا إلى كيفية تحميل موقعك الإلكتروني لأشكاله وأسلوبه، من المحتمل أن يتمكّن المتصفّح من الرسم قبل توفّر المحتوى أو الأنماط. في هذه الحالات، قد يشير firstpaint إلى شاشة بيضاء فارغة. في حال استخدام firstpaint، من المهم التأكّد من أنّه يتوافق مع نقطة ذات مغزى في تحميل موارد موقعك الإلكتروني.
  3. من الناحية الفنية، يمكننا إرسال مرّة توقيت (وهي غير تفاعلية تلقائيًا) لتسجيل هذه المعلومات بدلاً من حدث. في الواقع، تمت إضافة نتائج التوقيت إلى "إحصاءات Google" تحديدًا لتتبُّع مقاييس التحميل على هذا النحو، ومع ذلك، يتم أخذ عيّنات من نتائج التوقيت بشكلٍ كبير في وقت المعالجة، ولا يمكن استخدام قيمها في الشرائح. ونظرًا لهذه القيود الحالية، تظلّ الأحداث غير المرتبطة بالتفاعلات هي الأنسب.
  4. لفهم النطاق الذي يجب منحه لسمة مخصّصة في "إحصاءات Google" بشكل أفضل، يُرجى الرجوع إلى قسم السمة المخصّصة في مركز مساعدة "إحصاءات Google". من المهمّ أيضًا فهم نموذج بيانات "إحصاءات Google" الذي يتألّف من المستخدِمين والجلسات والتفاعلات (النتائج). لمعرفة المزيد من المعلومات، يمكنك مشاهدة درس "أكاديمية إحصاءات Google" حول نموذج بيانات "إحصاءات Google".
  5. ولا يشمل ذلك الموارد التي يتم تحميلها بشكلٍ كسول بعد حدث التحميل.