Every public method (load, identify, track, show, hide, shutdown, setAttribute, …) must be safe to call before the provider's CDN script has finished booting. Calls buffered into an internal queue and drained in-order once the underlying global becomes real.
Evidence from competing libraries (dozens of bugs we preempt)
Contract
load() returns a Promise<void> that resolves only when the provider's real API object is exposed.
- Every other method synchronously enqueues, returns
Promise<void> that resolves after drain.
- Queue is per-provider singleton keyed by config hash.
- For queue-native providers (Crisp
\$crisp.push, HubSpot _hsq.push) we use their queue directly — we never call methods on the replaced global.
- Acceptance test: call every method inside
Promise.resolve().then() before awaiting load() — all must land in order.
Every public method (
load,identify,track,show,hide,shutdown,setAttribute, …) must be safe to call before the provider's CDN script has finished booting. Calls buffered into an internal queue and drained in-order once the underlying global becomes real.Evidence from competing libraries (dozens of bugs we preempt)
devrnt/react-use-intercom#635— "Data is lost because Intercom is booted too late (update and track sends before intercom is booted)" Data is lost because Intercom is booted to late (update and track sends before intercom is booted) devrnt/react-use-intercom#635devrnt/react-use-intercom#747— "AutoBoot is not booting Intercom by the timetrackEventis called" (regression in 5.4.1) AutoBoot is not booting Intercom by the time trackEvent is called devrnt/react-use-intercom#747devrnt/react-use-intercom#824— "showNewMessagefails on first call, works only from second time" Issue: Intercom showNewMessages fails on first call, works only from second time devrnt/react-use-intercom#824crisp-im/crisp-sdk-web#11— "window.\$crisp.is is not a function" —\$crispstill the bootstrap array window.$crisp.is is not a function crisp-im/crisp-sdk-web#11crisp-im/crisp-sdk-web#28— "session.reset error" — wrapper called\$crisp.do()instead ofpush(["do", ...])session.reset error crisp-im/crisp-sdk-web#28tawk/tawk-messenger-react#9— "open messenger programmatically" (silently no-ops before boot) open messenger programmatically tawk/tawk-messenger-react#9tawk/tawk-messenger-react#26— "Changes throughsetAttributesonly sporadically reflected" Changes made through setAttributes are only reflected sporadically in tawkto dashboard tawk/tawk-messenger-react#26nhagen/react-intercom#96— "window.Intercom('update')not working" window.intercom("update") not working nhagen/react-intercom#96Contract
load()returns aPromise<void>that resolves only when the provider's real API object is exposed.Promise<void>that resolves after drain.\$crisp.push, HubSpot_hsq.push) we use their queue directly — we never call methods on the replaced global.Promise.resolve().then()before awaitingload()— all must land in order.