FrontendPro

94Implement an analytics SDK with event batching and sendBeacon fallback

mediumAbout 45 minutesCodinganalyticsbatchingsendBeaconpage-lifecycle

Problem

Implement createAnalytics({ endpoint, batchSize = 10, flushInterval = 5000, maxQueue = 500, transport, target = window, doc = document }) returning { track(name, props), flush(), destroy(), queueSize }.

  • track adds { id, name, props, ts } to a queue (id from crypto.randomUUID(), ts from Date.now()).
  • The queue is sent as one request when it reaches batchSize, and at least every flushInterval ms while it is not empty.
  • Normal sends use transport.fetch(endpoint, { method: "POST", body, keepalive: true, headers }) with a JSON body { events: [...] }. If it fails (network error or non-2xx), put the events back at the front of the queue so they are sent next time.
  • When the page is being hidden or unloaded (visibilitychange with doc.visibilityState === "hidden", or pagehide on target), flush with transport.sendBeacon(endpoint, blob). If sendBeacon returns false (or is missing), fall back to the keepalive fetch.
  • The queue never holds more than maxQueue events; drop the oldest when it overflows.
  • destroy() stops the timer and removes the listeners.

transport defaults to { fetch: window.fetch.bind(window), sendBeacon: navigator.sendBeacon?.bind(navigator) }; tests pass fakes.

Try it yourself

Write your solution, run it, then submit to check it against the tests.

App.jsxReact + DOM

Step-by-step

Sending a request per event costs radio wake-ups and server load. track only pushes onto an array and decides whether a flush is needed.

Unlock the full solution

What's inside

  • Step-by-step
  • Approach
  • Solution
  • Complexity
  • Edge cases
  • Follow-up questions
  • Tests

Includes 2 code listings, 5 edge cases, 4 follow-up questions.

One-time payment by UPI, card or net banking. Launch price.

All 150 answersOne payment, yours forever