নির্ভরযোগ্যভাবে সম্পূর্ণ সেশন অ্যানালিটিক্স ও টেলিমেট্রি পরিমাপ করা

ওয়েব ফিচার: fetchLater AbortController এবং AbortSignal

অ্যানালিটিক্স, Core Web Vitals এবং টেলিমেট্রি ডেটা নির্ভরযোগ্যভাবে ট্র্যাক করতে, যা কোনও ওয়েব পেজে ব্যবহারকারীর সম্পূর্ণ ভিজিট কভার করে (শুধু পেজ লোড হওয়া পর্যন্ত নয়), fetchLater() API ব্যবহার করুন।

যেসব ক্ষেত্রে উত্তরের প্রয়োজন নেই এবং ডেলিভারির সময় জরুরি নয়, সেখানে সার্ভারে ডেটা পাঠানোর সবচেয়ে নির্ভরযোগ্য উপায় হল fetchLater() API। এটি ব্যবহারকারীর অ্যানালিটিক্স, টেলিমেট্রি, সমস্যা ট্র্যাকিং এবং Core Web Vitals-এর মতো পারফর্ম্যান্স মেট্রিকের মতো ডেটার ক্ষেত্রে প্রযোজ্য।

unload ইভেন্ট লিসেনারে <img> পিক্সেল তৈরি করার মতো পুরনো টেকনিক অত্যন্ত অবিশ্বাস্য (বিশেষ করে মোবাইলে) এবং পারফর্ম্যান্সে নেতিবাচক প্রভাব ফেলতে পারে (bfcache-এর জন্য পেজ অনুপযুক্ত করে)।

কীভাবে প্রয়োগ করতে হয়

  1. অনুরোধ শিডিউল করুন: প্রাসঙ্গিক ডেটা উপলভ্য হওয়ার সাথে সাথেই আপনার ডেটা পেলোড সহ fetchLater() কল করুন। এটি পরে পাঠানোর জন্য ডেটা সারিবদ্ধ করে।

  2. প্রয়োজন অনুযায়ী পেলোড আপডেট করুন: ব্যবহারকারী আরও ডেটা তৈরি করলে বা স্ট্যাটাস পরিবর্তন হলে, আগে থেকে শিডিউল করা অনুরোধ বাতিল করে দিন এবং সম্পূর্ণ আপডেট করা স্ন্যাপশট সহ fetchLater() আবার কল করুন।

  3. বাকিটা ব্রাউজারকে ম্যানেজ করতে দিন: ব্যবহারকারী নেভিগেট করে বেরিয়ে গেলে বা ট্যাব বন্ধ করে দিলে, ব্রাউজার আপনার সবচেয়ে সাম্প্রতিক fetchLater() কল থেকে নির্ভরযোগ্যভাবে পেলোড পাঠাবে।

কোডের উদাহরণ

এই কোডটি কোনও ব্যবহারকারীর কোনও পৃষ্ঠা দেখার সেশনের সময়কাল পরিমাপ করে, fetchLater() ব্যবহার করে প্রতি ১০ সেকেন্ডে আপডেট করা সেশনের সময়কাল সহ একটি নতুন বিকন সারিবদ্ধ করে।

const ANALYTICS_ENDPOINT = '/path/to/analytics/endpoint';

const sessionData = {
  duration: 0,
  id: crypto.randomUUID(),
};

let fetchLaterController = null;

function queueBeacon() {
  // Abort any pending beacons before creating a new one.
  if (fetchLaterController) {
    fetchLaterController.abort();
  }
  fetchLaterController = new AbortController();

  // Update session duration to the current page time.
  sessionData.duration = performance.now();

  // Schedule a fetch for the data payload to be sent later.
  // IMPORTANT: wrap the call in a try/catch to handle quota errors.
  try {
    fetchLater(ANALYTICS_ENDPOINT, {
      method: 'POST',
      headers: {'content-type': 'application/json'},
      body: JSON.stringify(sessionData),
      signal: fetchLaterController.signal,
    });
  } catch (error) {
    // Handle errors as needed.
  }
}

// Update the session data and queue a new beacon every 10 seconds.
setInterval(queueBeacon, 10000);

পেশাদার পদ্ধতি

  • এমন যেকোনও পরিস্থিতিতে সার্ভারে ডেটা পাঠাতে fetchLater() ব্যবহার করুন যেখানে উত্তর দেওয়া প্রয়োজনীয় নয় এবং ডেটা অবিলম্বে পাঠানো গুরুত্বপূর্ণ নয়।
  • ব্যবহারকারী পৃষ্ঠা ছেড়ে চলে যাওয়ার আগে ডেটা আপডেট করার প্রয়োজন হতে পারে এমন ক্ষেত্রে মুলতুবি থাকা ফেচ বাতিল করতে AbortController ব্যবহার করুন
  • কোটা যাতে অতিক্রম না করে তার জন্য পেলোডের সাইজ যতটা সম্ভব কম রাখুন (বর্তমানে প্রতিটি অরিজিনের জন্য প্রায় ৬৪ কেবি)।
  • কোটা সংক্রান্ত সমস্যা ম্যানেজ করতে fetchLater()-এ করা কল try/catch-এ র‍্যাপ করুন।
  • DO ফিচার globalThis-এ fetchLater()-এর উপস্থিতি শনাক্ত করে এবং যেসব ব্রাউজারে API কাজ করে না সেগুলির জন্য একটি ফলব্যাক স্ট্র্যাটেজি প্রয়োগ করে।
  • অনুরোধের বডির জন্য ReadableStream অবজেক্ট ব্যবহার করবেন না, কারণ এটি করলে সমস্যা হবে।

ব্রাউজার সাপোর্ট ও ফলব্যাক স্ট্র্যাটেজি

fetchLater() আপনার বেসলাইন টার্গেট পূরণ না করলে, একটি ফলব্যাক স্ট্র্যাটেজি প্রয়োজন। তবে, এই API-এর উন্নত নির্ভরযোগ্যতা এবং পারফর্ম্যান্সের সুবিধা বিবেচনা করে, ব্রাউজার এটি সাপোর্ট করলে fetchLater() ব্যবহার করা উচিত।

সাজেস্ট করা ফলব্যাক স্ট্র্যাটেজি হল নিচে উল্লেখ করা পলিফিল ব্যবহার করা, যা keepalive বা navigator.sendBeacon()-এর সাথে fetch() ব্যবহার করে ইন্টার্নালি কাজ না করা ব্রাউজার ম্যানেজ করে। আপনার কোডকে সরাসরি fetchLater() কল করতে হবে — কখনই fetch(), sendBeacon() বা অন্য কোনও বিকন API নিজে কল করবেন না।

fetchLater() পলিফিল

নিম্নলিখিত ন্যূনতম fetchLater() পলিফিল ব্যবহার করুন, যা কাজ করে না এমন ব্রাউজারে যতটা সম্ভব API প্রয়োগ করে।

এই পলিফিলের সাথে একমাত্র উল্লেখযোগ্য আচরণগত পার্থক্য হল যে ব্যবহারকারী কখন চলে যান তা শনাক্ত করতে এটি visibilitychange ব্যবহার করে, ব্রাউজারের নেটিভ আনলোড হ্যান্ডলিংয়ের উপর নির্ভর করার পরিবর্তে। এটি একটি ইন্টার্নাল ইমপ্লিমেন্টেশন সংক্রান্ত বিবরণ — আপনার কোডকে visibilitychange বা অন্য কোনও পৃষ্ঠা লাইফসাইকেল ইভেন্ট শুনতে হবে না। শুধু fetchLater() কল করুন এবং পলিফিল ডেলিভারি ম্যানেজ করে।

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