Files
myeasycms-v2/apps/web/components/analytics-provider.tsx
gbuomprisco 8647c13896 Integrate user traits into event payloads
Extends the user traits (e.g., email) in dispatch events and integrates monitoring to identify users alongside emitting events. Additionally, ensures the analytics service captures these traits when identifying users.
2024-08-16 11:00:37 +02:00

96 lines
2.4 KiB
TypeScript

'use client';
import { useEffect } from 'react';
import { usePathname, useSearchParams } from 'next/navigation';
import { analytics } from '@kit/analytics';
import { AppEvent, AppEventType, ConsumerProvidedEventTypes, useAppEvents } from '@kit/shared/events';
type AnalyticsMapping<
T extends ConsumerProvidedEventTypes = NonNullable<unknown>,
> = {
[K in AppEventType<T>]?: (event: AppEvent<T, K>) => unknown;
};
/**
* Hook to subscribe to app events and map them to analytics actions
* @param mapping
*/
function useAnalyticsMapping<T extends ConsumerProvidedEventTypes>(
mapping: AnalyticsMapping<T>,
) {
const appEvents = useAppEvents<T>();
useEffect(() => {
const subscriptions = Object.entries(mapping).map(
([eventType, handler]) => {
appEvents.on(eventType as AppEventType<T>, handler);
return () => appEvents.off(eventType as AppEventType<T>, handler);
},
);
return () => {
subscriptions.forEach((unsubscribe) => unsubscribe());
};
}, [appEvents, mapping]);
}
/**
* Define a mapping of app events to analytics actions
* Add new mappings here to track new events in the analytics service from app events
*/
const analyticsMapping: AnalyticsMapping = {
'user.signedIn': (event) => {
const { userId, ...traits } = event.payload;
if (userId) {
return analytics.identify(userId, traits);
}
},
'user.signedUp': (event) => {
return analytics.trackEvent(event.type, event.payload);
},
'checkout.started': (event) => {
return analytics.trackEvent(event.type, event.payload);
},
'user.updated': (event) => {
return analytics.trackEvent(event.type, event.payload);
},
};
/**
* Provider for the analytics service
*/
export function AnalyticsProvider(props: React.PropsWithChildren) {
// Subscribe to app events and map them to analytics actions
useAnalyticsMapping(analyticsMapping);
// Report page views to the analytics service
useReportPageView((url) => analytics.trackPageView(url));
// Render children
return props.children;
}
/**
* Hook to report page views to the analytics service
* @param reportAnalyticsFn
*/
function useReportPageView(reportAnalyticsFn: (url: string) => unknown) {
const pathname = usePathname();
const searchParams = useSearchParams();
useEffect(() => {
const url = [pathname, searchParams.toString()].filter(Boolean).join('?');
reportAnalyticsFn(url);
}, [pathname, reportAnalyticsFn, searchParams]);
}