SELF-773: standardize analytics imports (#1538)

* standardize analytics

* format
This commit is contained in:
Justin Hernandez
2025-12-30 14:04:28 -08:00
committed by GitHub
parent 9860020cd1
commit 5cdf345372
12 changed files with 147 additions and 132 deletions

View File

@@ -93,64 +93,41 @@ function validateParams(
return cleanParams(validatedProps);
}
/*
Records analytics events and screen views
In development mode, events are logged to console instead of being sent to Segment
/**
* Internal tracking function used by trackEvent and trackScreenView
* Records analytics events and screen views
* In development mode, events are logged to console instead of being sent to Segment
*/
const analytics = () => {
function _track(
type: 'event' | 'screen',
eventName: string,
properties?: Record<string, unknown>,
) {
// Validate and clean properties
const validatedProps = validateParams(properties);
function _track(
type: 'event' | 'screen',
eventName: string,
properties?: Record<string, unknown>,
) {
// Validate and clean properties
const validatedProps = validateParams(properties);
if (__DEV__) {
console.log(`[DEV: Analytics ${type.toUpperCase()}]`, {
name: eventName,
properties: validatedProps,
});
return;
}
if (!segmentClient) {
return;
}
const trackMethod = (e: string, p?: JsonMap) =>
type === 'screen'
? segmentClient.screen(e, p)
: segmentClient.track(e, p);
if (!validatedProps) {
// you may need to remove the catch when debugging
return trackMethod(eventName).catch(console.info);
}
// you may need to remove the catch when debugging
trackMethod(eventName, validatedProps).catch(console.info);
if (__DEV__) {
console.log(`[DEV: Analytics ${type.toUpperCase()}]`, {
name: eventName,
properties: validatedProps,
});
return;
}
return {
// Using LiteralCheck will allow constants but not plain string literals
trackEvent: (eventName: string, properties?: TrackEventParams) => {
_track('event', eventName, properties);
},
trackScreenView: (
screenName: string,
properties?: Record<string, unknown>,
) => {
_track('screen', screenName, properties);
},
flush: () => {
if (!__DEV__ && segmentClient) {
segmentClient.flush();
}
},
};
};
if (!segmentClient) {
return;
}
const trackMethod = (e: string, p?: JsonMap) =>
type === 'screen' ? segmentClient.screen(e, p) : segmentClient.track(e, p);
export default analytics;
if (!validatedProps) {
// you may need to remove the catch when debugging
return trackMethod(eventName).catch(console.info);
}
// you may need to remove the catch when debugging
trackMethod(eventName, validatedProps).catch(console.info);
}
/**
* Cleanup function to clear event queues
@@ -160,6 +137,69 @@ export const cleanupAnalytics = () => {
eventCount = 0;
};
// --- Mixpanel NFC Analytics ---
export const configureNfcAnalytics = async () => {
if (!MIXPANEL_NFC_PROJECT_TOKEN || mixpanelConfigured) return;
const enableDebugLogs =
String(ENABLE_DEBUG_LOGS ?? '')
.trim()
.toLowerCase() === 'true';
// Check if PassportReader and configure method exist (Android doesn't have configure)
if (PassportReader && typeof PassportReader.configure === 'function') {
try {
// iOS configure method only accepts token and enableDebugLogs
// Android doesn't have this method at all
await Promise.resolve(
PassportReader.configure(MIXPANEL_NFC_PROJECT_TOKEN, enableDebugLogs),
);
} catch (error) {
console.warn('Failed to configure NFC analytics:', error);
}
}
setupFlushPolicies();
mixpanelConfigured = true;
};
/**
* Flush any pending analytics events immediately
*/
export const flush = () => {
if (!__DEV__ && segmentClient) {
segmentClient.flush();
}
};
/**
* @deprecated Use named exports (trackEvent, trackScreenView, flush) instead
* Factory function that returns analytics methods
* Kept for backward compatibility
*/
const analytics = () => {
return {
trackEvent,
trackScreenView,
flush,
};
};
export default analytics;
/**
* Consolidated analytics flush function that flushes both Segment and Mixpanel events
* This should be called when you want to ensure all analytics events are sent immediately
*/
export const flushAllAnalytics = () => {
// Flush Segment analytics
flush();
// Never flush Mixpanel during active NFC scanning to prevent interference
if (!isNfcScanningActive) {
flushMixpanelEvents().catch(console.warn);
}
};
const setupFlushPolicies = () => {
AppState.addEventListener('change', (state: AppStateStatus) => {
// Never flush during active NFC scanning to prevent interference
@@ -221,46 +261,6 @@ const flushMixpanelEvents = async () => {
}
};
// --- Mixpanel NFC Analytics ---
export const configureNfcAnalytics = async () => {
if (!MIXPANEL_NFC_PROJECT_TOKEN || mixpanelConfigured) return;
const enableDebugLogs =
String(ENABLE_DEBUG_LOGS ?? '')
.trim()
.toLowerCase() === 'true';
// Check if PassportReader and configure method exist (Android doesn't have configure)
if (PassportReader && typeof PassportReader.configure === 'function') {
try {
// iOS configure method only accepts token and enableDebugLogs
// Android doesn't have this method at all
await Promise.resolve(
PassportReader.configure(MIXPANEL_NFC_PROJECT_TOKEN, enableDebugLogs),
);
} catch (error) {
console.warn('Failed to configure NFC analytics:', error);
}
}
setupFlushPolicies();
mixpanelConfigured = true;
};
/**
* Consolidated analytics flush function that flushes both Segment and Mixpanel events
* This should be called when you want to ensure all analytics events are sent immediately
*/
export const flushAllAnalytics = () => {
// Flush Segment analytics
const { flush: flushAnalytics } = analytics();
flushAnalytics();
// Never flush Mixpanel during active NFC scanning to prevent interference
if (!isNfcScanningActive) {
flushMixpanelEvents().catch(console.warn);
}
};
/**
* Set NFC scanning state to prevent analytics flush interference
*/
@@ -277,6 +277,18 @@ export const setNfcScanningActive = (active: boolean) => {
}
};
/**
* Track an analytics event
* @param eventName - Name of the event to track
* @param properties - Optional properties to attach to the event
*/
export const trackEvent = (
eventName: string,
properties?: TrackEventParams,
) => {
_track('event', eventName, properties);
};
export const trackNfcEvent = async (
name: string,
properties?: Record<string, unknown>,
@@ -302,3 +314,15 @@ export const trackNfcEvent = async (
eventQueue.push({ name, properties });
}
};
/**
* Track a screen view
* @param screenName - Name of the screen to track
* @param properties - Optional properties to attach to the screen view
*/
export const trackScreenView = (
screenName: string,
properties?: Record<string, unknown>,
) => {
_track('screen', screenName, properties);
};