# @magicpixel/rn-mp-client-sdk

React Native SDK for MagicPixel analytics and tag management. Provides event-driven data collection, server-side and client-side tag execution, and comprehensive visitor tracking for iOS and Android apps.

## Installation

```sh
npm install @magicpixel/rn-mp-client-sdk
```

### Peer Dependencies

```sh
npm install react-native @react-native-async-storage/async-storage
```

### For Bare React Native

Bare React Native apps require additional setup:

#### 1. Install Required Dependencies

```sh
npm install react-native-get-random-values react-native-device-info
```

#### 2. Link Native Modules (Required)

**iOS:**
```sh
cd ios && pod install && cd ..
```

**Android:** Native modules are auto-linked via Gradle.

> ⚠️ **Important:** After running `pod install`, you must fully restart the app:
> 1. Kill the app in the simulator/device
> 2. Stop Metro bundler (`Ctrl+C`)
> 3. Restart Metro (`npx react-native start`)
> 4. Rebuild and launch the app
>
> Simply reloading Metro is not sufficient - the native binary must be rebuilt.

#### 3. Add Polyfill Import (Required)

Add this import at the very top of your app's entry file (`index.js`), **before any other imports**:

```javascript
import 'react-native-get-random-values'; // Must be first import!

import {AppRegistry} from 'react-native';
import App from './App';
import {name as appName} from './app.json';

AppRegistry.registerComponent(appName, () => App);
```

> ⚠️ **Without this setup, you will see the error:**
> ```
> MagicPixel SDK initialization failed: Invariant Violation: TurboModuleRegistry.getEnforcing(...): 'RNGetRandomValues' could not be found.
> ```

The SDK uses ULID for generating unique identifiers, which requires `crypto.getRandomValues()`. This polyfill must be loaded before any other code runs.

> **Note**: For Expo managed apps, no additional setup is required - the polyfill is handled automatically.

## Quick Start

```javascript
import { MagicPixel } from '@magicpixel/rn-mp-client-sdk';

// Initialize the SDK (call once at app startup)
MagicPixel.init({
  orgId: 'your-org-id',
  env: 'production',
  projectId: 'your-project-id',
  baseUrl: 'https://your-collector-url.com',
});

// Track screen views
MagicPixel.recordPageLoad({
  page_name: 'HomeScreen',
});

// Track custom events
MagicPixel.recordEvent('add_to_cart', {
  product_id: '123',
  price: 29.99,
  quantity: 1,
});
```

## API Reference

### Initialization

```javascript
MagicPixel.init({
  orgId: string,           // Required: Organization ID
  env: string,             // Required: 'staging' or 'production'
  projectId: string,       // Required: Project ID
  baseUrl: string,         // Required: Base URL for SDK configuration
  logLevel?: string,       // Optional: 'none' | 'debug' | 'error' (default: 'none')
  eventDeduplicationWindowMs?: number,  // Optional: Dedup window in ms (default: 5000)
  onInitFailure?: (error: Error) => void,  // Optional: Callback on init failure
});
```

### Screen Tracking

```javascript
MagicPixel.recordPageLoad({
  page_name: 'ProductDetails',
  deep_link_url?: 'myapp://product/123',  // Optional: For attribution
});
```

### Event Tracking

```javascript
MagicPixel.recordEvent('event_name', {
  // Custom event properties
  product_id: '123',
  category: 'electronics',
  value: 99.99,
});
```

### User Information

```javascript
// Set user identity for tracking
MagicPixel.setUserInfo({
  email?: 'user@example.com',
  phone?: '+1234567890',
  pid?: 'user-123',           // Your internal user ID
  fName?: 'John',
  lName?: 'Doe',
  zip?: '12345',
  city?: 'New York',
  state?: 'NY',
  country?: 'US',
});

// Set customer attribution info
MagicPixel.setCustomerInfo({
  first_name: 'John',
  last_name: 'Doe',
  email: 'john@example.com',
});
```

### Deep Link Attribution

```javascript
// Set deep link URL for attribution tracking
MagicPixel.setDeepLinkUrl('myapp://promo?utm_source=facebook&campaign=summer');
```

The SDK also automatically detects deep links (custom schemes, universal links, app links) when the app is opened via a link.

### Data Layer

```javascript
// Persist custom data across sessions
MagicPixel.persistData('user_tier', 'premium');

// Set temporary data layer variables
MagicPixel.setDataLayer({ campaign: 'summer_sale', source: 'email' });

// Clear persisted data
MagicPixel.clearPersistedData(['user_tier']);

// Read data layer state
const dataLayer = MagicPixel.getDataLayer();
const hasPageLoaded = MagicPixel.hasEventHappened('page_load');
```

### Firebase Integration

```javascript
MagicPixel.setFirebaseAppInstanceId('firebase-instance-id');
```

### Debugging

```javascript
// Get debug ID for troubleshooting
const debugId = MagicPixel.getDebugId();
```

### Shutdown

```javascript
// Clean up SDK resources (call when reinitializing or on app close)
MagicPixel.shutdown();
```

## Features

- **Event Buffering**: Events are buffered until SDK initialization completes
- **Event Deduplication**: Prevents duplicate events within configurable time window
- **Auto Device Detection**: Automatically detects device info, OS version, app version
- **Deep Link Support**: Handles custom schemes, universal links (iOS), and app links (Android)
- **Offline Support**: Events are queued and processed sequentially
- **Privacy Compliance**: Built-in support for opt-out tracking
- **Server-Side Tags**: Support for server-side tag execution

## Requirements

- React Native >= 0.60
- iOS >= 11.0
- Android >= API 21

## License

MIT
