UNPKG

react-native-efilli-sdk

Version:
575 lines (445 loc) 15.3 kB
# React Native Efilli SDK A React Native SDK for managing user consent preferences in mobile applications, with support for both iOS and Android platforms. ## Overview The Efilli SDK provides a simple and customizable way to collect and manage user consent for data processing, tracking, and other privacy-related functions in React Native applications. The SDK handles the presentation of consent choices, storage of user preferences, and provides an easy-to-use API for integrating consent management into your app. ## Features - ✅ Cross-platform support (iOS and Android) - ✅ Customizable consent form via WebView - ✅ Local storage of consent preferences - ✅ TypeScript support with type-safe API - ✅ Comprehensive error handling - ✅ Network connectivity detection - ✅ Error reporting capabilities - ✅ Simple integration with React Native applications ## Requirements - iOS 12.0+ - Android 5.0+ (API level 21+) - React Native 0.65+ - React 17.0+ ## Installation ```bash # Using npm npm install react-native-efilli-sdk # Using yarn yarn add react-native-efilli-sdk ``` ### iOS Setup For iOS, the SDK uses Swift and requires your project to be configured for using Swift modules: 1. Make sure you have CocoaPods installed 2. Ensure your Podfile includes the use_frameworks! directive or use_modular_headers! for Swift compatibility 3. Run pod install in your iOS directory ```bash cd ios && pod install ``` ### Android Setup The SDK automatically includes the necessary Android configuration. For Android, ensure you have set up React Native properly and linked the module: ```bash # React Native 0.60+ cd android && ./gradlew clean ``` ## Integration Guide ### 1. Initialize the SDK The first step is to initialize the SDK with your consent form URL and language configuration: ```javascript import { EfilliSDK } from 'react-native-efilli-sdk'; // Initialize the SDK at app startup, typically in your App.js/App.tsx file async function initializeConsentSDK() { try { await EfilliSDK.initialize({ endpointUrl: 'https://your-consent-form-url.com', language: 'en-US' }); console.log('Efilli SDK initialized successfully'); } catch (error) { console.error('Failed to initialize Efilli SDK:', error); } } ``` ### 2. Display the Consent Form When you need to show the consent form to users (e.g., at first app launch or when privacy settings need updating): ```javascript async function showConsentForm() { try { const result = await EfilliSDK.showConsentForm(); console.log('User consent result:', result); // Handle the consent choices if (result.action === 'save' || result.action === 'accept-all') { // User accepted consent handleAcceptedConsent(result.data); } else if (result.action === 'reject-all') { // User rejected optional consent handleRejectedConsent(); } } catch (error) { console.error('Error showing consent form:', error); } } ``` ### 3. Check for Existing Consent Before showing the consent form, you may want to check if the user has already provided consent: ```javascript async function checkExistingConsent() { try { const storedConsent = await EfilliSDK.getStoredConsent(); if (storedConsent) { console.log('User has already provided consent:', storedConsent); return true; } else { console.log('No existing consent found'); return false; } } catch (error) { console.error('Error checking stored consent:', error); return false; } } ``` ### 4. Handling Consent in Your App ```javascript function handleAcceptedConsent(categories) { // Example: Enable features based on consent if (categories.marketing) { // Enable marketing features enableMarketingTracking(); } if (categories.functional) { // Enable functional cookies/features enableFunctionalFeatures(); } // Essential features are always enabled } function handleRejectedConsent() { // Disable all optional features disableMarketingTracking(); disableFunctionalFeatures(); // Essential features remain enabled } ``` ### 5. Changing Language If your app supports multiple languages, you can update the consent form language: ```javascript async function changeLanguage(newLanguage) { try { await EfilliSDK.changeLanguage(newLanguage); // e.g., 'fr-FR', 'de-DE', etc. console.log('Language changed successfully'); } catch (error) { console.error('Error changing language:', error); } } ``` ### 6. Clearing Consent Data For GDPR compliance or when a user wants to reset their choices: ```javascript async function clearConsentData() { try { await EfilliSDK.clearAllData(); console.log('Consent data cleared successfully'); } catch (error) { console.error('Error clearing consent data:', error); } } ``` ## API Reference ### EfilliSDK #### Initialization ```typescript EfilliSDK.initialize(options: EfilliOptions): Promise<void> ``` Parameters: - `options.endpointUrl` (string): URL to your consent form webpage - `options.language` (string): Language code for localization (e.g., 'en-US', 'fr-FR') #### Checking Initialization Status ```typescript EfilliSDK.isReady(): Promise<boolean> ``` Returns `true` if the SDK is initialized and ready for use. #### Show Consent Form ```typescript EfilliSDK.showConsentForm(): Promise<ConsentResult> ``` Displays the consent form WebView to the user and returns the result after user selection. #### Get Stored Consent ```typescript EfilliSDK.getStoredConsent(): Promise<ConsentResult | null> ``` Retrieves previously stored consent choices. #### Change Language ```typescript EfilliSDK.changeLanguage(language: string): Promise<void> ``` Changes the language used for the consent form. #### Clear All Data ```typescript EfilliSDK.clearAllData(): Promise<void> ``` Clears all stored consent data. #### Close SDK ```typescript EfilliSDK.closeSDK(): Promise<void> ``` Properly closes and cleans up SDK resources. ### EfilliNetwork The SDK also provides network-related functionality: #### Post Error Report ```typescript EfilliNetwork.postError(errorType: string, errorMessage: string, errorStack: string): Promise<boolean> ``` Reports errors to your error tracking system. #### Get Connection Type ```typescript EfilliNetwork.getConnectionType(): Promise<string> ``` Returns the current network connection type (e.g., 'wifi', 'cellular', 'none'). ## Data Models ### ConsentResult Represents the result of a consent decision. ```typescript interface ConsentResult { action: 'save' | 'accept-all' | 'reject-all' | 'saved-consent'; data?: { essential: boolean; functional: boolean; marketing: boolean; other: boolean; }; } ``` ## Creating Your Consent Form Your consent form webpage needs to communicate with the SDK using the JavaScript bridge. Here's how to set it up: ### For iOS WebView Communication ```javascript // In your consent form HTML/JavaScript function sendConsentToiOS(action, categories) { const consentData = { action: action, data: categories }; // Use the EfilliSDK bridge if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.eventListener) { window.webkit.messageHandlers.eventListener.postMessage(JSON.stringify(consentData)); } else if (window.EfilliSDK && window.EfilliSDK.sendConsent) { window.EfilliSDK.sendConsent(consentData); } } ``` ### For Android WebView Communication ```javascript // In your consent form HTML/JavaScript function sendConsentToAndroid(action, categories) { const consentData = { action: action, data: categories }; // Use the Android bridge if (window.android && window.android.postMessage) { window.android.postMessage(JSON.stringify(consentData)); } } // Cross-platform function to use in your consent form function sendConsent(action, categories) { const consentData = { action: action, data: categories }; // Detect platform and use appropriate bridge if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.eventListener) { // iOS window.webkit.messageHandlers.eventListener.postMessage(JSON.stringify(consentData)); } else if (window.android && window.android.postMessage) { // Android window.android.postMessage(JSON.stringify(consentData)); } else if (window.EfilliSDK && window.EfilliSDK.sendConsent) { // iOS alternative window.EfilliSDK.sendConsent(consentData); } } // Example usage document.getElementById('accept-all-button').addEventListener('click', function() { sendConsent('accept-all', { essential: true, functional: true, marketing: true, other: true }); }); document.getElementById('reject-all-button').addEventListener('click', function() { sendConsent('reject-all', { essential: true, functional: false, marketing: false, other: false }); }); document.getElementById('save-button').addEventListener('click', function() { sendConsent('save', { essential: true, functional: document.getElementById('functional-checkbox').checked, marketing: document.getElementById('marketing-checkbox').checked, other: document.getElementById('other-checkbox').checked }); }); ``` ## Error Handling The SDK provides detailed error handling with descriptive error messages. All methods return Promises, so errors can be caught using standard try/catch blocks. Error types include: - `INVALID_PARAMETERS`: Missing or incorrect initialization parameters - `INVALID_URL`: Malformed URL provided - `NOT_INITIALIZED`: Attempt to use SDK before initialization - `SHOW_CONSENT_ERROR`: Error showing the consent form - `NETWORK_ERROR`: Network connectivity issues - `INVALID_RESULT`: Invalid consent result format - `PARSE_ERROR`: Error parsing consent data ## Storage Implementation ### iOS Storage On iOS, consent data is stored using `UserDefaults` with a custom suite name for isolation. ### Android Storage On Android, consent data is stored using `SharedPreferences` with a private mode for security. ## Best Practices 1. **Initialize Early**: Initialize the SDK as early as possible in your app's lifecycle. 2. **Error Handling**: Always implement proper error handling around SDK method calls. 3. **Check Existing Consent**: Before showing the consent form, check if the user has already provided consent. 4. **Language Support**: Set the appropriate language for your users based on their device settings. 5. **Clear Consent Data**: Provide a way for users to reset their consent choices. 6. **Testing**: Test the consent flow thoroughly, including edge cases like network failures. ## Advanced Configuration ### Customizing the Consent Form The consent form is loaded from your provided URL, giving you full control over its design and behavior. You can: 1. Style the form to match your app's branding 2. Add custom logic for different consent flows 3. Implement localization support 4. Add analytics tracking (if consent is provided) ### Debugging The SDK includes extensive logging to help with debugging: - iOS: Check the Xcode debug console for logs with the prefix "📢" or "✅" - Android: Filter LogCat for "EfilliSDK" or "EfilliConsentActivity" tags ## Example Implementation ```tsx import React, { useState, useEffect } from 'react'; import { View, Button, Text, StyleSheet, Alert } from 'react-native'; import { EfilliSDK, EfilliNetwork } from 'react-native-efilli-sdk'; const App = () => { const [isInitialized, setIsInitialized] = useState(false); const [consentData, setConsentData] = useState(null); useEffect(() => { initializeSDK(); }, []); const initializeSDK = async () => { try { await EfilliSDK.initialize({ endpointUrl: 'https://example.com/consent-form', language: 'en-US' }); setIsInitialized(true); // Check for existing consent const storedConsent = await EfilliSDK.getStoredConsent(); if (storedConsent) { setConsentData(storedConsent); } } catch (error) { Alert.alert('Initialization Error', error.message); } }; const handleShowConsentForm = async () => { try { const result = await EfilliSDK.showConsentForm(); setConsentData(result); Alert.alert('Consent Updated', `Action: ${result.action}`); } catch (error) { Alert.alert('Error', error.message); } }; const handleClearData = async () => { try { await EfilliSDK.clearAllData(); setConsentData(null); Alert.alert('Success', 'Consent data cleared'); } catch (error) { Alert.alert('Error', error.message); } }; return ( <View style={styles.container}> <Text style={styles.title}>Efilli Consent Manager</Text> <Text style={styles.status}> Status: {isInitialized ? 'Initialized' : 'Not Initialized'} </Text> <Button title="Show Consent Form" onPress={handleShowConsentForm} disabled={!isInitialized} /> <Button title="Clear Consent Data" onPress={handleClearData} disabled={!isInitialized} /> {consentData && ( <View style={styles.consentContainer}> <Text style={styles.consentTitle}>Consent Choices:</Text> <Text>Action: {consentData.action}</Text> {consentData.data && ( <> <Text>Essential: {consentData.data.essential ? 'Yes' : 'No'}</Text> <Text>Functional: {consentData.data.functional ? 'Yes' : 'No'}</Text> <Text>Marketing: {consentData.data.marketing ? 'Yes' : 'No'}</Text> <Text>Other: {consentData.data.other ? 'Yes' : 'No'}</Text> </> )} </View> )} </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, padding: 20, justifyContent: 'center', gap: 20, }, title: { fontSize: 24, fontWeight: 'bold', marginBottom: 20, }, status: { fontSize: 16, marginBottom: 20, }, consentContainer: { marginTop: 20, padding: 15, backgroundColor: '#f5f5f5', borderRadius: 10, }, consentTitle: { fontSize: 18, fontWeight: 'bold', marginBottom: 10, }, }); export default App; ``` ## Troubleshooting ### Common Issues and Solutions #### Consent Data Not Saving - iOS: Check that your UserDefaults implementation is working properly - Android: Verify SharedPreferences are being written correctly #### WebView Not Loading - Check your internet connection - Verify the URL is correct and accessible - Check for any SSL certificate issues #### Language Not Changing - Ensure the language code format is correct (e.g., 'en-US', not just 'en') - Verify that your consent form handles language changes correctly #### WebView Communication Errors - Make sure your JavaScript code properly detects the platform - Check that message formats match exactly what the SDK expects ## License [License details as provided by the licensee] ## Support For issues, questions, or contributions, please open an issue on the GitHub repository: https://github.com/mobile-sdk-lab/efilli-react-native-sdk-v2 --- © Efilli. All rights reserved.