Hầu hết dữ liệu phân tích, dữ liệu đo từ xa và dữ liệu phân tích Core Web Vitals đều có mức độ ưu tiên thấp hơn so với việc phản hồi người dùng, vì vậy, bạn có thể trì hoãn việc gửi dữ liệu đó cho đến khi người dùng rời khỏi trang. Trường hợp ngoại lệ là khi bạn cần cung cấp thông tin cập nhật theo thời gian thực, trong trường hợp đó, tính kịp thời là yếu tố quan trọng.
Cách tối ưu để cung cấp thông tin cập nhật về số liệu phân tích theo thời gian thực mà vẫn giảm thiểu được số lượng đèn hiệu là sử dụng fetchLater() với tuỳ chọn cấu hình activateAfter. Điều này cho phép bạn loại bỏ và gộp tất cả sự kiện phân tích xảy ra trong một khoảng thời gian nhất định thành một beacon duy nhất, được gửi một cách đáng tin cậy ngay cả khi người dùng rời khỏi trang trước khi hết thời gian chờ.
Cách triển khai
Lên lịch yêu cầu: Ngay khi có dữ liệu phân tích liên quan, hãy gọi
fetchLater()bằng tải trọng dữ liệu của bạn và truyền giá trịactivateAfter. Thao tác này sẽ đưa dữ liệu vào hàng đợi để gửi sau khi khoảng thời gian đó trôi qua hoặc nếu người dùng rời khỏi trang trước đó.Gộp nhiều sự kiện lại với nhau: Nếu một sự kiện phân tích mới xảy ra trước khi hết thời gian chờ
activateAfter, hãy huỷ yêu cầu đã lên lịch trước đó và gọi lạifetchLater()(với cùng giá trịactivateAfter) bằng hàng đợi sự kiện đầy đủ trong một tải trọng duy nhất.Đặt lại hàng đợi sự kiện khi hết thời gian chờ: Nếu một sự kiện phân tích mới xảy ra sau khi đèn hiệu theo lịch đã gửi thành công (tức là giá trị
activatedcủa kết quảfetchLater()làtrue), hãy đặt lại hàng đợi sự kiện.Để trình duyệt xử lý phần còn lại: Nếu người dùng rời khỏi hoặc đóng thẻ trước khi hết thời gian chờ
activateAfter, trình duyệt vẫn sẽ gửi tải trọng một cách đáng tin cậy từ lệnh gọifetchLater()gần đây nhất của bạn.
Mã mẫu
Mã này theo dõi tất cả sự kiện load và click trên một trang, đồng thời gộp tất cả sự kiện xảy ra trong khoảng thời gian chờ 10 giây.
// Replace with your analytics endpoint.
const ANALYTICS_ENDPOINT = '/path/to/analytics/endpoint';
// Replace with a time window of your choice. All analytics events that
// occur within this time window will be batched together.
const BATCH_WINDOW = 10 * 1000;
// The maximum number of events to batch. Pick a number that is unlikely
// to overflow the fetchLater() quota for the page.
const MAX_QUEUE_SIZE = 100;
const eventQueue = [];
let fetchLaterResult;
let fetchLaterController;
function trackEvent(eventData) {
// If the previously queued beacon has already been sent, or if the
// max queue size has been met, reset the queue.
if (fetchLaterResult?.activated || eventQueue.length > MAX_QUEUE_SIZE) {
fetchLaterController = null;
fetchLaterResult = null;
eventQueue.length = 0;
}
eventQueue.push(eventData);
// Abort any pending beacons before creating a new one.
if (fetchLaterController) {
fetchLaterController.abort();
}
fetchLaterController = new AbortController();
// Schedule a fetch for the events to be sent when the batch window expires.
// IMPORTANT: wrap the call in a try/catch to handle quota errors.
try {
fetchLaterResult = fetchLater(ANALYTICS_ENDPOINT, {
method: 'POST',
headers: {'content-type': 'application/json'},
body: JSON.stringify(eventQueue),
signal: fetchLaterController.signal,
activateAfter: BATCH_WINDOW,
});
} catch (error) {
// Handle errors as needed.
}
}
// Track page loads.
window.addEventListener('load', () => {
trackEvent({type: 'page_load'});
});
// Track click events.
window.addEventListener('click', (event) => {
trackEvent({type: 'click', target: serializeElement(event.target)});
});
Các phương pháp hay nhất
- NÊN sử dụng
fetchLater()với tuỳ chọnactivateAfterđể gộp nhiều sự kiện phân tích xảy ra gần nhau. - NÊN sử dụng
AbortControllerđể huỷ lệnh tìm nạp đang chờ xử lý trong trường hợp xảy ra sự kiện phân tích mới. - NÊN kiểm tra để đảm bảo bạn không gộp quá nhiều sự kiện và vượt quá hạn mức
fetchLater()(hiện tại là khoảng 64 KB cho mỗi nguồn gốc). - NÊN gói các lệnh gọi đến
fetchLater()trongtry/catchđể xử lý lỗi hạn mức. - NÊN phát hiện tính năng về sự hiện diện của
fetchLater()trênglobalThisvà triển khai chiến lược dự phòng cho các trình duyệt không hỗ trợ API. - KHÔNG sử dụng đối tượng
ReadableStreamcho nội dung yêu cầu vì việc này sẽ gây ra lỗi.
Hỗ trợ trình duyệt và chiến lược dự phòng
Do đó, bạn thường cần có một chiến lược dự phòng.
Tuy nhiên, do API này có độ tin cậy và hiệu suất cao hơn, nên bạn nên sử dụng fetchLater() nếu trình duyệt hỗ trợ.
fetchLater() polyfill
Sử dụng polyfill fetchLater() tối thiểu sau đây để triển khai API gần nhất có thể trong các trình duyệt không hỗ trợ.
Điểm khác biệt đáng chú ý duy nhất về hành vi của polyfill này là thay vì gửi tải trọng khi người dùng rời khỏi trang, polyfill này sẽ gửi tải trọng bất cứ khi nào visibilityState của trang thay đổi thành "hidden" (ẩn), vì đây là tín hiệu kết thúc phiên đáng tin cậy nhất hiện có rộng rãi.
globalThis.fetchLater ??= function fetchLater(url, init = {}) {
let timeoutHandle;
let activated = false;
function sendNow() {
if (!(init.signal && init.signal.aborted)) {
// Use fetch keepalive if the browser supports it or if custom fetch
// parameters are specified (e.g. custom headers or methods).
// Otherwise fall back to `navigator.sendBeacon()`.
if (
'keepalive' in Request.prototype ||
init.method !== 'POST' ||
init.headers
) {
fetch(url, Object.assign({}, init, {keepalive: true}));
activated = true;
} else {
activated = navigator.sendBeacon(url, init.body);
}
}
destroy();
}
function destroy() {
document.removeEventListener('visibilitychange', sendNow);
clearTimeout(timeoutHandle);
}
if (document.visibilityState === 'hidden') {
// If the beacon was created while the page is already hidden, send data
// ASAP but wait until the next microtask to allow all sync code to run.
queueMicrotask(sendNow);
} else {
document.addEventListener('visibilitychange', sendNow);
if (typeof init.activateAfter === 'number' && init.activateAfter >= 0) {
timeoutHandle = setTimeout(sendNow, init.activateAfter);
}
}
if (init.signal) {
init.signal.addEventListener('abort', destroy);
}
return {
get activated() {
return activated;
},
};
};