ज़्यादातर आंकड़ों, टेलीमेट्री, और Core Web Vitals के आंकड़ों के डेटा को उपयोगकर्ता को जवाब देने की तुलना में कम प्राथमिकता दी जाती है. इसलिए, उपयोगकर्ता के पेज छोड़ने तक, इसे भेजने में देरी की जा सकती है. हालांकि, अगर आपको रीयल-टाइम अपडेट देने हैं, तो समय पर अपडेट देना ज़रूरी है.
रीयल-टाइम में आंकड़ों के अपडेट देने का सबसे सही तरीका यह है कि बीकन को कम से कम इस्तेमाल किया जाए. इसके लिए, activateAfter कॉन्फ़िगरेशन विकल्प के साथ fetchLater() का इस्तेमाल करें. इससे, किसी तय समयावधि में होने वाले सभी Analytics इवेंट को एक ही बीकन में इकट्ठा किया जा सकता है. साथ ही, उन्हें एक साथ भेजा जा सकता है. इससे, उपयोगकर्ता के पेज छोड़ने पर भी डेटा सुरक्षित तरीके से भेजा जा सकता है. भले ही, टाइम आउट खत्म होने से पहले ही उपयोगकर्ता पेज छोड़ दे.
इन्हें कैसे लागू करें
अनुरोध शेड्यूल करना: काम का कोई भी Analytics डेटा उपलब्ध होते ही, अपने डेटा पेलोड के साथ
fetchLater()को कॉल करें औरactivateAfterवैल्यू पास करें. इससे डेटा को तय समय के बाद या उपयोगकर्ता के पेज छोड़ने पर भेजने के लिए सूची में डाल दिया जाता है.एक साथ कई इवेंट का बैच बनाएं: अगर
activateAfterटाइम आउट खत्म होने से पहले कोई नया Analytics इवेंट होता है, तो पहले से शेड्यूल किए गए अनुरोध को रद्द करें. इसके बाद, एक ही पेलोड में पूरी इवेंट सूची के साथfetchLater()को फिर से कॉल करें. इसके लिए,activateAfterकी वही वैल्यू इस्तेमाल करें जो पहले की थी.टाइम आउट खत्म होने पर, इवेंट सूची को रीसेट करें: अगर शेड्यूल किया गया बीकन सही तरीके से भेजे जाने के बाद कोई नया Analytics इवेंट होता है, तो इवेंट सूची को रीसेट करें. जैसे,
fetchLater()नतीजे कीactivatedवैल्यू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 इवेंट का बैच बनाया जा सके.- नया Analytics इवेंट होने पर, बाकी फ़ेच को रद्द करने के लिए
AbortControllerका इस्तेमाल करें. - ज़रूर देखें कि आपने एक साथ कई इवेंट का बैच न बनाया हो और
fetchLater()कोटा (फ़िलहाल, हर ऑरिजिन के लिए करीब 64 केबी) से ज़्यादा न हो. - कोटा से जुड़ी गड़बड़ियों को मैनेज करने के लिए,
fetchLater()को किए जाने वाले कॉल कोtry/catchमें रैप करें. globalThisपरfetchLater()की मौजूदगी का पता लगाने के लिए, सुविधा की पहचान करने की प्रोसेस का इस्तेमाल करें. साथ ही, एपीआई के साथ काम न करने वाले ब्राउज़र के लिए, फ़ॉलबैक रणनीति लागू करें.- अनुरोध के मुख्य हिस्से के लिए,
ReadableStreamऑब्जेक्ट का इस्तेमाल न करें. ऐसा करने पर गड़बड़ी होगी.
ब्राउज़र से जुड़ी सहायता और फ़ॉलबैक रणनीतियां
इसलिए, आम तौर पर फ़ॉलबैक रणनीति की ज़रूरत होती है.
हालांकि, इस एपीआई की बेहतर विश्वसनीयता और परफ़ॉर्मेंस के फ़ायदों को देखते हुए, अगर ब्राउज़र पर यह एपीआई काम करता है, तो fetchLater() का इस्तेमाल किया जाना चाहिए.
fetchLater() polyfill
यहां दिए गए कम से कम fetchLater() पॉलीफ़िल का इस्तेमाल करें. यह उन ब्राउज़र में एपीआई को लागू करता है जो इसे सपोर्ट नहीं करते.
इस पॉलीफ़िल के साथ व्यवहार में सिर्फ़ एक अंतर यह है कि जब उपयोगकर्ता पेज छोड़ता है, तब पेलोड भेजने के बजाय, यह पेज के 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;
},
};
};