ข้อมูลการวิเคราะห์ การวัดและส่งข้อมูลทางไกล และข้อมูลการวิเคราะห์ Core Web Vitals ส่วนใหญ่มีความสำคัญต่ำกว่าการตอบสนองต่อผู้ใช้ คุณจึงเลื่อนการส่งข้อมูลดังกล่าวออกไปได้อย่างปลอดภัยจนกว่าผู้ใช้จะออกจากหน้าเว็บ ข้อยกเว้นสำหรับเรื่องนี้คือหากคุณต้องการนำเสนอข้อมูลอัปเดตแบบเรียลไทม์ ซึ่งในกรณีนี้ความทันท่วงทีเป็นสิ่งสำคัญ
วิธีที่ดีที่สุดในการอัปเดตข้อมูลวิเคราะห์แบบเรียลไทม์โดยที่ยังลดบีคอนให้เหลือน้อยที่สุดคือการใช้ fetchLater() กับตัวเลือกการกำหนดค่า activateAfter ซึ่งจะช่วยให้คุณลดการตีกลับและรวมเหตุการณ์ Analytics ทั้งหมดที่เกิดขึ้นภายในกรอบเวลาที่กำหนดไว้เป็นบีคอนเดียวได้อย่างมีประสิทธิภาพ ซึ่งจะส่งได้อย่างน่าเชื่อถือแม้ว่าผู้ใช้จะออกจากหน้าเว็บก่อนที่ระยะหมดเวลาจะสิ้นสุดลง
วิธีการนำไปใช้งาน
กำหนดเวลาคำขอ: ทันทีที่ข้อมูลวิเคราะห์ที่เกี่ยวข้องพร้อมใช้งาน ให้เรียกใช้
fetchLater()พร้อมเพย์โหลดข้อมูลและส่งค่าactivateAfterซึ่งจะจัดคิวข้อมูลที่จะส่งหลังจากผ่านระยะเวลาดังกล่าวไปแล้ว หรือหากผู้ใช้ออกจากหน้าเว็บก่อนหน้านั้นรวมเหตุการณ์หลายรายการเข้าด้วยกัน: หากเหตุการณ์ Analytics ใหม่เกิดขึ้นก่อนที่ระยะหมดเวลา
activateAfterจะสิ้นสุดลง ให้ยกเลิกคำขอที่กำหนดเวลาไว้ก่อนหน้านี้และเรียกใช้fetchLater()อีกครั้ง (โดยใช้ค่าactivateAfterเดียวกัน) โดยมีคิวเหตุการณ์ทั้งหมดในเพย์โหลดเดียวรีเซ็ตคิวเหตุการณ์เมื่อหมดเวลา: หากมีเหตุการณ์ Analytics ใหม่เกิดขึ้นหลังจากส่งบีคอนที่กำหนดเวลาไว้เรียบร้อยแล้ว (นั่นคือ ค่า
activatedของผลลัพธ์fetchLater()คือtrue) ให้รีเซ็ตคิวเหตุการณ์ปล่อยให้เบราว์เซอร์จัดการส่วนที่เหลือ: หากผู้ใช้ออกจากหน้าหรือปิดแท็บก่อนที่ระยะหมดเวลา
activateAfterจะสิ้นสุดลง เบราว์เซอร์จะยังคงส่งเพย์โหลดจากการเรียกfetchLater()ล่าสุดได้อย่างน่าเชื่อถือ
โค้ดตัวอย่าง
โค้ดนี้จะติดตามเหตุการณ์ load และ click ทั้งหมดในหน้าเว็บ และจัดกลุ่มเหตุการณ์ทั้งหมดที่เกิดขึ้นภายในระยะหมดเวลา 10 วินาทีเข้าด้วยกัน
// 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)});
});
แนวทางปฏิบัติแนะนำ
- ควรใช้
fetchLater()โดยตั้งค่าตัวเลือกactivateAfterเป็นกลุ่มเหตุการณ์ Analytics หลายรายการที่เกิดขึ้นใกล้เคียงกัน - ควรใช้
AbortControllerเพื่อยกเลิกการดึงข้อมูลที่รอดำเนินการในกรณีที่เกิดเหตุการณ์ Analytics ใหม่ - ควรตรวจสอบว่าคุณไม่ได้รวมเหตุการณ์ไว้ด้วยกันมากเกินไปและเกินโควต้า
fetchLater()(ปัจจุบันอยู่ที่ประมาณ 64 KB ต่อต้นทาง) - ควรรวมการเรียกไปยัง
fetchLater()ไว้ในtry/catchเพื่อจัดการข้อผิดพลาดเกี่ยวกับโควต้า - ควรใช้ฟีเจอร์ตรวจหาการมีอยู่ของ
fetchLater()ในglobalThisและใช้กลยุทธ์สำรองสำหรับเบราว์เซอร์ที่ไม่รองรับ API - อย่าใช้ออบเจ็กต์
ReadableStreamสำหรับเนื้อหาคำขอ เนื่องจากจะทำให้เกิดข้อผิดพลาด
การรองรับเบราว์เซอร์และกลยุทธ์สำรอง
ดังนั้น โดยทั่วไปจึงต้องมีกลยุทธ์สำรอง
อย่างไรก็ตาม เนื่องจาก API นี้มีประโยชน์ด้านความน่าเชื่อถือและประสิทธิภาพที่ดีขึ้น คุณจึงควรใช้ fetchLater() หากเบราว์เซอร์รองรับ
fetchLater() polyfill
ใช้ Polyfill fetchLater() ขั้นต่ำต่อไปนี้ ซึ่งจะใช้ API อย่างใกล้เคียงที่สุดในเบราว์เซอร์ที่ไม่รองรับ
ความแตกต่างด้านลักษณะการทำงานที่สำคัญเพียงอย่างเดียวของ Polyfill นี้คือ แทนที่จะส่งเพย์โหลดเมื่อผู้ใช้ออกจากหน้าเว็บ ระบบจะส่งเพย์โหลดเมื่อ visibilityState ของหน้าเว็บเปลี่ยนเป็น "ซ่อน" เนื่องจากเป็นสัญญาณสิ้นสุดเซสชันที่เชื่อถือได้มากที่สุดซึ่งมีให้บริการอย่างแพร่หลายในปัจจุบัน
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;
},
};
};