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

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

إنّ تطبيق الويب Google I/O (المعروف اختصارًا باسم IOWA) هو تطبيق ويب تقدّمي يستفيد من معظم الإمكانات الجديدة التي يقدّمها عمال الخدمة لتقديم تجربة غنية تشبه التطبيقات. واستعانت أيضًا بخدمة "إحصاءات Google" لجمع بيانات الأداء الرئيسية وأنماط الاستخدام من شرائح جمهورها الكبيرة والمتنوّعة.

تستكشف دراسة الحالة هذه كيفية استخدام IOWA لبرنامج Google Analytics للإجابة عن الأسئلة الرئيسية المتعلقة بالأداء وإعداد تقارير عن التأثير الفعلي للعاملين في الخدمة.

البدء بالأسئلة

في أي وقت تنفذ فيه التحليلات في موقع ويب أو تطبيق، من المهم أن تبدأ بتحديد الأسئلة التي تحاول الإجابة عنها من البيانات التي ستجمعها.

في حين أننا أردنا الإجابة عن العديد من الأسئلة، لنركّز على اثنين من أكثر الأسئلة إثارةً للاهتمام، وذلك لأغراض دراسة الحالة هذه.

1. هل التخزين المؤقت لعامل الخدمة أكثر أداءً من آليات التخزين المؤقت الحالية لبروتوكول HTTP المتوفّرة في جميع المتصفّحات؟

نتوقع بالفعل أن يتم تحميل الصفحات بشكل أسرع للزوّار المكرري الزيارة مقارنةً بالزائرين الجدد؛ نظرًا لأن المتصفحات يمكنها تخزين الطلبات في ذاكرة التخزين المؤقت وعرضها على الفور في الزيارات المتكررة.

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

ولكن هل ستكون هذه الجهود أفضل مما يفعله المتصفح بشكل افتراضي؟ وإذا كان الأمر كذلك، فإلى أي مدى يكون أفضل؟ 1

2. كيف يؤثر مشغّل الخدمات في تجربة تحميل الموقع الإلكتروني؟

بعبارة أخرى، ما مدى سرعة تحميل الموقع الإلكتروني الشعور، بغض النظر عن أوقات التحميل الفعلية التي يتم قياسها بمقاييس تحميل الصفحات التقليدية؟

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

اختيار المقياس الصحيح

يتتبع برنامج Google Analytics بشكلٍ افتراضي أوقات تحميل الصفحة (عبر واجهة برمجة تطبيقات وقت التنقل) لنسبة 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 المعروضة عبر واجهة برمجة تطبيقات وقت التنقل، توفّر لنا إمكانية حساب دقيق جدًا للوقت المنقضي بين وقت طلب المستخدم للصفحة لأول مرة ووقت مشاهدته لأول مرة.

كما ذكرت سابقًا، يُعتبر وقت عرض المحتوى للمرة الأولى مقياسًا مهمًا يجب قياسه، إذ إنّه هو النقطة الأولى التي يختبر فيها المستخدم سرعة تحميل موقعك الإلكتروني. وهي الانطباع الأول الذي يتكون لدى المستخدمين، والانطباع الأول الجيد يمكن أن يؤثر بشكل إيجابي في بقية تجربة المستخدم.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();
});

يُبلغ الرمز أعلاه "إحصاءات Google" firstpaint مرة، ولكن هذا الرقم ليس سوى نصف المدة. ما زلنا بحاجة إلى تتبُّع حالة مشغّل الخدمات، وإلا فلن نتمكّن من مقارنة أوقات عرض محتوى الصفحة التي يتحكّم فيها مشغّل الخدمات وتلك التي لا يتم التحكّم فيها.

تحديد حالة مشغّل الخدمات

لتحديد الحالة الحالية لمشغِّل الخدمات، أنشأنا دالة مساعدة تُرجع إحدى القيم الثلاث التالية:

  • تحكم فيها: يعني هذا أن أحد مشغّلي الخدمات يتحكّم في الصفحة. وفي حالة 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 من جميع مشاهدات صفحات IOWA مصدرها المتصفّحات التي تتوافق مع مشغّل الخدمات.

النتائج: الإجابة عن أسئلتنا

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

على سبيل المثال، تم استخدام إعدادات طلب واجهة برمجة التطبيقات التالية لتوزيع قيم 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، تم إخطار المستخدمين عندما كانت جلسة في جدولهم على وشك البدء.

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

في IOWA، أرسلنا فقط إشعارات ذات صلة بالجدول الزمني المخصص للمستخدم، وهو شيء لا يمكن سوى للمستخدمين الذين سجّلوا دخولهم إنشاءه. وقد حدَّد ذلك مجموعة المستخدمين الذين يمكنهم تلقّي إشعارات للمستخدمين الذين سجّلوا دخولهم (يتم تتبُّعهم عبر سمة مخصّصة تُسمى مسجّل الدخول) الذين تتوافق متصفّحاتهم مع الإشعارات الفورية (التي يتم تتبُّعها من خلال سمة مخصّصة أخرى باسم إذن إرسال الإشعارات).

يستند التقرير التالي إلى المقياس المستخدِمون والسمة المخصّصة لإذن إرسال الإشعارات، وقد تمّ تقسيمها حسب المستخدمين الذين سجّلوا الدخول في وقت ما والذين تتوافق متصفّحاتهم مع الإشعارات الفورية.

من الرائع أن نرى أنّ أكثر من نصف المستخدمِين الذين سجّلوا دخولهم فعّلوا ميزة تلقّي الإشعارات الفورية.

إعلانات بانر لتثبيت التطبيقات

إذا استوفى تطبيق الويب التقدّمي المعايير ويتم استخدامه بشكل متكرر من قِبل المستخدم، قد يظهر لهذا المستخدم إعلان بانر لتثبيت التطبيق يطلب منه إضافة التطبيق إلى شاشته الرئيسية.

في 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 (موقع فعالية) ونوع جمهور IOWA (معظمهم من مطوّري البرامج).

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

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

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