Privacy & Consent
Gate the Grovs React Native SDK on user consent, and see what it collects
Gating collection on consent
Call setSDK(false) when the user declines analytics and setSDK(true) when they accept:
import Grovs from 'react-native-grovs-wrapper';
async function applyConsent(granted: boolean) {
await consentStore.save(granted);
Grovs.setSDK(granted);
}The native SDKs do not persist this flag, so the wrapper does it for you. setSDK stores the value on the device (in SharedPreferences on Android and UserDefaults on iOS), then forwards it to the native SDK. The default, before anything is stored, is true.
Start the next launch disabled
The native SDK is configured in MainApplication and AppDelegate, before any JavaScript runs. Configuring starts the first round of collection, so a setSDK(false) from JavaScript arrives too late for that launch unless the native configure call reads the stored value. Pass it through the enabled parameter, as the Quick Start and the Expo config plugin do:
import com.grovswrapper.GrovsConsent
Grovs.configure(
this, "your-api-key", useTestEnvironment = false, baseURL = null,
autoTrackScreenViews = false, clipboardDomains = null,
enabled = GrovsConsent.isEnabled(this)
)import react_native_grovs_wrapper
Grovs.configure(
APIKey: "your-api-key", useTestEnvironment: false,
autoTrackScreenViews: false, clipboardDomains: nil,
enabled: GrovsWrapperSwift.isSDKEnabled(), delegate: nil
)With this in place, a user who declined stays opted out from the first frame of the next cold start. Without it, every launch starts enabled until your JavaScript calls setSDK(false).
GrovsConsent.isEnabled and GrovsWrapperSwift.isSDKEnabled() return true until setSDK has been called once. On the very first launch the native SDK therefore starts enabled. If your app must be opted out before the user has answered, call Grovs.setSDK(false) as early as possible in your JavaScript on that launch: collection stops from that point, and the next cold start begins disabled.
While the SDK is disabled
The wrapper checks the stored flag before calling native for the features that need the backend:
generateLink,displayMessages, andnumberOfUnreadMessagesreject with an error whosecodeis'SDK_DISABLED'and whose message ends withGrovs SDK is disabled. Call setSDK(true) first.track,trackScreenView,logInAppPurchase, andlogCustomPurchaseare forwarded to the native SDK, which sends nothing while disabled.setIdentifier,setAttributes,setPushToken, andsetScreenAliasesare forwarded too; the native SDK holds the latest values and syncs them once it is enabled again.- Deep links are not resolved, so
onDeeplinkReceiveddoes not fire.
try {
const link = await Grovs.generateLink({ title: 'Invite' });
} catch (error) {
if ((error as { code?: string }).code === 'SDK_DISABLED') {
// ask for consent, then Grovs.setSDK(true)
}
}Everything else about the disabled state is the native SDK's: no authentication, device lookup, clipboard read, events, screen views, or purchases leave the device, and outstanding requests are cancelled. See Android and iOS for the full lists.
Re-enabling
setSDK(true) stores the value and enables the native SDK, which authenticates if needed and sends everything it held. On Android the wrapper also forwards onStart for the current Activity again, so a link the app was opened with while disabled is resolved and delivered to your listener. On iOS a launch link that arrived while disabled is not replayed.
What the SDK collects
The wrapper adds nothing of its own: it stores the consent flag locally and forwards your calls. What leaves the device is documented per platform, including the clipboard read used for clipboard-assisted deferred deep linking:
- What the Android SDK collects, and the Google Play data safety categories to declare
- What the iOS SDK collects, the bundled privacy manifest, and the App Store privacy details to declare
Anything you put in setAttributes or event properties, an email address or name for example, is data you collect too, and needs its own declaration.
Logs
setDebug('info') turns on verbose native logging; setDebug('error') restores the default. The native logs go through Logcat and os_log as described on the Android and iOS pages. The wrapper's own JavaScript logs, about which bridge it is using and listener registration, go to the Metro console with the prefix 🔗GROVS JS.