diff --git a/frontend/src/concepts/analyticsTracking/segmentIOUtils.tsx b/frontend/src/concepts/analyticsTracking/segmentIOUtils.tsx index 080ebeb379..cfec33f43c 100644 --- a/frontend/src/concepts/analyticsTracking/segmentIOUtils.tsx +++ b/frontend/src/concepts/analyticsTracking/segmentIOUtils.tsx @@ -94,7 +94,7 @@ export const fireIdentifyEvent = (properties: IdentifyEventProperties): void => const clusterID = window.clusterID ?? ''; if (DEV_MODE) { /* eslint-disable-next-line no-console */ - console.log(`Identify event triggered`); + console.log(`Identify event triggered: ${JSON.stringify(properties)}`); } else if (window.analytics) { window.analytics.identify(properties.anonymousID, { clusterID }); } diff --git a/frontend/src/concepts/analyticsTracking/trackingProperties.ts b/frontend/src/concepts/analyticsTracking/trackingProperties.ts index 81c26f44e9..17daeb3a16 100644 --- a/frontend/src/concepts/analyticsTracking/trackingProperties.ts +++ b/frontend/src/concepts/analyticsTracking/trackingProperties.ts @@ -3,7 +3,10 @@ export type ODHSegmentKey = { }; export type IdentifyEventProperties = { + isAdmin: boolean; anonymousID?: string; + userId?: string; + canCreateProjects: boolean; }; export const enum TrackingOutcome { diff --git a/frontend/src/concepts/analyticsTracking/useSegmentTracking.ts b/frontend/src/concepts/analyticsTracking/useSegmentTracking.ts index d609a9a2f9..db96579a38 100644 --- a/frontend/src/concepts/analyticsTracking/useSegmentTracking.ts +++ b/frontend/src/concepts/analyticsTracking/useSegmentTracking.ts @@ -2,6 +2,7 @@ import React from 'react'; import { useAppContext } from '~/app/AppContext'; import { useAppSelector } from '~/redux/hooks'; import { fireIdentifyEvent, firePageEvent } from '~/concepts/analyticsTracking/segmentIOUtils'; +import { useTrackUser } from '~/concepts/analyticsTracking/useTrackUser'; import { useWatchSegmentKey } from './useWatchSegmentKey'; import { initSegment } from './initSegment'; @@ -10,28 +11,18 @@ export const useSegmentTracking = (): void => { const { dashboardConfig } = useAppContext(); const username = useAppSelector((state) => state.user); const clusterID = useAppSelector((state) => state.clusterID); + const userProps = useTrackUser(username); React.useEffect(() => { if (segmentKey && loaded && !loadError && username && clusterID) { - const computeUserId = async () => { - const anonymousIDBuffer = await crypto.subtle.digest( - 'SHA-1', - new TextEncoder().encode(username), - ); - const anonymousIDArray = Array.from(new Uint8Array(anonymousIDBuffer)); - return anonymousIDArray.map((b) => b.toString(16).padStart(2, '0')).join(''); - }; - window.clusterID = clusterID; initSegment({ segmentKey, enabled: !dashboardConfig.spec.dashboardConfig.disableTracking, }).then(() => { - computeUserId().then((userId) => { - fireIdentifyEvent({ anonymousID: userId }); - firePageEvent(); - }); + fireIdentifyEvent(userProps); + firePageEvent(); }); } - }, [clusterID, loadError, loaded, segmentKey, username, dashboardConfig]); + }, [clusterID, loadError, loaded, segmentKey, username, dashboardConfig, userProps]); }; diff --git a/frontend/src/concepts/analyticsTracking/useTrackUser.ts b/frontend/src/concepts/analyticsTracking/useTrackUser.ts new file mode 100644 index 0000000000..b3fa5c3b84 --- /dev/null +++ b/frontend/src/concepts/analyticsTracking/useTrackUser.ts @@ -0,0 +1,44 @@ +import React from 'react'; +import { useUser } from '~/redux/selectors'; +import { useAccessReview } from '~/api'; +import { AccessReviewResourceAttributes } from '~/k8sTypes'; +import { IdentifyEventProperties } from '~/concepts/analyticsTracking/trackingProperties'; + +export const useTrackUser = (username?: string): IdentifyEventProperties => { + const { isAdmin } = useUser(); + const [anonymousId, setAnonymousId] = React.useState(undefined); + + const createReviewResource: AccessReviewResourceAttributes = { + group: 'project.openshift.io', + resource: 'projectrequests', + verb: 'create', + }; + const [allowCreate] = useAccessReview(createReviewResource); + + React.useEffect(() => { + const computeAnonymousUserId = async () => { + const anonymousIDBuffer = await crypto.subtle.digest( + 'SHA-1', + new TextEncoder().encode(username), + ); + const anonymousIDArray = Array.from(new Uint8Array(anonymousIDBuffer)); + const aId = anonymousIDArray.map((b) => b.toString(16).padStart(2, '0')).join(''); + return aId; + }; + + if (!anonymousId) { + computeAnonymousUserId().then((val) => setAnonymousId(val)); + } + }, [username, anonymousId]); + + const props: IdentifyEventProperties = React.useMemo( + () => ({ + isAdmin, + canCreateProjects: allowCreate, + anonymousID: anonymousId, + }), + [isAdmin, allowCreate, anonymousId], + ); + + return props; +};