Đo lường tác động thực tế đến hiệu suất của nhân viên dịch vụ

Một trong những lợi ích quan trọng nhất của nhân viên dịch vụ (ít nhất là từ góc độ hiệu suất) là khả năng chủ động kiểm soát việc lưu tài sản vào bộ nhớ đệm. Một ứng dụng web có thể lưu tất cả tài nguyên cần thiết vào bộ nhớ đệm sẽ tải nhanh hơn đáng kể cho khách truy cập cũ. Nhưng lợi ích thực sự của những lợi ích này đối với người dùng thực sự là gì? Và làm cách nào để đo lường điều này?

Ứng dụng web Google I/O (viết tắt là IOWA) là một ứng dụng web tiến bộ tận dụng hầu hết các tính năng mới do worker dịch vụ cung cấp để mang lại trải nghiệm phong phú, giống như ứng dụng cho người dùng. Ứng dụng này cũng sử dụng Google Analytics để thu thập dữ liệu hiệu suất chính và các mẫu sử dụng từ đối tượng người dùng lớn và đa dạng.

Nghiên cứu điển hình này tìm hiểu cách IOWA sử dụng Google Analytics để trả lời các câu hỏi chính về hiệu suất và báo cáo về tác động thực tế của nhân viên dịch vụ.

Bắt đầu bằng câu hỏi

Bất cứ khi nào triển khai tính năng phân tích trong một trang web hoặc ứng dụng, điều quan trọng là bạn phải bắt đầu bằng cách xác định những câu hỏi mà bạn đang cố gắng trả lời từ dữ liệu mà bạn sẽ thu thập.

Mặc dù chúng ta có một số câu hỏi muốn trả lời, nhưng trong phạm vi nghiên cứu điển hình này, hãy tập trung vào hai câu hỏi thú vị hơn.

1. Tính năng lưu vào bộ nhớ đệm của worker có hiệu suất cao hơn các cơ chế lưu vào bộ nhớ đệm HTTP hiện có trong tất cả trình duyệt không?

Chúng tôi dự kiến các trang sẽ tải nhanh hơn cho khách truy cập cũ so với khách truy cập mới vì trình duyệt có thể lưu các yêu cầu vào bộ nhớ đệm và phân phát ngay lập tức các yêu cầu đó trong các lượt truy cập lặp lại.

Trình chạy dịch vụ cung cấp các chức năng lưu vào bộ nhớ đệm thay thế để nhà phát triển có thể kiểm soát chi tiết về nội dung và cách thức lưu vào bộ nhớ đệm. Trong IOWA, chúng tôi đã tối ưu hoá việc triển khai worker dịch vụ để mọi thành phần đều được lưu vào bộ nhớ đệm, nhờ đó, khách truy cập cũ có thể sử dụng ứng dụng hoàn toàn ở chế độ ngoại tuyến.

Nhưng nỗ lực này có tốt hơn những gì trình duyệt đã làm theo mặc định không? Nếu có thì tốt hơn bao nhiêu? 1

2. Trình chạy dịch vụ ảnh hưởng như thế nào đến trải nghiệm tải trang web?

Nói cách khác, trang web có vẻ tải nhanh như thế nào, bất kể thời gian tải thực tế được đo lường bằng các chỉ số tải trang truyền thống?

Rõ ràng là việc trả lời các câu hỏi về cảm nhận về một trải nghiệm không phải là một nhiệm vụ dễ dàng và không có chỉ số nào có thể thể hiện hoàn hảo cảm xúc chủ quan như vậy. Tuy nhiên, chắc chắn có một số chỉ số tốt hơn các chỉ số khác, vì vậy, bạn cần chọn đúng chỉ số.

Chọn chỉ số phù hợp

Theo mặc định, Google Analytics theo dõi thời gian tải trang (thông qua Navigation Timing API) cho 1% khách truy cập trang web và cung cấp dữ liệu đó thông qua các chỉ số như Thời gian tải trang trung bình.

Thời gian tải trang trung bình là một chỉ số phù hợp để trả lời câu hỏi đầu tiên, nhưng không phải là chỉ số phù hợp để trả lời câu hỏi thứ hai. Trước hết, sự kiện load không nhất thiết phải tương ứng với thời điểm người dùng thực sự có thể tương tác với ứng dụng. Hơn nữa, hai ứng dụng có cùng thời gian tải có thể có cảm giác như thể chúng tải theo cách khác nhau. Ví dụ: một trang web có màn hình chờ hoặc chỉ báo tải có thể cho cảm giác tải nhanh hơn nhiều so với một trang web chỉ hiển thị trang trống trong vài giây.

Trong IOWA, chúng tôi đã hiển thị ảnh động đếm ngược trên màn hình chờ (theo tôi) rất thành công trong việc giải trí cho người dùng trong khi phần còn lại của ứng dụng tải ở chế độ nền. Do đó, việc theo dõi thời gian xuất hiện màn hình chờ sẽ hợp lý hơn nhiều khi đo lường hiệu suất tải được cảm nhận. Chúng tôi đã chọn chỉ số thời gian vẽ lần đầu để lấy giá trị này.

Sau khi quyết định những câu hỏi mà chúng tôi muốn trả lời và xác định những chỉ số hữu ích để trả lời các câu hỏi đó, đã đến lúc triển khai Google Analytics và bắt đầu đo lường.

Cách triển khai tính năng phân tích

Nếu bạn đã sử dụng Google Analytics trước đây, thì bạn có thể quen thuộc với đoạn mã theo dõi JavaScript được đề xuất. Thông báo sẽ có dạng như sau:

<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>

Dòng đầu tiên trong mã trên khởi chạy một hàm ga() toàn cục (nếu chưa có) và dòng cuối cùng tải thư viện analytics.js xuống một cách không đồng bộ.

Phần giữa chứa hai dòng sau:

ga('create', 'UA-XXXXX-Y', 'auto');
ga('send', 'pageview');

Hai lệnh này theo dõi những trang mà người dùng truy cập vào trang web của bạn đã truy cập, nhưng không có nhiều thông tin hơn. Nếu muốn theo dõi các lượt tương tác khác của người dùng, bạn phải tự thực hiện.

Đối với IOWA, chúng tôi muốn theo dõi thêm hai điều:

  • Khoảng thời gian trôi qua từ khi trang bắt đầu tải lần đầu tiên cho đến khi các pixel xuất hiện trên màn hình.
  • Liệu trình chạy dịch vụ có đang kiểm soát trang hay không. Với thông tin này, chúng ta có thể phân đoạn báo cáo để so sánh kết quả có và không có worker.

Ghi lại thời gian vẽ lần đầu

Một số trình duyệt ghi lại thời gian chính xác mà pixel đầu tiên được vẽ lên màn hình và cho phép nhà phát triển biết thời gian đó. Giá trị đó, so với giá trị navigationStart được hiển thị qua Navigation Timing API cung cấp cho chúng ta tính toán rất chính xác về khoảng thời gian đã trôi qua từ khi người dùng yêu cầu trang lần đầu đến khi họ nhìn thấy nội dung nào đó lần đầu tiên.

Như tôi đã đề cập, thời gian vẽ lần đầu là một chỉ số quan trọng cần đo lường vì đó là thời điểm đầu tiên người dùng trải nghiệm tốc độ tải của trang web. Đây là ấn tượng đầu tiên mà người dùng nhận được và ấn tượng tốt có thể ảnh hưởng tích cực đến trải nghiệm còn lại của người dùng.2

Để lấy giá trị sơn đầu tiên trong các trình duyệt hiển thị giá trị đó, chúng ta đã tạo hàm tiện ích 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;
    }
  }
}

Như vậy, giờ đây chúng ta có thể viết một hàm khác có khả năng gửi một sự kiện không tương tác với thời gian để hiển thị đầu tiên dưới dạng giá trị: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
    });
  }
}

Sau khi viết cả hai hàm này, mã theo dõi của chúng ta sẽ có dạng như sau:

// 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();

Xin lưu ý rằng tuỳ thuộc vào thời điểm chạy mã trên, các pixel có thể đã được vẽ lên màn hình hoặc chưa. Để đảm bảo luôn chạy mã này sau khi lần vẽ đầu tiên xảy ra, chúng ta đã trì hoãn lệnh gọi đến sendTimeToFirstPaint() cho đến sau sự kiện load. Trên thực tế, chúng tôi quyết định hoãn việc gửi tất cả dữ liệu phân tích cho đến sau khi trang được tải để đảm bảo các yêu cầu đó không cạnh tranh với việc tải các tài nguyên khác.

// 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();
});

Mã ở trên báo cáo firstpaint lần cho Google Analytics, nhưng đó chỉ là một nửa câu chuyện. Chúng ta vẫn cần theo dõi trạng thái của trình chạy dịch vụ; nếu không, chúng ta sẽ không thể so sánh thời gian vẽ đầu tiên của trang do trình chạy dịch vụ kiểm soát và trang không được kiểm soát.

Xác định trạng thái của trình chạy dịch vụ

Để xác định trạng thái hiện tại của trình chạy dịch vụ, chúng ta đã tạo một hàm hiệu dụng trả về một trong ba giá trị:

  • kiểm soát: trình chạy dịch vụ đang kiểm soát trang. Trong trường hợp của IOWA, điều đó cũng có nghĩa là tất cả thành phần đều đã được lưu vào bộ nhớ đệm và trang hoạt động khi không có mạng.
  • được hỗ trợ: trình duyệt hỗ trợ trình chạy dịch vụ, nhưng trình chạy dịch vụ chưa kiểm soát trang. Đây là trạng thái dự kiến cho khách truy cập lần đầu.
  • không được hỗ trợ: trình duyệt của người dùng không hỗ trợ trình chạy dịch vụ.
function getServiceWorkerStatus() {
  if ('serviceWorker' in navigator) {
    return navigator.serviceWorker.controller ? 'controlled' : 'supported';
  } else {
    return 'unsupported';
  }
}

Hàm này nhận được trạng thái của trình chạy dịch vụ cho chúng ta; bước tiếp theo là liên kết trạng thái này với dữ liệu mà chúng ta đã gửi đến Google Analytics.

Theo dõi dữ liệu tuỳ chỉnh bằng phương diện tuỳ chỉnh

Theo mặc định, Google Analytics cung cấp cho bạn nhiều cách để chia nhỏ tổng lưu lượng truy cập thành các nhóm dựa trên các thuộc tính của người dùng, phiên hoặc lượt tương tác. Các thuộc tính này được gọi là phương diện. Những phương diện phổ biến mà các nhà phát triển web quan tâm là những phương diện như Trình duyệt, Hệ điều hành hoặc Danh mục thiết bị.

Trạng thái của worker dịch vụ không phải là một phương diện mà Google Analytics cung cấp theo mặc định; tuy nhiên, Google Analytics cho phép bạn tạo phương diện tuỳ chỉnh của riêng mình và xác định các phương diện đó theo ý muốn.

Đối với IOWA, chúng tôi đã tạo thứ nguyên tùy chỉnh có tên là Trạng thái trình chạy dịch vụ và đặt phạm vi của thứ nguyên thành lượt truy cập (tức là mỗi lần tương tác).4 Mỗi thứ nguyên tùy chỉnh mà bạn tạo trong Google Analytics được cung cấp một chỉ mục duy nhất trong thuộc tính đó và trong mã theo dõi của bạn, bạn có thể tham chiếu thứ nguyên đó theo chỉ mục của thứ nguyên đó. Ví dụ: nếu chỉ mục của phương diện mà chúng ta vừa tạo là 1, thì chúng ta có thể cập nhật logic như sau để gửi sự kiện firstpaint bao gồm trạng thái của worker dịch vụ:

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()
});

Cách này hoạt động, nhưng sẽ chỉ liên kết trạng thái của worker với sự kiện cụ thể này. Vì Trạng thái trình chạy dịch vụ là thông tin có thể hữu ích cho mọi lượt tương tác, nên tốt nhất bạn nên thêm thông tin này vào tất cả dữ liệu được gửi đến Google Analytics.

Để đưa thông tin này vào tất cả các lượt truy cập (ví dụ: tất cả lượt xem trang, sự kiện, v.v.), chúng tôi đặt giá trị phương diện tuỳ chỉnh trên chính đối tượng tracker (trình theo dõi), trước khi gửi bất kỳ dữ liệu nào đến Google Analytics.

ga('set', 'dimension1', getServiceWorkerStatus());

Sau khi được đặt, giá trị này sẽ được gửi cùng với tất cả các lượt truy cập tiếp theo cho lượt tải trang hiện tại. Nếu sau đó người dùng tải trang lại, thì một giá trị mới có thể được trả về từ hàm getServiceWorkerStatus() và giá trị đó sẽ được đặt trên đối tượng trình theo dõi.

Lưu ý nhanh về độ rõ ràng và dễ đọc của mã: vì những người khác xem mã này có thể không biết dimension1 đề cập đến điều gì, nên tốt nhất bạn nên tạo một biến liên kết các tên phương diện có ý nghĩa với các giá trị mà analytics.js sẽ sử dụng.

// 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();
});

Như tôi đã đề cập, việc gửi phương diện Trạng thái trình chạy dịch vụ cùng với mỗi lượt truy cập cho phép chúng ta sử dụng phương diện này khi báo cáo về bất kỳ chỉ số nào.

Như bạn có thể thấy gần 85% trong tổng số lượt xem trang cho IOWA là từ các trình duyệt hỗ trợ service worker.

Kết quả: trả lời câu hỏi của chúng tôi

Sau khi bắt đầu thu thập dữ liệu để trả lời các câu hỏi, chúng ta có thể báo cáo dữ liệu đó để xem kết quả. (Lưu ý: tất cả dữ liệu Google Analytics hiển thị ở đây thể hiện lưu lượng truy cập thực tế trên web đến trang web IOWA từ ngày 16 đến ngày 22 tháng 5 năm 2016).

Câu hỏi đầu tiên của chúng tôi là: Công cụ lưu vào bộ nhớ đệm của worker có hiệu suất cao hơn các cơ chế lưu vào bộ nhớ đệm HTTP hiện có trong tất cả trình duyệt không?

Để trả lời câu hỏi đó, chúng tôi đã tạo một báo cáo tuỳ chỉnh xem xét chỉ số Thời gian tải trang trung bình trên nhiều phương diện. Chỉ số này rất phù hợp để trả lời câu hỏi này vì sự kiện load chỉ kích hoạt sau khi tất cả tài nguyên ban đầu được tải xuống. Do đó, chỉ số này trực tiếp phản ánh tổng thời gian tải cho tất cả tài nguyên quan trọng của trang web.5

Các phương diện chúng tôi chọn là:

  • Phương diện Trạng thái trình chạy dịch vụ tuỳ chỉnh của chúng tôi.
  • Kiểu người dùng: cho biết đây là lần đầu tiên người dùng truy cập vào trang web hay quay lại. (Lưu ý: khách truy cập mới sẽ không có tài nguyên nào được lưu vào bộ nhớ đệm; khách truy cập cũ có thể có.)
  • Danh mục thiết bị, cho phép chúng ta so sánh kết quả trên thiết bị di động và máy tính.

Để kiểm soát khả năng các yếu tố không liên quan đến worker làm sai lệch kết quả về thời gian tải, chúng tôi đã giới hạn truy vấn của mình chỉ bao gồm các trình duyệt hỗ trợ worker.

Như bạn có thể thấy, các lượt truy cập vào ứng dụng của chúng tôi khi được kiểm soát bởi một nhân viên dịch vụ tải nhanh hơn khá nhiều so với các lượt truy cập không được kiểm soát, thậm chí các lượt truy cập từ người dùng cũ có thể đã lưu hầu hết tài nguyên của trang vào bộ nhớ đệm. Một điều thú vị khác là trung bình, khách truy cập trên thiết bị di động có worker dịch vụ sẽ tải nhanh hơn so với khách truy cập mới trên máy tính.

"…các lượt truy cập vào ứng dụng của chúng tôi khi được kiểm soát bởi một trình chạy dịch vụ tải nhanh hơn khá nhiều so với các lượt truy cập không được kiểm soát…"

Bạn có thể xem thêm thông tin chi tiết trong hai bảng sau:

Thời gian tải trang trung bình (Máy tính)
Trạng thái của trình chạy dịch vụ Loại Người Dùng Thời gian tải trang tr.bình (mili giây) Kích thước mẫu
Đã kiểm soát Khách truy cập cũ 2568 30860
Có thể làm Khách truy cập cũ 3612 1289
Có thể làm Khách truy cập mới 4664 21991
Thời gian tải trang trung bình (Thiết bị di động)
Trạng thái của trình chạy dịch vụ Loại Người Dùng Thời gian tải trang tr.bình (mili giây) Kích thước mẫu
Đã kiểm soát Khách truy cập cũ 3760 8162
Có thể làm Khách truy cập cũ 4843 676
Có thể làm Khách truy cập mới 6158 5779

Bạn có thể thắc mắc làm cách nào để một khách truy cập quay lại có trình duyệt hỗ trợ trình chạy dịch vụ có thể ở trạng thái không được kiểm soát. Có một số lý do có thể giải thích cho điều này:

  • Người dùng đã rời khỏi trang trong lần truy cập đầu tiên trước khi trình chạy dịch vụ có cơ hội hoàn tất quá trình khởi chạy.
  • Người dùng đã gỡ cài đặt trình chạy dịch vụ thông qua công cụ cho nhà phát triển.

Cả hai trường hợp này đều tương đối hiếm gặp. Chúng ta có thể thấy điều đó trong dữ liệu bằng cách xem các giá trị Mẫu tải trang trong cột thứ tư. Hãy lưu ý rằng các hàng ở giữa có mẫu nhỏ hơn nhiều so với hai hàng còn lại.

Câu hỏi thứ hai của chúng tôi là: Trình chạy dịch vụ ảnh hưởng như thế nào đến trải nghiệm tải trang web?

Để trả lời câu hỏi này, chúng tôi đã tạo một báo cáo tuỳ chỉnh khác cho chỉ số Giá trị sự kiện trung bình và lọc kết quả để chỉ bao gồm các sự kiện firstpaint. Chúng tôi đã sử dụng phương diện Danh mục thiết bị và phương diện tuỳ chỉnh Trạng thái trình chạy dịch vụ.

Trái với những gì tôi mong đợi, trình chạy dịch vụ trên thiết bị di động có tác động ít hơn nhiều đến thời gian để vẽ đầu tiên so với tổng thể tải trang.

"…trình chạy dịch vụ trên thiết bị di động ít tác động hơn nhiều đến thời gian vẽ lần đầu so với thời gian tải trang tổng thể".

Để tìm hiểu lý do dẫn đến tình trạng này, chúng ta phải tìm hiểu sâu hơn về dữ liệu. Số liệu trung bình có thể phù hợp với thông tin tổng quan chung và các số liệu tổng quát, nhưng để thực sự hiểu rõ cách những con số này được phân tích trên một loạt người dùng, chúng ta cần xem xét mức phân phối của firstpaint lần.

Xem thông tin phân phối của một chỉ số trong Google Analytics

Để có được thông tin phân phối về số lần firstpaint, chúng ta cần có quyền truy cập vào kết quả riêng lẻ cho từng sự kiện. Rất tiếc, Google Analytics không hỗ trợ việc này một cách dễ dàng.

Google Analytics cho phép chúng ta phân tích một báo cáo theo bất kỳ phương diện nào chúng ta muốn, nhưng không cho phép phân tích một báo cáo theo chỉ số. Điều đó không có nghĩa là không thể, mà chỉ là chúng ta phải tuỳ chỉnh cách triển khai thêm một chút để có được kết quả mong muốn.

Vì chỉ có thể phân tích kết quả báo cáo theo phương diện, nên chúng tôi phải đặt giá trị chỉ số (trong trường hợp này là firstpaint lần) làm phương diện tuỳ chỉnh cho sự kiện. Để làm điều này, chúng tôi đã tạo một thứ nguyên tùy chỉnh khác có tên là Giá trị chỉ số và cập nhật logic theo dõi firstpaint như sau:

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);
  }
}

Giao diện web của Google Analytics hiện không cung cấp cách trực quan hoá việc phân phối các giá trị chỉ số tuỳ ý, nhưng nhờ có API Báo cáo chính của Google Analyticsthư viện Biểu đồ của Google, chúng ta có thể truy vấn kết quả thô rồi tự tạo biểu đồ thanh.

Ví dụ: cấu hình yêu cầu API sau đây được dùng để phân phối các giá trị firstpaint trên máy tính bằng một worker dịch vụ không được kiểm soát.

{
  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'
    }
  ]
}

Yêu cầu API này trả về một mảng các giá trị như sau (Lưu ý: đây chỉ là 5 kết quả đầu tiên). Kết quả được sắp xếp theo thứ tự từ nhỏ nhất đến lớn nhất, do đó các hàng này thể hiện thời gian nhanh nhất.

Kết quả phản hồi API (5 hàng đầu tiên)
ga:dimension2 ga:totalEvents
4 3
5 2
6 10
7 8
8 10

Sau đây là ý nghĩa của những kết quả này bằng tiếng Anh đơn giản:

  • Có 3 sự kiện mà giá trị firstpaint là 4 mili giây
  • Có 2 sự kiện mà giá trị firstpaint là 5 mili giây
  • Có 10 sự kiện có giá trị firstpaint là 6 mili giây
  • Có 8 sự kiện có giá trị firstpaint là 7 mili giây
  • Có 10 sự kiện mà firstpaint value là 8 mili giây
  • v.v.

Từ những kết quả này, chúng ta có thể ngoại suy giá trị firstpaint cho từng sự kiện và tạo biểu đồ về mức phân phối. Chúng tôi làm việc này cho mỗi truy vấn mà chúng tôi đã thực hiện.

Dưới đây là hình ảnh phân phối trên máy tính có trình chạy dịch vụ không được kiểm soát (nhưng được hỗ trợ):

Thời gian phân phối lần vẽ đầu tiên trên máy tính (được hỗ trợ)

Thời gian firstpaint trung bình cho phân phối ở trên là 912 mili giây.

Hình dạng của đường cong này khá điển hình cho các phân phối thời gian tải. Trái ngược với biểu đồ bên dưới, biểu đồ này hiển thị việc phân phối sự kiện hiển thị đầu tiên cho các lượt truy cập mà trong đó một worker dịch vụ đang kiểm soát trang.

Thời gian phân phối lần vẽ đầu tiên trên máy tính (được kiểm soát)

Lưu ý rằng khi một trình chạy dịch vụ đang kiểm soát trang, nhiều khách truy cập gặp phải lần hiển thị đầu tiên gần như ngay lập tức, với trung vị là 583 mili giây.

"...khi một nhân viên dịch vụ đang kiểm soát trang, nhiều khách truy cập đã trải qua lần hiển thị đầu tiên gần như ngay lập tức..."

Để hiểu rõ hơn về sự khác biệt giữa hai phân phối này, biểu đồ tiếp theo cho thấy chế độ xem hợp nhất của hai phân phối. Biểu đồ thể hiện lượt truy cập của nhân viên dịch vụ không được kiểm soát được phủ lên đầu biểu đồ hiển thị số lượt truy cập được kiểm soát và cả hai đều được phủ lên đầu biểu đồ hiển thị cả hai.

Phân phối thời gian vẽ lần đầu trên máy tính

Một điều tôi thấy thú vị về những kết quả này là việc phân phối với một worker dịch vụ được kiểm soát vẫn có đường cong hình chuông sau khi tăng đột biến ban đầu. Tôi dự kiến sẽ có một mức tăng đột biến lớn ban đầu rồi giảm dần, tôi không dự kiến sẽ có một đỉnh thứ hai trong đường cong.

Khi tìm hiểu nguyên nhân có thể gây ra vấn đề này, tôi nhận thấy rằng mặc dù trình chạy dịch vụ có thể đang kiểm soát một trang, nhưng luồng của trình chạy dịch vụ đó có thể không hoạt động. Trình duyệt thực hiện việc này để tiết kiệm tài nguyên – rõ ràng là bạn không cần mỗi service worker cho mọi trang web bạn từng truy cập để hoạt động và sẵn sàng kịp thời. Điều này giải thích phần đuôi của phân phối. Đối với một số người dùng, đã có sự chậm trễ khi luồng trình chạy dịch vụ khởi động.

Tuy nhiên, như bạn có thể thấy từ dữ liệu phân phối, ngay cả với độ trễ ban đầu này, trình duyệt có worker dịch vụ vẫn phân phối nội dung nhanh hơn trình duyệt truy cập qua mạng.

Dưới đây là giao diện trên thiết bị di động:

Phân phối thời gian vẽ lần đầu trên thiết bị di động

Mặc dù thời gian vẽ lần đầu gần như tức thì vẫn tăng lên đáng kể, nhưng đuôi lại lớn và dài hơn khá nhiều. Điều này có thể là do trên thiết bị di động, việc bắt đầu một luồng worker dịch vụ rảnh mất nhiều thời gian hơn so với trên máy tính. Điều này cũng giải thích lý do tại sao sự khác biệt giữa thời gian firstpaint trung bình không lớn như tôi mong đợi (đã thảo luận ở trên).

"…trên thiết bị di động, việc khởi động luồng worker dịch vụ rảnh mất nhiều thời gian hơn so với trên máy tính."

Dưới đây là bảng chi tiết về các biến thể này của thời gian vẽ đầu tiên trung bình trên thiết bị di động và máy tính, được nhóm theo trạng thái của worker dịch vụ:

Thời gian trung bình để vẽ lần đầu (mili giây)
Trạng thái của trình chạy dịch vụ Máy tính Thiết bị di động
Đã kiểm soát 583 1634
Được hỗ trợ (không được kiểm soát) 912 1933

Mặc dù việc tạo những hình ảnh phân phối này mất nhiều thời gian và công sức hơn một chút so với việc tạo báo cáo tuỳ chỉnh trong Google Analytics, nhưng chúng cho chúng tôi hiểu rõ hơn về cách trình thực thi dịch vụ ảnh hưởng đến hiệu suất của trang web so với khi chỉ sử dụng mức trung bình.

Tác động khác của Trình chạy dịch vụ

Ngoài tác động đến hiệu suất, trình chạy dịch vụ cũng tác động đến trải nghiệm người dùng theo một số cách khác có thể đo lường được bằng Google Analytics.

Xem không cần mạng

Trình chạy dịch vụ cho phép người dùng tương tác với trang web của bạn khi không có mạng. Mặc dù một số loại dịch vụ hỗ trợ ngoại tuyến có thể rất quan trọng đối với mọi ứng dụng web tiến bộ, nhưng việc xác định mức độ quan trọng của dịch vụ đó trong trường hợp của bạn phần lớn phụ thuộc vào mức sử dụng ngoại tuyến. Nhưng làm cách nào để chúng tôi đo lường điều đó?

Việc gửi dữ liệu đến Google Analytics cần có kết nối Internet, nhưng không yêu cầu gửi dữ liệu vào đúng thời điểm xảy ra hoạt động tương tác. Google Analytics hỗ trợ việc gửi dữ liệu tương tác sau khi sự kiện xảy ra bằng cách chỉ định độ lệch thời gian (thông qua tham số qt).

Trong hai năm qua, IOWA đã sử dụng một tập lệnh worker dịch vụ để phát hiện các lượt truy cập không thành công đến Google Analytics khi người dùng không có mạng và phát lại các lượt truy cập đó sau đó bằng tham số qt.

Để theo dõi xem người dùng đang trực tuyến hay ngoại tuyến, chúng tôi đã tạo một phương diện tuỳ chỉnh có tên là Trực tuyến và đặt phương diện đó thành giá trị navigator.onLine, sau đó chúng tôi đã theo dõi các sự kiện onlineoffline rồi cập nhật phương diện cho phù hợp.

Để biết mức độ phổ biến của việc người dùng ở trạng thái ngoại tuyến khi sử dụng IOWA, chúng tôi đã tạo một phân khúc nhắm đến những người dùng có ít nhất một lượt tương tác ngoại tuyến. Hóa ra, đó là gần 5% người dùng.

Thông báo đẩy

Trình chạy dịch vụ cho phép người dùng chọn nhận thông báo đẩy. Trong IOWA, người dùng được thông báo khi một phiên trong lịch của họ sắp bắt đầu.

Giống như mọi hình thức thông báo, điều quan trọng là bạn phải tìm được sự cân bằng giữa việc cung cấp giá trị cho người dùng và gây phiền toái cho họ. Để hiểu rõ hơn điều gì đang xảy ra, điều quan trọng là phải theo dõi xem người dùng có đang chọn nhận những thông báo này hay không, liệu họ có tương tác với chúng khi đến nơi hay không và có bất kỳ người dùng nào trước đó đã chọn nhận thay đổi tùy chọn của họ và chọn không nhận thông báo hay không.

Trong IOWA, chúng tôi chỉ gửi thông báo liên quan đến lịch biểu được cá nhân hoá của người dùng, một nội dung mà chỉ người dùng đã đăng nhập mới có thể tạo. Điều này đã giới hạn nhóm người dùng có thể nhận thông báo ở những người dùng đã đăng nhập (được theo dõi thông qua một phương diện tuỳ chỉnh có tên là Đã đăng nhập) có trình duyệt hỗ trợ thông báo đẩy (được theo dõi thông qua một phương diện tuỳ chỉnh khác có tên là Quyền gửi thông báo).

Báo cáo sau đây dựa trên chỉ số Số người dùng và phương diện tuỳ chỉnh Quyền gửi thông báo của chúng tôi. Phương diện này được phân đoạn theo những người dùng đã đăng nhập tại một thời điểm nào đó và có trình duyệt hỗ trợ thông báo đẩy.

Chúng tôi rất vui khi thấy hơn một nửa số người dùng đã đăng nhập đã chọn nhận thông báo đẩy.

Biểu ngữ cài đặt ứng dụng

Nếu một ứng dụng web tiến trình đáp ứng tiêu chí và được người dùng thường xuyên sử dụng, thì người dùng đó có thể thấy một biểu ngữ cài đặt ứng dụng, nhắc họ thêm ứng dụng vào màn hình chính.

Trong IOWA, chúng tôi đã theo dõi tần suất hiển thị các lời nhắc này cho người dùng (và liệu họ có chấp nhận hay không) bằng mã sau:

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
    });
  });
});

Trong số những người dùng đã nhìn thấy biểu ngữ cài đặt ứng dụng, khoảng 10% đã chọn thêm biểu ngữ đó vào màn hình chính.

Những điểm cải thiện có thể áp dụng cho hoạt động theo dõi (cho lần sau)

Dữ liệu phân tích mà chúng tôi thu thập được từ IOWA năm nay rất có giá trị. Tuy nhiên, những khoảnh khắc bỏ ngỏ luôn mang đến những lỗ hổng nhỏ và cơ hội để cải thiện mọi thứ cho lần sau. Sau khi hoàn tất phân tích năm nay, tôi muốn chia sẻ 2 điều mà chúng tôi nên làm khác đi. Những độc giả muốn triển khai một chiến lược tương tự có thể cân nhắc những điều sau:

1. Theo dõi thêm các sự kiện liên quan đến trải nghiệm tải

Chúng tôi đã theo dõi một số sự kiện tương ứng với một chỉ số kỹ thuật (ví dụ: HTMLImportsLoaded, WebComponentsReady, v.v.), nhưng vì quá trình tải được thực hiện không đồng bộ, nên thời điểm kích hoạt các sự kiện này không nhất thiết phải tương ứng với một thời điểm cụ thể trong trải nghiệm tải tổng thể.

Sự kiện chính liên quan đến tải mà chúng tôi không theo dõi (nhưng rất muốn theo dõi) là thời điểm màn hình chờ biến mất và người dùng có thể xem nội dung trang.

2. Lưu trữ mã ứng dụng phân tích trong IndexedDB

Theo mặc định, analytics.js lưu trữ trường mã ứng dụng khách trong cookie của trình duyệt; tuy nhiên, tập lệnh trình chạy dịch vụ không thể truy cập vào cookie.

Điều này gây ra vấn đề cho chúng tôi khi cố gắng triển khai tính năng theo dõi thông báo. Chúng tôi muốn gửi một sự kiện từ worker dịch vụ (thông qua Measurement Protocol) mỗi khi gửi thông báo cho người dùng, sau đó theo dõi mức độ thành công của lượt tương tác lại của thông báo đó nếu người dùng nhấp vào thông báo đó và quay lại ứng dụng.

Mặc dù có thể theo dõi mức độ thành công của thông báo nói chung thông qua thông số chiến dịch utm_source, nhưng chúng tôi không thể liên kết một phiên tương tác lại cụ thể với một người dùng cụ thể.

Chúng ta có thể khắc phục hạn chế này bằng cách lưu trữ mã ứng dụng thông qua IndexedDB trong mã theo dõi, sau đó tập lệnh worker dịch vụ có thể truy cập vào giá trị đó.

3. Cho phép trình chạy dịch vụ báo cáo trạng thái trực tuyến/ngoại tuyến

Việc kiểm tra navigator.onLine sẽ cho bạn biết liệu trình duyệt của bạn có thể kết nối với bộ định tuyến hoặc mạng cục bộ hay không, nhưng không nhất thiết phải cho bạn biết liệu người dùng có kết nối thực sự hay không. Và vì tập lệnh worker dịch vụ phân tích ngoại tuyến của chúng ta chỉ phát lại các lượt truy cập không thành công (mà không sửa đổi hoặc đánh dấu các lượt truy cập đó là không thành công), nên có thể chúng ta đang báo cáo thiếu mức sử dụng ngoại tuyến.

Trong tương lai, chúng ta nên theo dõi cả trạng thái của navigator.onLine cũng như liệu trình chạy dịch vụ có phát lại lượt truy cập do lỗi mạng ban đầu hay không. Điều này sẽ giúp chúng tôi hiểu rõ hơn về mức sử dụng thực sự ở chế độ ngoại tuyến.

Kết thúc

Nghiên cứu điển hình này cho thấy việc sử dụng worker dịch vụ thực sự đã cải thiện hiệu suất tải của ứng dụng web Google I/O trên nhiều trình duyệt, mạng và thiết bị. Nghiên cứu này cũng cho thấy rằng khi xem xét việc phân phối dữ liệu tải trên nhiều trình duyệt, mạng và thiết bị, bạn sẽ hiểu rõ hơn về cách công nghệ này xử lý các tình huống thực tế và khám phá những đặc điểm hiệu suất mà bạn có thể không lường trước được.

Sau đây là một số điểm chính cần ghi nhớ từ nghiên cứu IOWA:

  • Trung bình, các trang tải nhanh hơn khá nhiều khi có trình chạy dịch vụ kiểm soát trang so với khi không có trình chạy dịch vụ, cho cả khách truy cập mới và khách truy cập cũ.
  • Đối với nhiều người dùng, các lượt truy cập vào các trang do trình chạy dịch vụ kiểm soát tải gần như ngay lập tức.
  • Trình chạy dịch vụ, khi không hoạt động, mất một chút thời gian để khởi động. Tuy nhiên, trình chạy dịch vụ không hoạt động vẫn hoạt động hiệu quả hơn so với không có trình chạy dịch vụ.
  • Thời gian khởi động của trình chạy dịch vụ không hoạt động lâu hơn trên thiết bị di động so với trên máy tính.

Mặc dù mức tăng hiệu suất được quan sát trong một ứng dụng cụ thể thường hữu ích để báo cáo cho cộng đồng nhà phát triển lớn hơn, nhưng điều quan trọng cần nhớ là những kết quả này dành riêng cho loại trang web của IOWA (trang web sự kiện) và loại đối tượng mà IOWA có (chủ yếu là nhà phát triển).

Nếu đang triển khai worker dịch vụ trong ứng dụng, bạn cần phải triển khai chiến lược đo lường của riêng mình để có thể đánh giá hiệu suất của chính mình và ngăn chặn sự hồi quy trong tương lai. Nếu có, vui lòng chia sẻ kết quả để mọi người đều có thể hưởng lợi!

Chú thích chân trang

  1. Việc so sánh hiệu suất triển khai bộ nhớ đệm của worker dịch vụ với hiệu suất của trang web chỉ bằng bộ nhớ đệm HTTP là chưa hoàn toàn công bằng. Vì đang tối ưu hoá IOWA cho worker dịch vụ, nên chúng tôi không dành nhiều thời gian để tối ưu hoá cho bộ nhớ đệm HTTP. Nếu chúng tôi có, kết quả có lẽ đã khác. Để tìm hiểu thêm về cách tối ưu hoá trang web của bạn cho bộ nhớ đệm HTTP, hãy đọc bài viết Tối ưu hoá nội dung một cách hiệu quả.
  2. Tuỳ thuộc vào cách trang web tải kiểu và nội dung, trình duyệt có thể vẽ trước khi nội dung hoặc kiểu có sẵn. Trong những trường hợp như vậy, firstpaint có thể tương ứng với màn hình trắng trống. Nếu bạn sử dụng firstpaint, điều quan trọng là phải đảm bảo rằng firstpaint tương ứng với một điểm có ý nghĩa trong quá trình tải tài nguyên của trang web.
  3. Về mặt kỹ thuật, chúng ta có thể gửi một lượt truy cập thời gian (theo mặc định là lượt truy cập không tương tác) để thu thập thông tin này thay vì một sự kiện. Trên thực tế, các lượt truy cập theo thời gian đã được thêm vào Google Analytics để theo dõi các chỉ số tải như thế này; tuy nhiên, các lượt truy cập theo thời gian được lấy mẫu rất nhiều tại thời điểm xử lý và không thể sử dụng giá trị của các lượt truy cập này trong phân khúc. Với những hạn chế hiện tại này, các sự kiện không tương tác vẫn phù hợp hơn.
  4. Để hiểu rõ hơn về phạm vi cần cung cấp cho một phương diện tuỳ chỉnh trong Google Analytics, hãy tham khảo mục Phương diện tuỳ chỉnh trong trung tâm trợ giúp của Analytics. Bạn cũng cần hiểu rõ mô hình dữ liệu của Google Analytics, bao gồm người dùng, phiên và lượt tương tác (lượt truy cập). Để tìm hiểu thêm, hãy xem bài học của Học viện Analytics về Mô hình dữ liệu của Google Analytics.
  5. Số liệu này không tính đến các tài nguyên được tải theo phương thức tải lười sau sự kiện tải.