npm package: @reddimon/react-native-attribution
Description: React Native Attribution SDK
Author: Davidon4
Latest version: 1.2.0

# @reddimon/react-native-attribution

A React Native Attribution SDK for tracking app installations, subscriptions, and user attribution.

## Features

- 📱 Cross-platform support (iOS & Android)
- 📍 Optional location tracking
- 🔄 Complete subscription lifecycle tracking (initial, renewals, cancellations)
- 🔗 Deep linking and attribution URL support
- 📊 Analytics and metrics tracking
- ⏱️ Attribution window management
- 🔒 Privacy-first with proper permission handling

## Installation

```sh
npm install @reddimon/react-native-attribution
# or
yarn add @reddimon/react-native-attribution
```

### iOS Setup

1. Add these permissions to your `Info.plist`:

```xml
<!-- User Tracking (for IDFA) -->
<key>NSUserTrackingUsageDescription</key>
<string>We use this identifier to measure advertising effectiveness.</string>

<!-- Location Services (optional) -->
<key>NSLocationWhenInUseUsageDescription</key>
<string>We use your location to provide region-specific content.</string>
```

2. For deep linking, add URL scheme:

```xml
<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>yourapp</string>
        </array>
    </dict>
</array>
```

### Android Setup

1. Add permissions to `AndroidManifest.xml`:

```xml
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="com.google.android.gms.permission.AD_ID"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <!-- Optional -->
<uses-permission android:name="com.google.android.finsky.permission.BIND_GET_INSTALL_REFERRER_SERVICE" />
```

2. For deep linking, add intent filter:

```xml
<activity>
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data android:scheme="yourapp" android:host="attribution" />
    </intent-filter>
</activity>
```

## Usage

### Initialization

```typescript
import Attribution from '@reddimon/react-native-attribution';

// Initialize the SDK
await Attribution.initialize({
  apiKey: 'YOUR_API_KEY',
  appId: 'com.yourapp.id',
  baseUrl: 'https://reddimon.com/api/tracking',
  enableLocationTracking: true // optional
});
```

### Track Installation

```typescript
// Track app installation with attribution
await Attribution.trackEvent('installation', {
  short_code: 'CREATOR_CODE', // The creator's unique short code from the deep link
  platform: Platform.OS,
  device_type: await DeviceInfo.getModel(),
  attribution_url: 'https://reddimon.com/c/CREATOR_CODE',
  click_timestamp: Date.now(),
  install_timestamp: Date.now(),
  install_source: Platform.OS === 'ios' ? 'App Store' : 'Play Store',
  device_id: await DeviceInfo.getUniqueId()
});
```

### Track Subscription

```typescript
// Track subscription purchase
// The short_code should be retrieved from the stored attribution data
const attributionData = await AsyncStorage.getItem('last_attribution');
let shortCode = 'ORGANIC'; // Default to organic if no attribution

if (attributionData) {
  const { short_code, timestamp } = JSON.parse(attributionData);
  // Check if within attribution window (e.g., 7 days)
  const DAY_IN_MS = 86400000;
  const ATTRIBUTION_WINDOW = 7 * DAY_IN_MS;
  
  if (Date.now() - timestamp < ATTRIBUTION_WINDOW) {
    shortCode = short_code;
  }
}

await Attribution.trackEvent('subscription', {
  short_code: shortCode,
  subscription_id: 'sub_123',
  plan_type: 'premium_monthly',
  amount: 9.99,
  currency: 'USD',
  interval: 'monthly',
  payment_provider: Platform.OS === 'ios' ? 'app_store' : 'play_store',
  subscription_date: Date.now()
});
```

### Attribution Flow

1. When a user clicks a creator's link:
```typescript
// Store attribution data when processing deep link
await AsyncStorage.setItem('last_attribution', JSON.stringify({
  short_code: extractedShortCode,
  timestamp: Date.now()
}));
```

2. When tracking installations:
```typescript
// Use the short_code directly from the deep link
await trackInstallation(shortCode, attributionUrl);
```

3. When tracking subscriptions:
```typescript
// Check attribution window and use stored short_code
const attributionData = await AsyncStorage.getItem('last_attribution');
if (attributionData) {
  const { short_code, timestamp } = JSON.parse(attributionData);
  if (isWithinAttributionWindow(timestamp)) {
    // Track with creator attribution
    await trackSubscriptionWithAttribution(short_code);
  } else {
    // Track as organic
    await trackSubscriptionAsOrganic();
  }
}
```

### Best Practices

1. **Attribution Storage**:
   - Store attribution data with timestamp
   - Include creator's short code
   - Use for subscription attribution

2. **Attribution Window**:
   - Default: 7 days
   - Check window for subscriptions
   - Fall back to 'ORGANIC' if expired

3. **Multiple Creators**:
   - Last-touch attribution model
   - Store most recent creator code
   - Respect attribution window

## API Reference

### Methods

#### `initialize(config: AttributionConfig): Promise<void>`

Initialize the Attribution SDK.

Parameters:
- `config.apiKey` (string): Your API key
- `config.appId` (string): Your app bundle ID
- `config.baseUrl` (string): API base URL
- `config.enableLocationTracking` (boolean): Enable location tracking
- `config.appStoreSharedSecret` (string, iOS only): App Store shared secret for receipt validation

#### `trackEvent(eventType: string, eventData: EventPayload): Promise<void>`

Track an attribution event.

Event Types:
- `'installation'`: Track app installation
- `'subscription'`: Track subscription purchase

### Types

```typescript
interface AttributionConfig {
  apiKey: string;
  appId: string;
  baseUrl: string; // https://reddimon.com/api/tracking
  enableLocationTracking?: boolean;
  appStoreSharedSecret?: string;
}

interface InstallationPayload {
  short_code: string;
  attribution_url?: string;
  platform: 'ios' | 'android';
  device_type?: string;
  install_source: string;
  click_timestamp?: number;
  install_timestamp: number;
}

interface SubscriptionPayload {
  short_code: string;
  subscription_id: string;
  plan_type: string;
  amount: number;
  currency: string;
  interval: 'weekly' | 'monthly' | 'yearly';
  payment_provider: 'app_store' | 'play_store' | 'stripe';
  subscription_date: number;
  event_type?: 'initial' | 'renewal' | 'cancellation';
  cancellation_reason?: string;
  status?: 'active' | 'cancelled' | 'expired';
}
```

## Error Handling

The SDK throws errors in these cases:
- Initialization errors (invalid config)
- Network errors (API unreachable)
- Validation errors (invalid payload)
- Permission errors (location/tracking denied)

Example:
```typescript
try {
  await Attribution.trackEvent('subscription', eventData);
} catch (error) {
  console.error('Attribution error:', error.message);
}
```

## Privacy & Permissions

The SDK respects user privacy and handles permissions appropriately:

- iOS: Requests ATT permission for IDFA access
- Android: Handles Advertising ID access
- Location: Only tracks when explicitly enabled and permitted
- Data: Follows GDPR and CCPA guidelines

## Testing

For testing attribution:

1. iOS Simulator:
```bash
xcrun simctl openurl booted "yourapp://attribution?code=test123"
```

2. Android Emulator:
```bash
adb shell am start -W -a android.intent.action.VIEW -d "yourapp://attribution?code=test123" com.yourapp.id
```

## License

MIT