React Native SDK
React Native SDK for iOS and Android apps
React Native SDK
The @entrolytics/react-native-sdk package provides a comprehensive React Native SDK for analytics tracking in iOS and Android applications with native performance and battery optimization.
Installation
npm install @entrolytics/react-native-sdkiOS Setup
-
Install iOS dependencies:
cd ios && pod install -
Add to
Info.plist:<key>NSAppTransportSecurity</key> <dict> <key>NSAllowsArbitraryLoads</key> <false/> <key>NSExceptionDomains</key> <dict> <key>entrolytics.dev</key> <dict> <key>NSExceptionAllowsInsecureHTTPLoads</key> <true/> </dict> </dict> </dict>
Android Setup
Add to android/app/src/main/AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />Quick Start
Initialize SDK
import { Entrolytics } from '@entrolytics/react-native-sdk'
// Initialize in your app entry point
Entrolytics.initialize({
websiteId: 'your-website-id',
apiKey: 'your-api-key',
host: 'https://entrolytics.dev',
debug: __DEV__ // Enable debug mode in development
})Track Events
// Track custom events
Entrolytics.track('button_click', {
button_name: 'Sign Up',
screen: 'Onboarding',
timestamp: new Date().toISOString()
})
// Track screen views
Entrolytics.screen('HomeScreen', {
title: 'Home',
category: 'main'
})
// Identify users
Entrolytics.identify('user-123', {
email: 'user@example.com',
name: 'John Doe',
plan: 'pro'
})React Hook Integration
import React from 'react'
import { useEntrolytics } from '@entrolytics/react-native-sdk'
function SignupButton() {
const { track, screen, identify } = useEntrolytics()
const handleSignup = async () => {
// Track button click
await track('signup_attempt', {
method: 'email',
screen: 'Signup'
})
// Handle signup logic
try {
const user = await signup()
// Identify user
await identify(user.id, {
email: user.email,
name: user.name
})
// Track success
await track('signup_success', {
userId: user.id
})
// Navigate to next screen
navigation.navigate('Home')
} catch (error) {
// Track error
await track('signup_error', {
error: error.message,
code: error.code
})
}
}
return <Button title='Sign Up' onPress={handleSignup} />
}Configuration
Initialization Options
interface EntrolyticsConfig {
/** Website ID (required) */
websiteId: string
/** API key for authentication */
apiKey?: string
/** Custom API host */
host?: string
/** Enable debug logging */
debug?: boolean
/** Auto-track screen views */
autoTrackScreens?: boolean
/** Track crashes automatically */
trackCrashes?: boolean
/** Track app lifecycle events */
trackAppLifecycle?: boolean
/** Network configuration */
network?: {
timeout?: number
retryAttempts?: number
batchSize?: number
flushInterval?: number
}
/** Privacy settings */
privacy?: {
disableTracking?: boolean
anonymizeIp?: boolean
respectDoNotTrack?: boolean
}
}Environment Variables
// Using react-native-config
import Config from 'react-native-config'
Entrolytics.initialize({
websiteId: Config.ENTROLYTICS_WEBSITE_ID,
apiKey: Config.ENTROLYTICS_API_KEY,
host: Config.ENTROLYTICS_HOST,
debug: Config.ENTROLYTICS_DEBUG === 'true'
})API Reference
Core Methods
Entrolytics Class
class Entrolytics {
/** Initialize the SDK */
static initialize(config: EntrolyticsConfig): Promise<void>
/** Track a custom event */
static track(event: string, properties?: Record<string, any>): Promise<void>
/** Track a screen view */
static screen(name: string, properties?: Record<string, any>): Promise<void>
/** Identify a user */
static identify(userId: string, traits?: Record<string, any>): Promise<void>
/** Set user properties */
static setUserProperties(properties: Record<string, any>): Promise<void>
/** Reset the user session */
static reset(): Promise<void>
/** Get current user ID */
static getUserId(): Promise<string | null>
/** Get session ID */
static getSessionId(): Promise<string>
/** Flush pending events */
static flush(): Promise<void>
/** Enable/disable tracking */
static setEnabled(enabled: boolean): Promise<void>
/** Check if tracking is enabled */
static isEnabled(): Promise<boolean>
}React Hook
interface UseEntrolyticsReturn {
/** Track a custom event */
track: (event: string, properties?: Record<string, any>) => Promise<void>
/** Track a screen view */
screen: (name: string, properties?: Record<string, any>) => Promise<void>
/** Identify a user */
identify: (userId: string, traits?: Record<string, any>) => Promise<void>
/** Set user properties */
setUserProperties: (properties: Record<string, any>) => Promise<void>
/** Reset the user session */
reset: () => Promise<void>
/** Current configuration */
config: EntrolyticsConfig
/** Current user ID */
userId: string | null
/** Session ID */
sessionId: string
}
function useEntrolytics(): UseEntrolyticsReturnAdvanced Usage
Screen Tracking
Automatic Screen Tracking
// Enable automatic screen tracking
Entrolytics.initialize({
websiteId: 'your-website-id',
autoTrackScreens: true
})
// React Navigation integration
import { useNavigationContainerRef } from '@react-navigation/native'
function App() {
const navigationRef = useNavigationContainerRef()
React.useEffect(() => {
const unsubscribe = navigationRef.addListener('state', (e) => {
const routeName = e.data.state.routes[e.data.state.index].name
Entrolytics.screen(routeName)
})
return unsubscribe
}, [navigationRef])
return (
<NavigationContainer ref={navigationRef}>
{/* Your navigators */}
</NavigationContainer>
)
}Manual Screen Tracking
import { useFocusEffect } from '@react-navigation/native'
function ProfileScreen() {
const { screen } = useEntrolytics()
useFocusEffect(
React.useCallback(() => {
screen('ProfileScreen', {
userId: 'user-123',
hasPremium: true
})
}, [])
)
return <ProfileComponent />
}User Management
User Identification
// Login flow
async function handleLogin(email, password) {
try {
const user = await login(email, password)
// Identify user in analytics
await Entrolytics.identify(user.id, {
email: user.email,
name: user.name,
plan: user.plan,
signupDate: user.createdAt
})
// Track login event
await Entrolytics.track('login_success', {
method: 'email',
userId: user.id
})
return user
} catch (error) {
await Entrolytics.track('login_error', {
error: error.message,
email: email
})
throw error
}
}
// Logout flow
async function handleLogout() {
// Track logout event
await Entrolytics.track('logout', {
sessionDuration: Date.now() - loginTime
})
// Reset user session
await Entrolytics.reset()
// Clear local data
await clearUserData()
}User Properties
// Update user properties
await Entrolytics.setUserProperties({
plan: 'premium',
lastSeen: new Date().toISOString(),
preferences: {
theme: 'dark',
notifications: true
}
})
// Increment user properties
await Entrolytics.setUserProperties({
loginCount: { $inc: 1 },
totalSpent: { $add: 9.99 }
})Event Tracking
Custom Events
// E-commerce events
await Entrolytics.track('product_view', {
productId: 'prod-123',
productName: 'Premium Widget',
category: 'widgets',
price: 29.99,
currency: 'USD',
source: 'search'
})
await Entrolytics.track('add_to_cart', {
productId: 'prod-123',
quantity: 2,
price: 59.98,
cartValue: 159.98
})
await Entrolytics.track('purchase', {
orderId: 'order-456',
total: 159.98,
currency: 'USD',
items: [
{
productId: 'prod-123',
quantity: 2,
price: 29.99
}
],
paymentMethod: 'credit_card'
})Performance Events
// Track app performance
await Entrolytics.track('app_performance', {
startupTime: 1200, // milliseconds
memoryUsage: 45.6, // MB
batteryLevel: 0.85, // percentage
networkType: 'wifi',
appVersion: '1.2.3'
})
// Track API performance
await Entrolytics.track('api_call', {
endpoint: '/api/users',
method: 'GET',
duration: 250, // milliseconds
statusCode: 200,
success: true
})Error and Crash Tracking
Automatic Crash Tracking
// Enable crash tracking
Entrolytics.initialize({
websiteId: 'your-website-id',
trackCrashes: true
})Manual Error Tracking
// Track custom errors
try {
await riskyOperation()
} catch (error) {
await Entrolytics.track('error', {
message: error.message,
stack: error.stack,
type: error.constructor.name,
context: 'risky_operation',
userId: await Entrolytics.getUserId()
})
}
// Track handled errors
await Entrolytics.track('handled_error', {
error: 'Invalid input',
field: 'email',
value: 'invalid-email',
screen: 'SignupForm'
})Offline Support
Offline Mode
// Enable offline mode
await Entrolytics.setOfflineMode(true)
// Track events while offline
await Entrolytics.track('offline_event', {
cached: true,
timestamp: new Date().toISOString()
})
// Events are stored locally and synced when onlineNetwork Monitoring
import { NetInfo } from '@react-native-community/netinfo'
// Monitor network status
NetInfo.addEventListener((state) => {
if (state.isConnected) {
// Back online, flush cached events
Entrolytics.flush()
} else {
// Went offline, enable offline mode
Entrolytics.setOfflineMode(true)
}
})React Integration
Provider Pattern
import { EntrolyticsProvider } from '@entrolytics/react-native-sdk'
function App() {
return (
<EntrolyticsProvider
config={{
websiteId: 'your-website-id',
apiKey: 'your-api-key',
debug: __DEV__
}}
>
<NavigationContainer>
<AppNavigator />
</NavigationContainer>
</EntrolyticsProvider>
)
}Context Hook
import { useEntrolytics } from '@entrolytics/react-native-sdk'
function ProductCard({ product }) {
const { track, screen } = useEntrolytics()
const handlePress = () => {
track('product_tap', {
productId: product.id,
productName: product.name,
category: product.category
})
}
const handleAddToCart = () => {
track('add_to_cart', {
productId: product.id,
price: product.price,
source: 'product_card'
})
}
return (
<TouchableOpacity onPress={handlePress}>
<Text>{product.name}</Text>
<Text>${product.price}</Text>
<Button title='Add to Cart' onPress={handleAddToCart} />
</TouchableOpacity>
)
}Higher-Order Component
import { withEntrolytics } from '@entrolytics/react-native-sdk'
class ProfileScreen extends React.Component {
componentDidMount() {
this.props.entrolytics.screen('ProfileScreen')
}
handleUpdateProfile = async (updates) => {
try {
await updateProfile(updates)
this.props.entrolytics.track('profile_updated', {
fields: Object.keys(updates)
})
} catch (error) {
this.props.entrolytics.track('profile_update_error', {
error: error.message
})
}
}
render() {
return <ProfileComponent onUpdate={this.handleUpdateProfile} />
}
}
export default withEntrolytics(ProfileScreen)Testing
Unit Tests
import { renderHook, act } from '@testing-library/react-hooks'
import { useEntrolytics } from '@entrolytics/react-native-sdk'
// Mock the SDK
jest.mock('@entrolytics/react-native-sdk', () => ({
useEntrolytics: () => ({
track: jest.fn(),
screen: jest.fn(),
identify: jest.fn()
})
}))
describe('useEntrolytics', () => {
it('should track events', () => {
const { result } = renderHook(() => useEntrolytics())
act(() => {
result.current.track('test_event', { property: 'value' })
})
expect(result.current.track).toHaveBeenCalledWith('test_event', {
property: 'value'
})
})
})Component Tests
import React from 'react'
import { render, fireEvent } from '@testing-library/react-native'
import { EntrolyticsProvider } from '@entrolytics/react-native-sdk'
function TestComponent() {
const { track } = useEntrolytics()
return <Button title='Test Button' onPress={() => track('button_press')} />
}
describe('Analytics Integration', () => {
it('should track button presses', () => {
const mockTrack = jest.fn()
render(
<EntrolyticsProvider>
<TestComponent />
</EntrolyticsProvider>
)
fireEvent.press(screen.getByText('Test Button'))
expect(mockTrack).toHaveBeenCalledWith('button_press')
})
})Performance Optimization
Batching Configuration
Entrolytics.initialize({
websiteId: 'your-website-id',
network: {
batchSize: 50, // Send events in batches of 50
flushInterval: 30000, // Flush every 30 seconds
timeout: 10000, // 10 second timeout
retryAttempts: 3 // Retry failed requests 3 times
}
})Memory Management
// Clear cached events on memory warning
import { AppState } from 'react-native'
AppState.addEventListener('memoryWarning', () => {
// Reduce batch size during memory pressure
Entrolytics.updateConfig({
network: { batchSize: 10 }
})
})
// Cleanup on app background
AppState.addEventListener('change', (state) => {
if (state === 'background') {
Entrolytics.flush() // Send pending events
}
})Battery Optimization
// Adaptive tracking based on battery level
import { Battery } from 'react-native-battery'
Battery.getLevel().then((level) => {
const config = {
websiteId: 'your-website-id',
network: {
batchSize: level < 0.2 ? 10 : 50, // Smaller batches on low battery
flushInterval: level < 0.2 ? 60000 : 30000
}
}
Entrolytics.initialize(config)
})Troubleshooting
Best Practices
Migration Guide
From Other Analytics SDKs
// Firebase Analytics
import analytics from '@react-native-firebase/analytics'
analytics().logEvent('button_click', { button_name: 'Sign Up' })
// Entrolytics
import { Entrolytics } from '@entrolytics/react-native-sdk'
Entrolytics.track('button_click', { button_name: 'Sign Up' })From Web SDK
// Web React SDK
import { useEntrolytics } from '@entrolytics/react-sdk'
function Component() {
const { track } = useEntrolytics()
const handleClick = () => {
track('button_click', { button_name: 'Sign Up' })
}
}
// React Native SDK
import { useEntrolytics } from '@entrolytics/react-native-sdk'
function Component() {
const { track } = useEntrolytics()
const handleClick = () => {
track('button_click', { button_name: 'Sign Up' })
}
}React Native SDK for Entrolytics - First-party growth analytics for the edge