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-sdk

iOS Setup

  1. Install iOS dependencies:

    cd ios && pod install
  2. 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(): UseEntrolyticsReturn

Advanced 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 online

Network 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