The Formo React Native SDK is designed for mobile dApps and implements the standard Events API with rich mobile context including device information, network status, and app metadata. Installation Install the SDK and required peer dependencies: npm install @formo/react-native-analytics @react-native-async-storage/async-storage react-native-device-info @react-native-community/netinfo
iOS Setup After installing, run pod install: Android Setup No additional setup required. The native modules are automatically linked. Quick Start Basic Setup Wrap your app with the FormoAnalyticsProvider: import AsyncStorage from '@react-native-async-storage/async-storage' ; import { FormoAnalyticsProvider } from '@formo/react-native-analytics' ; function App () { return ( < FormoAnalyticsProvider writeKey = "<YOUR_WRITE_KEY>" asyncStorage = { AsyncStorage } > < YourApp /> </ FormoAnalyticsProvider > ); }
With Wagmi For apps using Wagmi , enable native integration for automatic wallet event tracking: import AsyncStorage from '@react-native-async-storage/async-storage' ; import { WagmiProvider , createConfig } from 'wagmi' ; import { QueryClient , QueryClientProvider } from '@tanstack/react-query' ; import { FormoAnalyticsProvider } from '@formo/react-native-analytics' ; import { mainnet } from 'wagmi/chains' ; const wagmiConfig = createConfig ({ chains: [ mainnet ], // ... your transports }); const queryClient = new QueryClient (); function App () { return ( < WagmiProvider config = { wagmiConfig } > < QueryClientProvider client = { queryClient } > < FormoAnalyticsProvider writeKey = "<YOUR_WRITE_KEY>" asyncStorage = { AsyncStorage } options = { { wagmi: { config: wagmiConfig , queryClient: queryClient , }, } } > < YourApp /> </ FormoAnalyticsProvider > </ QueryClientProvider > </ WagmiProvider > ); }
Track screen views Use the screen() method to track screen views - the mobile equivalent of page views: import { useFormo } from '@formo/react-native-analytics' ; import { useEffect } from 'react' ; function WalletScreen () { const formo = useFormo (); useEffect (() => { formo . screen ( 'Wallet' , { category: 'Main' }); }, [ formo ]); return < View > ... </ View > ; }
Include formo in the dependency array. The SDK initializes asynchronously, so including it ensures the screen event fires once initialization completes.
With React Navigation Automatically track all screen transitions: import { NavigationContainer , useNavigationContainerRef } from '@react-navigation/native' ; import { useFormo } from '@formo/react-native-analytics' ; import { useRef } from 'react' ; function App () { const analytics = useFormo (); const navigationRef = useNavigationContainerRef (); const routeNameRef = useRef < string >(); return ( < NavigationContainer ref = { navigationRef } onReady = { () => { routeNameRef . current = navigationRef . getCurrentRoute ()?. name ; } } onStateChange = { () => { const previousRouteName = routeNameRef . current ; const currentRouteName = navigationRef . getCurrentRoute ()?. name ; if ( previousRouteName !== currentRouteName && currentRouteName ) { analytics . screen ( currentRouteName ); } routeNameRef . current = currentRouteName ; } } > { /* Your navigation stack */ } </ NavigationContainer > ); }
Identify users Call identify() after a user connects their wallet: const formo = useFormo (); formo . identify ({ address: '0x1234...abcd' , userId: 'optional-user-id' , providerName: 'MetaMask' , });
When using Wagmi integration, wallet connections are automatically tracked. You only need to call identify() manually if you want to associate additional user data or use a custom user ID.
Track custom events Track custom events with the track() method: const formo = useFormo (); // Basic custom event formo . track ( 'Swap Completed' , { from_token: 'ETH' , to_token: 'USDC' , amount: '1.5' , }); // With reserved properties for analytics formo . track ( 'Purchase Completed' , { productId: 'premium-nft-001' , revenue: 99.99 , // Reserved: revenue tracking currency: 'USD' , // Reserved: currency for revenue }); formo . track ( 'Achievement Unlocked' , { achievementId: 'first_transaction' , points: 500 , // Reserved: points tracking }); formo . track ( 'Swap Executed' , { fromToken: 'ETH' , toToken: 'USDC' , volume: 1.5 , // Reserved: volume tracking });
Code examples
React Native examples/react-native
Deep link attribution Parse UTM parameters and referral codes from deep links: import { Linking } from 'react-native' ; import { useFormo } from '@formo/react-native-analytics' ; import { useEffect } from 'react' ; function App () { const formo = useFormo (); useEffect (() => { // Handle initial deep link (app opened via link) Linking . getInitialURL (). then (( url ) => { if ( url ) formo . setTrafficSourceFromUrl ( url ); }); // Handle deep links while app is open const subscription = Linking . addEventListener ( 'url' , ( event ) => { formo . setTrafficSourceFromUrl ( event . url ); }); return () => subscription . remove (); }, [ formo ]); return < YourApp /> ; }
The SDK automatically extracts and stores: UTM parameters (utm_source, utm_medium, utm_campaign, utm_term, utm_content) Referral codes (ref, referral, refcode, referrer_code) Example deep link: myapp://home?utm_source=twitter&utm_campaign=launch&ref=friend123 Configuration Provider props Prop Type Required Description writeKeyString Yes Your Formo project write key. asyncStorageAsyncStorage Yes AsyncStorage instance for persistent storage. optionsObject No Configuration options (see below). disabledBoolean No Disable the SDK entirely. onReadyFunction No Callback when SDK is initialized. onErrorFunction No Callback when initialization fails.
Options < FormoAnalyticsProvider writeKey = "<YOUR_WRITE_KEY>" asyncStorage = { AsyncStorage } options = { { // Wagmi integration wagmi: { config: wagmiConfig , queryClient: queryClient , }, // App metadata (enriches all events) app: { name: 'MyDeFiApp' , version: '2.1.0' , build: '42' , bundleId: 'com.example.mydefiapp' , }, // Batching configuration flushAt: 20 , // Batch size (default: 20, max: 20) flushInterval: 30000 , // Auto-flush interval in ms (default: 30s) // Retry configuration retryCount: 3 , // Retry attempts (default: 3, max: 5) maxQueueSize: 500000 , // Max queue size in bytes (default: 500KB) // Tracking control tracking: true , // Enable/disable tracking // Autocapture control autocapture: true , // Enable/disable wallet autocapture // Logging logger: { enabled: true , levels: [ 'error' , 'warn' , 'info' ], }, // Custom API endpoint apiHost: 'https://your-proxy.com/api/ingest' , } } >
The SDK automatically detects app information from your app’s native configuration: app_name - from your app’s display name app_version - from your app’s version (e.g., 2.1.0) app_build - from your app’s build number (e.g., 42) app_bundle_id - from your bundle/package identifier To override the auto-detected values, provide custom app information: options = {{ app : { name : 'MyDeFiApp' , // Override detected app name version : '2.1.0' , // Override detected version build : '42' , // Override detected build bundleId : 'com.example.mydefiapp' , }, }}
Tracking control Control tracking behavior for different environments or chains: // Disable tracking entirely options = {{ tracking : false , }} // Exclude specific chains (e.g., testnets) options = {{ tracking : { excludeChains : [ 5 , 11155111 ], // Goerli, Sepolia }, }}
Autocapture Control which wallet events are automatically captured: // Enable all autocapture (default) options = {{ autocapture : true , }} // Disable specific events options = {{ autocapture : { connect : true , disconnect : true , signature : false , // Disable signature tracking transaction : false , // Disable transaction tracking chain : true , }, }} // Disable all autocapture options = {{ autocapture : false , }}
Logging Enable debug logging during development: options = {{ logger : { enabled : __DEV__ , levels : [ 'error' , 'warn' , 'info' , 'debug' ], }, }}
Log Level Description errorError messages only. warnWarning and error messages. infoInformative messages about normal operation. debugDetailed diagnostic information. traceMost detailed tracing information.
Ready callback Execute code when the SDK is fully initialized: < FormoAnalyticsProvider writeKey = "<YOUR_WRITE_KEY>" asyncStorage = { AsyncStorage } onReady = { ( sdk ) => { console . log ( 'Formo SDK ready!' ); // Auto-identify or perform other initialization } } onError = { ( error ) => { console . error ( 'Formo SDK failed to initialize:' , error ); } } >
Consent management Comply with privacy regulations using built-in consent management: const formo = useFormo (); // Check if user has opted out if ( formo . hasOptedOutTracking ()) { console . log ( 'User has opted out' ); } // Opt out of tracking (stops all tracking, clears queue) formo . optOutTracking (); // Opt back into tracking formo . optInTracking ();
When opting out, track the opt-out event before calling optOutTracking() so it gets recorded. When opting in, call optInTracking() first, then track the opt-in event.
Wagmi integration When Wagmi integration is enabled, the SDK automatically tracks: Event Type Without QueryClient With QueryClient Connect Tracked Tracked Disconnect Tracked Tracked Chain Change Tracked Tracked Signatures Not tracked Tracked Transactions Not tracked Tracked
Use the same QueryClient instance for both Wagmi and Formo to avoid creating multiple cache instances.
Mobile context The SDK automatically enriches every event with mobile-specific context: Field Description os_nameOperating system (iOS, Android). os_versionOS version number. device_modelDevice model (iPhone 14 Pro, Pixel 8). device_manufacturerDevice manufacturer (Apple, Google, Samsung). device_typeDevice type (mobile, tablet). screen_widthScreen width in pixels. screen_heightScreen height in pixels. screen_densityPixel density (devicePixelRatio). localeDevice language setting. timezoneDevice timezone. wifiWhether connected to WiFi. cellularWhether connected to cellular. carrierMobile carrier name (when available). app_nameYour app name. app_versionYour app version. app_buildYour app build number.
Session management Reset the current user session: const formo = useFormo (); // Clear current user session (anonymous_id, user_id, etc.) formo . reset ();
Manual event flushing Force flush pending events (useful before app backgrounding): const formo = useFormo (); await formo . flush ();
The SDK automatically flushes events when the app goes to background.
Verification To verify the SDK is working: Enable debug logging in development Trigger a screen view or custom event Check the console for event logs Verify events appear in the Activity page on your Formo dashboard Peer dependencies Package Version Required react>=18.0.0 Yes react-native>=0.70.0 Yes @react-native-async-storage/async-storage>=1.17.0 Yes wagmi>=2.0.0 No (for Wagmi integration) @tanstack/react-query>=5.0.0 No (for signature/transaction tracking)