UNPKG

@viss-develop/affiliate-sdk

Version:

React Native Affiliate SDK with AppsFlyer integration

466 lines (383 loc) 13.6 kB
# React Native Affiliate SDK A React Native SDK for tracking affiliate conversions with AppsFlyer integration and enterprise-grade security. ## Features - ✅ **AppsFlyer Integration**: Automatic install conversion tracking - ✅ **Buy Conversion**: Create buy conversions using stored clickId and campaignId - ✅ **Custom Conversion**: Create custom conversions with explicit clickId and campaignId - ✅ **Local Storage**: Automatic storage and retrieval of affiliate data - ✅ **TypeScript Support**: Full type definitions included - ✅ **Optional Parameters**: Support for detailed conversion data (orderId, amounts, conversion parts, etc.) - ✅ **Enterprise Security**: Production-safe logging with automatic data masking - ✅ **Debug Mode Control**: Separate logging behavior for development and production ## Installation ```bash npm install @viss-develop/affiliate-sdk ``` ## Quick Start ### 1. Initialize AppsFlyer ```javascript import { initAppsFlyer } from '@viss-develop/affiliate-sdk'; // Development (with secure logging) await initAppsFlyer({ devKey: 'your-dev-key', appId: 'your-app-id', apiToken: 'your-api-token', isDebug: true, // Shows masked logs for debugging onInstallConversionData: (data) => { console.log('📱 Install Conversion Data received:', data); if (data.status === 'success') { console.log('✅ Install conversion data success'); const conversionData = data.data; if (conversionData) { if (conversionData.is_first_launch) { console.log('🎉 First launch detected!'); } // Check if auto-conversion was triggered if (conversionData.click_id && conversionData.campaign_id) { console.log('🔄 Auto-conversion triggered for install'); } } } } }); // Production (no sensitive data logged) await initAppsFlyer({ devKey: 'your-dev-key', appId: 'your-app-id', apiToken: 'your-api-token', isDebug: false, // No logs, maximum security onInstallConversionData: (data) => { // Handle conversion data } }); ``` ### 2. Create Buy Conversion ```javascript import { createBuyConversion } from '@viss-develop/affiliate-sdk'; // Simple buy conversion using stored data const handleSimpleBuyConversion = async () => { try { const result = await createBuyConversion(); if (result.success) { console.log('✅ Buy conversion created:', result.data); } else { console.error('❌ Buy conversion failed:', result.error); } } catch (error) { console.error('❌ Unexpected error:', error); } }; // Buy conversion with optional data const handleBuyConversionWithData = async () => { try { const result = await createBuyConversion( 'ord.001', // orderId Date.now(), // actionTime { amount: 10000, currency: 'VND' }, // totalDiscount { amount: 100000, currency: 'VND' }, // totalSaleAmount { amount: 5000, currency: 'VND' }, // totalCommission '192.168.1.1', // clientIp 'React Native App', // userAgent [ // conversionParts { sku: 'product_001', url: 'https://example.com/product/001', price: 100000, discount: 10000, saleAmount: 90000, currency: 'VND', name: 'Sample Product', categoryName: 'Electronics', categoryId: 'cat_001', quantity: 1, commission: { amount: 5000, currency: 'VND' }, calculateBy: 'FIXED' } ] ); if (result.success) { console.log('✅ Buy conversion with data created:', result.data); } else { console.error('❌ Buy conversion with data failed:', result.error); } } catch (error) { console.error('❌ Unexpected error:', error); } }; ``` ### 3. Create Custom Conversion ```javascript import { createCustomConversion, getStoredClickId, getStoredCampaignId } from '@viss-develop/affiliate-sdk'; // Custom conversion using stored data const handleCustomConversionFromStored = async () => { try { // Get stored clickId and campaignId first const storedClickId = await getStoredClickId(); const storedCampaignId = await getStoredCampaignId(); if (!storedClickId || !storedCampaignId) { console.error('❌ No stored clickId or campaignId found'); return; } // Use stored data for custom conversion const result = await createCustomConversion( storedClickId, // use stored clickId storedCampaignId, // use stored campaignId 'buy', // action 'stored_ord.001', // orderId Date.now(), // actionTime undefined, // totalDiscount { amount: 75000, currency: 'VND' }, // totalSaleAmount { amount: 3750, currency: 'VND' }, // totalCommission undefined, // clientIp undefined, // userAgent [ // conversionParts { sku: 'registration_success', url: 'https://example.com/register', price: 0, discount: 0, saleAmount: 0, currency: 'VND', name: 'User Registration', categoryName: 'Registration', categoryId: 'reg_001', quantity: 1, commission: { amount: 10000, currency: 'VND' }, calculateBy: 'FIXED' } ] ); if (result.success) { console.log('✅ Custom conversion with stored data created:', result.data); } else { console.error('❌ Custom conversion with stored data failed:', result.error); } } catch (error) { console.error('❌ Unexpected error:', error); } }; // Custom conversion with explicit values const handleCustomConversionExplicit = async () => { try { const result = await createCustomConversion( 'GKbQfVgyCIFkTvVmZHyMPOTpKLHGkE', // clickId (required) 9, // campaignId (required) 'register', // action 'custom_ord.001', // orderId Date.now(), // actionTime undefined, // totalDiscount { amount: 0, currency: 'VND' }, // totalSaleAmount { amount: 10000, currency: 'VND' }, // totalCommission undefined, // clientIp undefined, // userAgent undefined // conversionParts ); if (result.success) { console.log('✅ Custom conversion with explicit values created:', result.data); } else { console.error('❌ Custom conversion with explicit values failed:', result.error); } } catch (error) { console.error('❌ Unexpected error:', error); } }; ``` ### 4. Get Stored Data ```javascript import { getStoredClickId, getStoredCampaignId, getStoredInstallData } from '@viss-develop/affiliate-sdk'; const handleGetStoredData = async () => { try { const clickId = await getStoredClickId(); const campaignId = await getStoredCampaignId(); const installData = await getStoredInstallData(); console.log('📊 Stored Data:', { clickId: clickId || 'Not found', campaignId: campaignId || 'Not found', installData: installData || 'Not found' }); } catch (error) { console.error('❌ Failed to get stored data:', error); } }; ``` ## Security Features The SDK includes enterprise-grade security with automatic data masking and production-safe logging. ### Data Masking Sensitive information is automatically masked in logs: ```javascript // Before: "abc123def456" // After: "abc1***def4" // Masked keys: - devKey → "abc1***def4" - apiToken → "tok1***ken4" - clickId → "cli1***id4" - campaignId → "***" ``` ### Debug Mode Control ```javascript // Development (debug on) - Shows masked logs await initAppsFlyer({ devKey: 'your-dev-key', appId: 'your-app-id', apiToken: 'your-api-token', isDebug: true // ✅ Shows masked logs for debugging }); // Production (debug off) - No sensitive data logged await initAppsFlyer({ devKey: 'your-dev-key', appId: 'your-app-id', apiToken: 'your-api-token', isDebug: false // ✅ No logs, maximum security }); ``` ## API Reference ### `initAppsFlyer(config)` Initialize AppsFlyer SDK and store affiliate data. **Parameters:** - `config` (AppsFlyerConfig): Configuration object - `devKey` (string): AppsFlyer dev key - `appId` (string): App ID (iOS) or package name (Android) - `apiToken` (string): API token for conversion service - `isDebug` (boolean): Enable/disable debug logging (default: false) - `onInstallConversionData` (function): Callback for install conversion data ### `createBuyConversion(orderId?, actionTime?, totalDiscount?, totalSaleAmount?, totalCommission?, clientIp?, userAgent?, conversionParts?)` Create buy conversion using stored clickId and campaignId. **Parameters:** - `orderId` (string, optional): Order ID - `actionTime` (number, optional): Action timestamp - `totalDiscount` (MonetaryAmount, optional): Total discount - `totalSaleAmount` (MonetaryAmount, optional): Total sale amount - `totalCommission` (MonetaryAmount, optional): Total commission - `clientIp` (string, optional): Client IP address - `userAgent` (string, optional): User agent string - `conversionParts` (ConversionPart[], optional): Conversion parts array **Returns:** Promise with result object ```javascript { success: boolean, data?: any, error?: string } ``` ### `createCustomConversion(clickId, campaignId, action?, orderId?, actionTime?, totalDiscount?, totalSaleAmount?, totalCommission?, clientIp?, userAgent?, conversionParts?)` Create custom conversion with explicit clickId and campaignId. **Parameters:** - `clickId` (string, required): Click ID from affiliate link - `campaignId` (number, required): Campaign ID - `action` (string, optional): Action type (default: 'buy') - `orderId` (string, optional): Order ID - `actionTime` (number, optional): Action timestamp - `totalDiscount` (MonetaryAmount, optional): Total discount - `totalSaleAmount` (MonetaryAmount, optional): Total sale amount - `totalCommission` (MonetaryAmount, optional): Total commission - `clientIp` (string, optional): Client IP address - `userAgent` (string, optional): User agent string - `conversionParts` (ConversionPart[], optional): Conversion parts array **Returns:** Promise with result object (same as createBuyConversion) ### `getStoredClickId()` Get stored clickId from local storage. **Returns:** Promise<string | null> ### `getStoredCampaignId()` Get stored campaignId from local storage. **Returns:** Promise<number | null> ### `getStoredInstallData()` Get stored install data from local storage. **Returns:** Promise<InstallConversionData | null> ### `clearStoredAffiliateData()` Clear all stored affiliate data. **Returns:** Promise<void> ## Types ### `MonetaryAmount` ```typescript interface MonetaryAmount { amount: number; currency: string; } ``` ### `ConversionPart` ```typescript interface ConversionPart { sku?: string; url?: string; price?: number; discount?: number; saleAmount?: number; currency?: string; name?: string; categoryName?: string; categoryId?: string; quantity?: number; commission?: MonetaryAmount; calculateBy?: string; } ``` ### `InstallConversionData` ```typescript interface InstallConversionData { af_status: string; is_first_launch: boolean; click_id?: string; campaign_id?: number; media_source?: string; campaign?: string; // ... other AppsFlyer data } ``` ## How it works 1. **Initialization**: AppsFlyer is initialized with dev key and app ID 2. **Data Storage**: When install conversion data is received, clickId and campaignId are stored locally 3. **Buy Conversion**: Uses stored data to create buy conversions 4. **Custom Conversion**: Uses explicit clickId and campaignId or retrieves from storage 5. **Security**: All sensitive data is automatically masked in logs 6. **Optional Data**: All functions support optional parameters like orderId, amounts, conversion parts, etc. ## Example App A complete demo app is included in the `example/` directory with the following features: - **Create Buy Conversion (Simple)**: Create buy conversion with stored data - **Create Buy Conversion (With Data)**: Create buy conversion with optional parameters - **Create Custom Conversion (From Stored)**: Create custom conversion using stored data - **Get Stored Data**: View stored data in the SDK ### Run Example App ```bash cd example npm install npx react-native run-ios # or npx react-native run-android ``` ## Security The SDK includes production-safe logging with automatic data masking. Sensitive information like `devKey`, `apiToken`, `clickId`, and `campaignId` are automatically masked in logs. ### Production Usage ```javascript // For production - no sensitive data logged await initAppsFlyer({ devKey: 'your-dev-key', appId: 'your-app-id', apiToken: 'your-api-token', isDebug: false // ✅ No sensitive data exposure }); ``` ### Development Usage ```javascript // For development - sensitive data masked await initAppsFlyer({ devKey: 'your-dev-key', appId: 'your-app-id', apiToken: 'your-api-token', isDebug: true // ✅ Shows masked logs: "abc1***def4" }); ``` For detailed security information, see [SECURITY.md](./SECURITY.md). ## Example Usage See `example-usage-with-optional-data.js` for complete usage examples with all optional parameters. ## Version History - **v1.0.3**: Added enterprise security with automatic data masking - **v1.0.2**: Flattened API parameters, improved TypeScript types - **v1.0.1**: Initial release with basic functionality ## License MIT License