# Privacy & consent

> Gate the Grovs Flutter SDK on user consent, and see what it collects.

Source: https://docs.grovs.io/docs/sdk/flutter/privacy

Gate collection on user consent, and declare what the native SDKs collect.

## Gating collection on consent

A disabled SDK collects nothing. The plugin configures the native SDKs at launch, before any Dart runs, so the launch state must come from the native config files. Set `GrovsEnabled` to `false` in `Info.plist` and `grovs_enabled` to `false` in `AndroidManifest.xml`:

```xml
<!-- ios/Runner/Info.plist -->
<key>GrovsEnabled</key>
<false/>
```

```xml
<!-- android/app/src/main/AndroidManifest.xml, inside <application> -->
<meta-data
    android:name="grovs_enabled"
    android:value="false" />
```

Toggle it from Dart as consent changes:

```dart
import 'package:grovs_flutter_plugin/grovs.dart';

final grovs = Grovs();

Future<void> userDidChangeConsent(bool granted) async {
  await ConsentStore.save(granted); // your own storage
  await grovs.setSDK(granted);
}
```

The SDK **doesn't persist** the flag. Store the decision yourself and call `setSDK(true)` on every launch once you've restored a positive one:

```dart
void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  if (await ConsentStore.hasConsent()) {
    await Grovs().setSDK(true);
  }
  runApp(const App());
}
```

> **Warning:** Leaving the config key at `true` and calling `setSDK(false)` in `main()` is too late. The native SDK is already configured, authenticating, and on a first launch may have read the clipboard. Start disabled through the config key.

`setSDK` with the current state does nothing. On Android, every Flutter engine in the process shares the consent state, since the native SDK is configured once per process.

### While the SDK is disabled

The native SDKs behave as in a native app (full lists: [iOS](https://docs.grovs.io/docs/sdk/ios/privacy#while-the-sdk-is-disabled), [Android](https://docs.grovs.io/docs/sdk/android/privacy#while-the-sdk-is-disabled)):

- Nothing leaves the device: no authentication, device lookup, events, screen views or purchases.

- `generateLink` throws a `GrovsException`.

- Changes to the user identifier, attributes, push token and screen aliases are held as the latest values.

- Already-queued events and purchases stay on the device.

- No in-app messages show, and push taps aren't reported.

The plugin adds one rule: deep links and in-app events arriving while disabled aren't delivered on `onDeeplinkReceived` or `onInAppMessage`, and buffered ones are discarded. `linkDetails` throws `SDK_DISABLED` and `handleUrl` returns `false`.

### Enabling again

`setSDK(true)` authenticates if needed and sends everything held or queued.

The plugin also replays the link that launched the app while disabled: on Android by re-running the launch intent through `Grovs.onStart`, on iOS by handing the universal link or URL back to the SDK. Only the most recent launch link is kept; it arrives on `onDeeplinkReceived` once resolved.

On iOS, the plugin drops a link lookup in flight when `setSDK(false)` is called. If consent returns before that lookup completes, the native SDK may still deliver it.

## What the SDK collects

The plugin collects nothing itself; the native SDK does. Full tables: [iOS](https://docs.grovs.io/docs/sdk/ios/privacy#what-the-sdk-collects) and [Android](https://docs.grovs.io/docs/sdk/android/privacy#what-the-sdk-collects). Summary:

| Data                                                                                                                   | When                                                                                                                                                                                                                                                                                                                                                                                            |
| ---------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| App version and build, bundle ID or package name, device model, user agent, screen size, time zone, preferred language | When the SDK authenticates and looks up the device                                                                                                                                                                                                                                                                                                                                              |
| A device identifier (IDFV and a keychain identifier on iOS; the Android ID and the Play install referrer on Android)   | Same                                                                                                                                                                                                                                                                                                                                                                                            |
| User identifier, user attributes, push token                                                                           | Only if you set them                                                                                                                                                                                                                                                                                                                                                                            |
| Installs, opens, time spent, reactivations                                                                             | Automatically                                                                                                                                                                                                                                                                                                                                                                                   |
| Custom events and screen views                                                                                         | When you call `track` or `trackScreenView`, and through `Grovs.navigatorObserver`                                                                                                                                                                                                                                                                                                               |
| Purchases                                                                                                              | When you call `logInAppPurchase` or `logCustomPurchase`                                                                                                                                                                                                                                                                                                                                         |
| Push campaign opens                                                                                                    | When the user taps a Grovs push                                                                                                                                                                                                                                                                                                                                                                 |
| In-app message views, clicks, dismissals and answers                                                                   | When a message shows and the user acts on it                                                                                                                                                                                                                                                                                                                                                    |
| Clipboard contents                                                                                                     | Read once on the first launch after install, when your project has recent copy-to-clipboard clicks and the clipboard holds a web URL. Sent only if it's a link on a Grovs host or one of your `GrovsClipboardDomains` / `grovs_clipboard_domains`. See [clipboard-assisted deferred deep linking](https://docs.grovs.io/docs/sdk/flutter/deep-linking#clipboard-assisted-deferred-deep-linking) |

Neither native SDK reads the advertising identifier. iOS doesn't need App Tracking Transparency.

## Store privacy declarations

- **App Store:** the iOS SDK ships a privacy manifest; your App Privacy answers must cover what it collects. The plugin adds its own manifest, which declares nothing; since 3.1 it's included in CocoaPods builds as well as Swift Package Manager builds. See [iOS privacy manifest](https://docs.grovs.io/docs/sdk/ios/privacy#privacy-manifest) and [App Store privacy details](https://docs.grovs.io/docs/sdk/ios/privacy#app-store-privacy-details).
- **Google Play:** your Data safety form must cover the same. See [Google Play data safety](https://docs.grovs.io/docs/sdk/android/privacy#google-play-data-safety).

Anything in user attributes or event properties (an email or name, say) is data you collect too and needs its own declaration.

## Logs

`setDebugLevel` accepts `'info'` or `'error'`; anything else is treated as `'error'`. Use `'info'` while integrating:

```dart
await Grovs().setDebugLevel('info');
```

Where logs appear and how to filter them: [iOS logs](https://docs.grovs.io/docs/sdk/ios/privacy#logs), [Android logs](https://docs.grovs.io/docs/sdk/android/privacy#logs).
