1.2.0 • Published 7 months ago
@reddimon/react-native-attribution v1.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
npm install @reddimon/react-native-attribution
# or
yarn add @reddimon/react-native-attributioniOS Setup
- Add these permissions to your
Info.plist:
<!-- 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>- For deep linking, add URL scheme:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>yourapp</string>
</array>
</dict>
</array>Android Setup
- Add permissions to
AndroidManifest.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" />- For deep linking, add intent filter:
<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
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
// 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
// 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
- When a user clicks a creator's link:
// Store attribution data when processing deep link
await AsyncStorage.setItem('last_attribution', JSON.stringify({
short_code: extractedShortCode,
timestamp: Date.now()
}));- When tracking installations:
// Use the short_code directly from the deep link
await trackInstallation(shortCode, attributionUrl);- When tracking subscriptions:
// 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
Attribution Storage:
- Store attribution data with timestamp
- Include creator's short code
- Use for subscription attribution
Attribution Window:
- Default: 7 days
- Check window for subscriptions
- Fall back to 'ORGANIC' if expired
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 keyconfig.appId(string): Your app bundle IDconfig.baseUrl(string): API base URLconfig.enableLocationTracking(boolean): Enable location trackingconfig.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
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:
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:
- iOS Simulator:
xcrun simctl openurl booted "yourapp://attribution?code=test123"- Android Emulator:
adb shell am start -W -a android.intent.action.VIEW -d "yourapp://attribution?code=test123" com.yourapp.idLicense
MIT