UNPKG

@layers/react-native

Version:

React Native SDK for Layers Analytics with SKAN and ATT support

732 lines 21.2 kB
//#region ../client/src/api-types.d.ts interface BaseEvent { event: string; timestamp: string; event_id?: string; app_id: string; app_user_id?: string | undefined; session_id: string; environment: 'development' | 'staging' | 'production'; platform: 'ios' | 'android' | 'react-native'; os_version: string; app_version: string; build_number?: string; device_model: string; screen_size?: string; locale: string; install_id?: string; install_source?: string; campaign_hint?: string; referrer?: string; referrer_source?: string; utm_source?: string; utm_medium?: string; utm_campaign?: string; utm_content?: string; utm_term?: string; click_id_param?: string; idfa?: string; idfv?: string; att_status?: 'authorized' | 'denied' | 'restricted' | 'not_determined'; country_code?: string; region?: string; city?: string; properties?: Record<string, any>; } interface AppInstallEvent extends BaseEvent { event: 'app_install'; install_id: string; install_source?: string; campaign_hint?: string; } interface AppOpenEvent extends BaseEvent { event: 'app_open'; session_id: string; referrer?: string; deeplink?: string; is_first_open?: boolean; } interface AppBackgroundEvent extends BaseEvent { event: 'app_background'; session_id: string; duration_ms: number; } interface ScreenViewEvent extends BaseEvent { event: 'screen_view'; screen_name: string; prev_screen?: string; } interface DeeplinkOpenEvent extends BaseEvent { event: 'deeplink_open'; url: string; params: Record<string, string>; matched_universal_link: boolean; } interface PaywallShowEvent extends BaseEvent { event: 'paywall_show'; paywall_id: string; placement: string; ab_test?: { id: string; variant: string; }; } interface PaywallDismissEvent extends BaseEvent { event: 'paywall_dismiss'; paywall_id: string; reason: string; } interface PurchaseAttemptEvent extends BaseEvent { event: 'purchase_attempt'; product_id: string; price: number; currency: string; store: 'app_store' | 'play_store'; } interface PurchaseSuccessEvent extends BaseEvent { event: 'purchase_success'; product_id: string; price: number; currency: string; revenue: number; store: 'app_store' | 'play_store'; transaction_id: string; receipt_data?: string; } interface PurchaseFailEvent extends BaseEvent { event: 'purchase_fail'; product_id: string; error_code: string; error_domain: string; } interface TrialStartEvent extends BaseEvent { event: 'trial_start'; product_id: string; store: 'app_store' | 'play_store'; trial_period: string; } interface TrialConvertEvent extends BaseEvent { event: 'trial_convert'; product_id: string; revenue: number; currency: string; store: 'app_store' | 'play_store'; } interface SubscriptionStartEvent extends BaseEvent { event: 'subscription_start'; product_id: string; period: string; subscription_id: string; } interface SubscriptionRenewEvent extends BaseEvent { event: 'subscription_renew'; product_id: string; period: string; revenue: number; currency: string; subscription_id: string; } interface SubscriptionCancelEvent extends BaseEvent { event: 'subscription_cancel'; product_id: string; reason: string; subscription_id: string; } interface RefundEvent extends BaseEvent { event: 'refund'; product_id: string; amount: number; currency: string; transaction_id: string; } interface ContentOpenEvent extends BaseEvent { event: 'content_open'; content_type: string; content_id: string; } interface BookmarkAddEvent extends BaseEvent { event: 'bookmark_add'; content_id: string; } interface SearchEvent extends BaseEvent { event: 'search'; query: string; results_count: number; } type LayersEvent = AppInstallEvent | AppOpenEvent | AppBackgroundEvent | ScreenViewEvent | DeeplinkOpenEvent | PaywallShowEvent | PaywallDismissEvent | PurchaseAttemptEvent | PurchaseSuccessEvent | PurchaseFailEvent | TrialStartEvent | TrialConvertEvent | SubscriptionStartEvent | SubscriptionRenewEvent | SubscriptionCancelEvent | RefundEvent | ContentOpenEvent | BookmarkAddEvent | SearchEvent; interface EventsBatchPayload { events: BaseEvent[]; batch_id?: string; sent_at: string; } interface UserPropertiesPayload { app_user_id?: string | undefined; app_id: string; properties: Record<string, any>; timestamp: string; } interface ConsentPayload { app_user_id?: string | undefined; app_id: string; consent: { advertising?: boolean; analytics?: boolean; }; att_status?: 'authorized' | 'denied' | 'restricted' | 'not_determined'; timestamp: string; } interface RemoteConfigResponse { config: { att?: { strategy: 'immediate' | 'after_onboarding' | 'after_paywall_view' | 'manual'; prompt_copy?: { title?: string; message?: string; }; }; skan?: { preset?: 'subscriptions' | 'engagement' | 'iap'; rules?: Record<string, any>; lock_policy?: string; }; events?: { allowlist?: string[]; denylist?: string[]; sampling?: Record<string, number>; sampling_rate?: number; rate_limit?: { per_minute?: number; per_hour?: number; per_event?: Record<string, { per_minute?: number; per_hour?: number; }>; }; }; connectors?: Record<string, { enabled?: boolean; app_id?: string; pixel_id?: string; test_mode?: boolean; }>; deeplinks?: { allowed_hosts?: string[]; behavior?: string; }; privacy?: { killswitches?: string[]; analytics_enabled?: boolean; advertising_enabled?: boolean; }; }; version: string; cache_ttl: number; } interface SKANPostbackPayload { app_id: string; version: string; ad_network_id: string; campaign_id?: string; source_app_id?: string; conversion_value?: number; coarse_conversion_value?: string; lock_window?: boolean; postback_sequence_index?: number; did_win?: boolean; timestamp: string; } interface APIResponse<T = any> { success: boolean; data?: T; error?: { code: string; message: string; details?: any; }; } interface EventsIngestResponse extends APIResponse { processed: number; failed: number; duplicate: number; } //#endregion //#region ../client/src/index.d.ts interface QueueOptions { flushIntervalMs?: number; maxQueueSize?: number; maxItemAgeMs?: number; requestTimeoutMs?: number; maxRetries?: number; baseRetryDelayMs?: number; maxRetryDelayMs?: number; } interface LayersConfig { apiKey: string; appId: string; environment: 'development' | 'staging' | 'production'; appUserId?: string | undefined; enableDebug?: boolean; baseUrl?: string; queueOptions?: QueueOptions; queueStorage?: QueueStorage | null; } interface EventData { [key: string]: unknown; } interface UserProperties { [key: string]: unknown; } interface ConsentOptions { advertising?: boolean; analytics?: boolean; } type RemoteConfig = RemoteConfigResponse['config']; interface QueuedRequest { endpoint: string; data: unknown; attempts: number; queuedAt: number; nextAttemptAt: number; requestId: string; retryable: boolean; } interface StoredQueuedRequest extends QueuedRequest {} interface StoredQueueSnapshot { version: number; items: StoredQueuedRequest[]; } interface QueueStorage { load(): Promise<StoredQueueSnapshot | null>; save(snapshot: StoredQueueSnapshot): Promise<void>; clear(): Promise<void>; } declare class LayersClient { private config; private remoteConfig; private remoteConfigMeta; private eventQueue; private isOnline; private consentState; private sessionId; private deviceInfo; private queueTimer; private queueConfig; private queueStorage; private rateLimitState; private logLevel; private shouldLog; constructor(config: LayersConfig); private generateSessionId; private initializeDeviceInfo; init(): Promise<void>; private fetchRemoteConfig; private extractRemoteConfigSettings; private setupNetworkListener; setOnlineState(isOnline: boolean): void; private hydrateQueue; private persistQueue; track(eventName: string, properties?: EventData): Promise<void>; private shouldProcessEvent; private passesSampling; private resolveAppUserId; screen(screenName: string, properties?: EventData): Promise<void>; setUserProperties(properties: UserProperties): Promise<void>; isAnalyticsEnabled(): boolean; isAdvertisingEnabled(): boolean; setConsent(consent: ConsentOptions): Promise<void>; private enqueue; private scheduleQueueFlush; private processQueue; private dropExpiredQueueItems; private getBackoffDelay; private resetRateLimitState; private getEventRateCounter; private normalizeRateLimitRule; private passesRateLimit; private canConsumeRateLimit; private canConsumeWindow; private recordRateLimit; private incrementWindow; private getWindowInfo; private makeRequest; private isRetryableStatus; private generateEventId; private generateBatchId; getRemoteConfig(): RemoteConfig | null; getRemoteConfigVersion(): string | undefined; getConsentState(): Required<ConsentOptions>; setAppUserId(appUserId: string | undefined): void; /** @deprecated Use setAppUserId instead */ setUserId(userId: string): void; getConfig(): LayersConfig; getAppUserId(): string | undefined; /** @deprecated Use getAppUserId instead */ getUserId(): string | undefined; getSessionId(): string; flush(): Promise<void>; setDeviceInfo(deviceInfo: Partial<BaseEvent>): void; startNewSession(): void; } //#endregion //#region src/native/ATTModule.d.ts type ATTStatus = 'not_determined' | 'restricted' | 'denied' | 'authorized'; interface ATTPermissionOptions { title?: string; message?: string; delay?: number; } interface ATTEventData { status: ATTStatus; previousStatus?: ATTStatus; timestamp: string; strategy?: string; context?: string; } //#endregion //#region src/native/ConnectorsModule.d.ts type NetworkType = 'meta' | 'tiktok' | 'snap' | 'google'; interface ConnectorConfig { appId?: string; pixelId?: string; enabled: boolean; testMode?: boolean; } interface ConnectorCapabilities { hasSDK: boolean; sdkVersion?: string; supportedEvents: string[]; initializationRequired: boolean; } interface ConnectorStatus { network: NetworkType; enabled: boolean; initialized: boolean; hasSDK: boolean; lastEventSent?: string; eventsSent: number; errors: number; } interface ConnectorMetrics { network: NetworkType; totalEvents: number; successfulEvents: number; failedEvents: number; lastError?: string; averageLatency?: number; } interface EventMappingRule { layersEvent: string; networkEvent: string; propertyMappings?: Record<string, string>; conditions?: Record<string, any>; } interface NetworkEvent { type: string; properties: Record<string, any>; timestamp: number; userId?: string; sessionId: string; } //#endregion //#region src/native/DeepLinkModule.d.ts interface DeepLinkData { url: string; scheme: string; host: string; path: string; queryParams: Record<string, string>; fragment?: string; timestamp: number; } interface AttributionData { source?: string; medium?: string; campaign?: string; term?: string; content?: string; clickId?: string; fbclid?: string; gclid?: string; ttclid?: string; snapclid?: string; referrer?: string; isDeferred?: boolean; installReferrer?: string; } interface DeepLinkConfig { urlSchemes: string[]; universalLinkDomains: string[]; deferredDeepLinkTimeout: number; attributionWindowDays: number; trackOrganicLinks: boolean; customParameterMapping?: Record<string, string>; } interface DeepLinkListener { onDeepLink: (data: DeepLinkData, attribution: AttributionData) => void; onAttributionData: (attribution: AttributionData) => void; } interface DeepLinkMetrics { totalLinks: number; uniqueLinks: number; attributedInstalls: number; attributedSessions: number; deferredLinks: number; sourceBreakdown: Record<string, number>; conversionRate: number; } //#endregion //#region src/native/SKANModule.d.ts type SKANVersion = '2.0' | '2.2' | '3.0' | '4.0'; interface SKANConversionRule { eventName: string; conditions?: Record<string, any>; conversionValue: number; coarseValue?: 'low' | 'medium' | 'high'; lockWindow?: boolean; priority?: number; description?: string; } interface SKANPresetConfig { name: 'subscriptions' | 'engagement' | 'iap'; rules: SKANConversionRule[]; description: string; maxValue: number; } interface SKANPostback { version: string; adNetworkId: string; campaignId?: string; conversionValue?: number; coarseConversionValue?: string; sourceAppId?: string; timestamp: string; postbackSequenceIndex?: number; didWin?: boolean; } interface SKANEventData { event: string; properties: Record<string, any>; matchedRule?: SKANConversionRule; previousValue?: number; newValue?: number; timestamp: string; ruleEvaluations?: Array<{ rule: string; matched: boolean; reason?: string; }>; } interface SKANMetrics { isSupported: boolean; version: SKANVersion; currentValue: number | null; currentPreset: string | null; ruleCount: number; evaluationCount: number; attributionData: SKANPostback | null; lastEvaluations: Array<{ event: string; rule?: string; timestamp: string; }>; } //#endregion //#region src/ExpoRouterIntegration.d.ts /** * Hook for tracking screen views with Expo Router. * * @param usePathname - The `usePathname` hook from `expo-router`. * @param useGlobalSearchParams - The `useGlobalSearchParams` hook from `expo-router`. */ declare function useLayersExpoRouterTracking(usePathname: () => string, useGlobalSearchParams: () => Record<string, string | string[]>): void; /** * Component for tracking screen views with Expo Router. * Render this in your root `_layout.tsx`. */ declare function LayersExpoRouter({ usePathname, useGlobalSearchParams }: { usePathname: () => string; useGlobalSearchParams: () => Record<string, string | string[]>; }): null; //#endregion //#region src/integrations/Commerce.d.ts interface CommerceProduct { productId: string; price: number; currency: string; name?: string; category?: string; quantity?: number; } interface CommerceTransaction { transactionId: string; store: 'app_store' | 'play_store' | 'stripe' | 'custom'; revenue: number; currency: string; products: CommerceProduct[]; } declare const Commerce: { /** * Track a successful purchase manually. * Use this if you are managing IAP code yourself (e.g. react-native-iap). */ trackPurchase: (transaction: CommerceTransaction) => Promise<void>; }; //#endregion //#region src/integrations/RevenueCat.d.ts /** * Safe wrapper for RevenueCat integration. * Does not import 'react-native-purchases' to avoid runtime crashes. */ declare const RevenueCat: { /** * Connects Layers to your existing RevenueCat Purchases instance. * Listens for customer info updates to track subscription status changes. * * @example * import Purchases from 'react-native-purchases'; * Layers.RevenueCat.connect(Purchases); */ connect: (purchasesInstance: any) => void; /** * Helper to manually track a package purchase if you are not using the automatic listener * or want explicit purchase event timing. * * @param rcPackage - The package object from Purchases.getOfferings() */ trackPurchase: (rcPackage: any) => Promise<void>; }; //#endregion //#region src/integrations/Superwall.d.ts interface MinimalPaywallInfo { identifier: string; name?: string; url?: string; products?: { id: string; }[]; experiment?: { id: string; variantId: string; }; } declare const Superwall: { /** * Track that a paywall was presented to the user. * Call this within your Superwall presentation handler. * * @param paywallInfo - The info object provided by Superwall callbacks */ trackPresentation: (paywallInfo: MinimalPaywallInfo) => Promise<void>; /** * Track that a paywall was dismissed. * * @param paywallInfo - The info object provided by Superwall callbacks */ trackDismiss: (paywallInfo: MinimalPaywallInfo) => Promise<void>; }; //#endregion //#region src/index.d.ts declare class LayersRN { private client; private isInitialized; private deepLinkConfig; private skanManager; init(config: LayersConfig): Promise<void>; /** * Initialize SKAN and apply config from server */ private initializeSKAN; /** * Get remote config from client */ private getRemoteConfig; /** * Apply SKAN configuration from server */ private applySKANConfig; getClient(): LayersClient | null; isReady(): boolean; destroy(): Promise<void>; track(eventName: string, properties?: EventData): Promise<void>; screen(screenName: string, properties?: EventData): Promise<void>; setUserProperties(properties: UserProperties): Promise<void>; setAppUserId(appUserId: string): void; clearAppUserId(): void; setConsent(consent: ConsentOptions): Promise<void>; requestTracking(_options?: { strategy?: string; }): Promise<void>; debug: { showOverlay: (_options?: { position?: "top" | "bottom"; theme?: "light" | "dark"; }) => void; hideOverlay: () => void; isOverlayVisible: () => boolean; getATTStatus: () => Promise<ATTStatus>; getSKANMetrics: () => Promise<SKANMetrics>; getDeepLinkMetrics: () => Promise<DeepLinkMetrics>; getConnectorStatuses: () => Promise<Record<NetworkType, ConnectorStatus>>; testConnectorConnection: (_network: NetworkType) => Promise<boolean>; flushAllEvents: () => Promise<Record<NetworkType, number>>; }; connectors: { configure: (_network: NetworkType, _config: Partial<ConnectorConfig>) => Promise<boolean>; enable: (_network: NetworkType) => Promise<boolean>; disable: (_network: NetworkType) => Promise<boolean>; getStatus: (network: NetworkType) => Promise<{ network: NetworkType; enabled: boolean; initialized: boolean; hasSDK: boolean; lastEventSent?: string; eventsSent: number; errors: number; }>; getAllStatuses: () => Promise<Record<NetworkType, ConnectorStatus>>; getMetrics: (network: NetworkType) => Promise<{ network: NetworkType; totalEvents: number; successfulEvents: number; failedEvents: number; lastError?: string; averageLatency?: number; }>; testConnection: (_network: NetworkType) => Promise<boolean>; flush: () => Promise<Record<NetworkType, number>>; }; deepLinks: { configure: (config: Partial<DeepLinkConfig>) => Promise<void>; addListener: (_listener: DeepLinkListener) => () => undefined; getMetrics: () => Promise<DeepLinkMetrics>; parseUrl: (url: string) => DeepLinkData; clearAttribution: () => Promise<void>; }; att: { request: (_strategy?: string) => Promise<ATTStatus>; getStatus: () => Promise<ATTStatus>; isSupported: () => Promise<boolean>; setCustomPrompt: (_title: string, _message: string) => void; }; skan: { setPreset: (preset: SKANPresetConfig["name"]) => Promise<void>; setRules: (rules: SKANConversionRule[]) => Promise<void>; getCurrentConversionValue: () => Promise<number | null>; getMetrics: () => Promise<SKANMetrics>; }; private createConnectorStatusMap; private createZeroCountMap; } declare const Layers: LayersRN; interface DebugOverlayProps { visible: boolean; onClose: () => void; layersClient?: LayersClient | null; } declare const DebugOverlay: (_props: DebugOverlayProps) => null; //#endregion export { APIResponse, type ATTEventData, type ATTPermissionOptions, type ATTStatus, AppBackgroundEvent, AppInstallEvent, AppOpenEvent, type AttributionData, BaseEvent, BookmarkAddEvent, Commerce, CommerceProduct, CommerceTransaction, type ConnectorCapabilities, type ConnectorConfig, type ConnectorMetrics, type ConnectorStatus, ConsentOptions, ConsentPayload, ContentOpenEvent, DebugOverlay, DebugOverlayProps, type DeepLinkData, type DeepLinkListener, type DeepLinkMetrics, DeeplinkOpenEvent, EventData, type EventMappingRule, EventsBatchPayload, EventsIngestResponse, Layers, Layers as default, LayersClient, LayersConfig, LayersEvent, LayersExpoRouter, type NetworkEvent, type NetworkType, PaywallDismissEvent, PaywallShowEvent, PurchaseAttemptEvent, PurchaseFailEvent, PurchaseSuccessEvent, QueueOptions, QueueStorage, RefundEvent, RemoteConfig, RemoteConfigResponse, RevenueCat, type SKANConversionRule, type SKANEventData, type SKANMetrics, type SKANPostback, SKANPostbackPayload, type SKANPresetConfig, type SKANVersion, ScreenViewEvent, SearchEvent, StoredQueueSnapshot, StoredQueuedRequest, SubscriptionCancelEvent, SubscriptionRenewEvent, SubscriptionStartEvent, Superwall, TrialConvertEvent, TrialStartEvent, UserProperties, UserPropertiesPayload, useLayersExpoRouterTracking }; //# sourceMappingURL=index.d.ts.map