1import RudderAnalytics from '@expo/rudder-sdk-node'; 2import os from 'os'; 3import { v4 as uuidv4 } from 'uuid'; 4 5import UserSettings from '../../api/user/UserSettings'; 6import { env } from '../env'; 7 8const PLATFORM_TO_ANALYTICS_PLATFORM: { [platform: string]: string } = { 9 darwin: 'Mac', 10 win32: 'Windows', 11 linux: 'Linux', 12}; 13 14let client: RudderAnalytics | null = null; 15let identified = false; 16let identifyData: { 17 userId: string; 18 deviceId: string; 19 traits: Record<string, any>; 20} | null = null; 21 22function getClient(): RudderAnalytics { 23 if (client) { 24 return client; 25 } 26 27 client = new RudderAnalytics( 28 env.EXPO_STAGING || env.EXPO_LOCAL 29 ? '24TKICqYKilXM480mA7ktgVDdea' 30 : '24TKR7CQAaGgIrLTgu3Fp4OdOkI', // expo unified 31 'https://cdp.expo.dev/v1/batch', 32 { 33 flushInterval: 300, 34 } 35 ); 36 37 // Install flush on exit... 38 process.on('SIGINT', () => client?.flush?.()); 39 process.on('SIGTERM', () => client?.flush?.()); 40 41 return client; 42} 43 44export async function setUserDataAsync(userId: string, traits: Record<string, any>): Promise<void> { 45 if (env.EXPO_NO_TELEMETRY) { 46 return; 47 } 48 49 const deviceId = await UserSettings.getAnonymousIdentifierAsync(); 50 51 identifyData = { 52 userId, 53 deviceId, 54 traits, 55 }; 56 57 ensureIdentified(); 58} 59 60export function logEvent( 61 event: // TODO: revise 62 | 'action' 63 | 'Open Url on Device' 64 | 'Start Project' 65 | 'Serve Manifest' 66 | 'dev client start command' 67 | 'Serve Expo Updates Manifest', 68 properties: Record<string, any> = {} 69): void { 70 if (env.EXPO_NO_TELEMETRY) { 71 return; 72 } 73 ensureIdentified(); 74 75 const { userId, deviceId } = identifyData ?? {}; 76 const commonEventProperties = { source_version: process.env.__EXPO_VERSION, source: 'expo' }; 77 78 const identity = { userId: userId ?? undefined, anonymousId: deviceId ?? uuidv4() }; 79 getClient().track({ 80 event, 81 properties: { ...properties, ...commonEventProperties }, 82 ...identity, 83 context: getContext(), 84 }); 85} 86 87function ensureIdentified(): void { 88 if (env.EXPO_NO_TELEMETRY || identified || !identifyData) { 89 return; 90 } 91 92 getClient().identify({ 93 userId: identifyData.userId, 94 anonymousId: identifyData.deviceId, 95 traits: identifyData.traits, 96 }); 97 identified = true; 98} 99 100function getContext(): Record<string, any> { 101 const platform = PLATFORM_TO_ANALYTICS_PLATFORM[os.platform()] || os.platform(); 102 return { 103 os: { name: platform, version: os.release() }, 104 device: { type: platform, model: platform }, 105 app: { name: 'expo', version: process.env.__EXPO_VERSION }, 106 }; 107} 108