import type { EnrichmentPlugin, Event, ReactNativeClient, ReactNativeConfig, } from '@amplitude/analytics-core'; import { Platform } from 'react-native'; import { forwardEvent, initAsync, screen, boot, enable, disable } from '.'; import NativePluginEngagementReactNative from './NativePluginEngagementReactNative'; import { Logger, type AmplitudeLogger } from './logger'; import type { EventSubscription } from 'react-native'; import type { AmplitudeBootOptions, AmplitudeInitOptions } from './types'; import * as Constants from './constants'; export class AmplitudeEngagementPlugin implements EnrichmentPlugin { name = 'AmplitudeEngagementPlugin'; type = 'enrichment' as const; initOptions?: AmplitudeInitOptions; client?: ReactNativeClient; userId?: string; deviceId?: string; sessionId?: number; userProperties?: Record; logger: AmplitudeLogger = new Logger('AmplitudeEngagementPlugin'); trackEventSubscription: EventSubscription | null = null; constructor(initOptions?: AmplitudeInitOptions) { this.initOptions = initOptions; } async setup( config: ReactNativeConfig, client: ReactNativeClient ): Promise { try { /* IMPORTANT do not take serverUrl from Analytics config, since Engagement uses its own backend */ const { apiKey, serverZone } = config; this.logger.log( `AmplitudeEngagementPlugin#setup; apiKey=${apiKey}, serverZone=${serverZone}` ); await initAsync(apiKey, { serverZone, ...this.initOptions, }); this.client = client; if (this.trackEventSubscription) { this.trackEventSubscription.remove(); } this.trackEventSubscription = NativePluginEngagementReactNative.onTrackEvent((event) => { if (!this.client) { this.logger.error( 'AmplitudeEngagementPlugin#onIdentityChanged client is not initialized' ); return; } const nativeTag = Platform.OS === 'ios' ? `${Constants.SDK_IOS_LIBRARY}/${Constants.SDK_IOS_VERSION}` : `${Constants.SDK_ANDROID_LIBRARY}/${Constants.SDK_ANDROID_VERSION}`; const rnTag = `${Constants.SDK_LIBRARY}/${Constants.SDK_VERSION}`; // Add the Guides & Surveys library version to events const eventProperties = { ...event.event_properties, '[Guides-Surveys] Library': `${rnTag}_${nativeTag}`, }; this.client?.track(event.event_type, eventProperties); }); // TODO: grab identity from client when available -- need to wait until it's added. // Need to wait until https://amplitude.atlassian.net/browse/AMP-133461 is resolved // then; follow the same pattern as in the `AmplitudeEngagementPlugin` in the Swift/iOS code } catch (error) { this.logger.error( 'AmplitudeEngagementPlugin#setup failed to initialize', error ); } } // TODO: for now, you must call `boot()` manually // but once we have access to the identity from the client, // we can call `boot()` automatically in `setup` and `onIdentityChanged` boot(options: AmplitudeBootOptions): void; boot(user_id?: string, device_id?: string): void; boot( optionsOrUserId?: AmplitudeBootOptions | string, device_id?: string ): void { if (typeof optionsOrUserId === 'object' && optionsOrUserId !== null) { boot(optionsOrUserId); } else { boot(optionsOrUserId, device_id); } } /** Re-enable the SDK after it has been disabled using disable(). */ enable(): void { enable(); } /** Temporarily disable the SDK; hide guides/surveys and prevent new ones. Can be re-enabled with enable(). */ disable(): void { disable(); } async execute(context: Event): Promise { this.logger.log( `AmplitudeEngagement#execute event=${JSON.stringify(context)}` ); if ( context.event_type === '[Amplitude] Screen Viewed' && typeof context.event_properties?.['[Amplitude] Screen Name'] === 'string' ) { const screenName = context.event_properties[ '[Amplitude] Screen Name' ] as string; if (this.initOptions?.ignoreAnalyticsAutomaticScreenTracking) { this.logger.log( `-- ignoring [Amplitude] Screen Viewed event because ignoreAnalyticsAutomaticScreenTracking is enabled` ); return context; } screen(screenName); } forwardEvent(context); return context; } }