UNPKG

@scaleway/use-analytics

Version:

A small hook to handle events analytics

125 lines (124 loc) 3.81 kB
import { jsx } from "react/jsx-runtime"; import { RudderAnalytics } from "@rudderstack/analytics-js"; import { useState, useEffect, useMemo, createContext, useContext } from "react"; import { useDeepCompareEffectNoCheck } from "use-deep-compare-effect"; import { pluginsSDKBaseURL, destSDKBaseURL } from "../constants.js"; import { defaultLoadOptions, defaultConsentOptions } from "./constants.js"; import { userMigrationsTraits } from "./segments/userMigrationsTraits.js"; const AnalyticsContext = createContext( void 0 ); function useAnalytics() { const context = useContext( // @ts-expect-error Here we force cast the generic onto the useContext because the context is a // global variable and cannot be generic AnalyticsContext ); if (context === void 0) { throw new Error("useAnalytics must be used within a AnalyticsProvider"); } return context; } function AnalyticsProvider({ children, settings, loadOptions, shouldRenderOnlyWhenReady = false, needConsent = true, onError, onEventError, allowedConsents, deniedConsents, events, onLoaded, timeout }) { const [isAnalyticsReady, setIsAnalyticsReady] = useState(false); const [internalAnalytics, setAnalytics] = useState( void 0 ); useEffect(() => { let timer; if (!isAnalyticsReady && !internalAnalytics && timeout) { if (shouldRenderOnlyWhenReady) { timer = setTimeout(() => setIsAnalyticsReady(true), timeout); onError?.(new Error("Analytics Setup Timeout")); } } return () => { clearTimeout(timer); }; }, [ isAnalyticsReady, internalAnalytics, setIsAnalyticsReady, shouldRenderOnlyWhenReady, timeout, onError ]); const shouldLoad = useMemo(() => { if (needConsent) { return false; } return !!settings?.writeKey; }, [settings?.writeKey, needConsent]); useDeepCompareEffectNoCheck(() => { if (shouldLoad && settings) { const analytics = new RudderAnalytics(); analytics.load(settings.writeKey, settings.cdnURL, { ...defaultLoadOptions, configUrl: settings.cdnURL, destSDKBaseURL: destSDKBaseURL(settings.cdnURL), pluginsSDKBaseURL: pluginsSDKBaseURL(settings.cdnURL), onLoaded: (rudderAnalytics) => { userMigrationsTraits(rudderAnalytics); rudderAnalytics.consent({ ...defaultConsentOptions, consentManagement: { enabled: true, allowedConsentIds: allowedConsents, deniedConsentIds: deniedConsents } }); onLoaded(rudderAnalytics); setIsAnalyticsReady(true); }, ...loadOptions }); analytics.ready(() => { setAnalytics(analytics); setIsAnalyticsReady(true); }); } }, [settings, loadOptions, shouldLoad]); const value = useMemo(() => { const curiedEvents = Object.entries(events).reduce( (acc, [eventName, eventFn]) => ({ ...acc, [eventName]: eventFn(internalAnalytics, onEventError) }), {} ); return { analytics: internalAnalytics, events: curiedEvents, isAnalyticsReady }; }, [events, internalAnalytics, isAnalyticsReady, onEventError]); const shouldRender = !shouldRenderOnlyWhenReady || isAnalyticsReady && !needConsent; useDeepCompareEffectNoCheck(() => { internalAnalytics?.consent({ consentManagement: { enabled: true, allowedConsentIds: allowedConsents, deniedConsentIds: deniedConsents } }); }, [allowedConsents, deniedConsents]); return /* @__PURE__ */ jsx(AnalyticsContext.Provider, { value, children: shouldRender ? children : null }); } export { AnalyticsProvider, AnalyticsProvider as default, useAnalytics };