# Privacy & consent

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

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

## Gating collection on consent

Tracking is on by default. To gate it behind a cookie banner, configure with `requireConsent: true` and grant consent when the banner is accepted:

```javascript
await Grovs.configure({ apiKey: "your-api-key", requireConsent: true });

// Nothing has been stored on the device or sent. Events tracked meanwhile are
// held in memory and delivered once consent arrives.
await Grovs.grantConsent();
```

`configure` resolves `false` while consent is pending. `grantConsent()` moves anything tracked meanwhile into durable storage, authenticates and resolves `true` on success. `configure` captures the URL's link token in memory, so a router that cleans the query string during the banner doesn't lose the deep link.

### Withdrawing consent

```javascript
Grovs.reset();
```

`reset()` clears every stored identifier, the session and queued events for all projects on the origin, and **stops tracking**. It doesn't re-authenticate on its own, by design. To start again, call `configure` (then `grantConsent()` if you require consent). A reset in one tab stops other tabs sending as the erased visitor.

### Disabling the SDK

```javascript
Grovs.setEnabled(false);
```

Disabling stops the SDK rather than muting it:

- Timers are cleared and lifecycle listeners detached.
- The History patch for screen tracking is removed, or left inert if another library has wrapped it since.
- In-app messages and the smart banner stop.
- Screen alias updates are held.

`setEnabled(true)` starts it again and re-runs an initialization interrupted mid-retry.

## What the SDK collects

| Data                                                                                                                                       | When                                                                             | Why                                                    |
| ------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------- | ------------------------------------------------------ |
| User agent, screen size, time zone, language, WebGL vendor and renderer strings, your `appVersion`, the SDK version, and a session id      | When `configure` authenticates                                                   | A device fingerprint used to match deferred deep links |
| A visitor identifier stored in a cookie and in `localStorage`                                                                              | Same                                                                             | Recognizing the visitor across visits                  |
| User identifier and attributes                                                                                                             | Only if you set them                                                             | Showing users in the dashboard                         |
| Installs, reinstalls, opens, time spent, reactivations                                                                                     | Automatically                                                                    | Attribution and analytics                              |
| Custom events and screen views, with your properties and tags, a session id, and the attribution path the visit arrived on                 | When you call `track` / `trackScreenView`, and through automatic screen tracking | Analytics                                              |
| Purchases                                                                                                                                  | When you call `logCustomPurchase`                                                | Revenue analytics                                      |
| In-app message views, clicks, dismissals and answers, with the campaign id; campaign sync requests                                         | When a campaign is shown or the SDK syncs                                        | In-app messages and their reports                      |
| The page path and the link data you passed to `setLinkData()`; `smart_banner_view`, `smart_banner_click` and `smart_banner_dismiss` events | On mobile browsers, when a smart banner shows                                    | The smart banner                                       |

With the default `requireConsent: false`, collection starts at `configure`. With `requireConsent: true`, nothing is written to the device or sent until `grantConsent()`.

The smart banner stores dismissals in `localStorage` (`grovs_smart_banner_dismissed`) and caches configuration and links in `sessionStorage` (`grovs_sb:*` keys). The web SDK never reads the clipboard. Stored state is keyed per project and `testEnvironment`; the visitor identifier is shared across projects on the origin.

### Safari

The visitor identifier goes in both a cookie and `localStorage`, because Safari's Intelligent Tracking Prevention caps script-written cookies at seven days. That covers visitors returning within the window. ITP can still evict storage for dormant visitors, so Safari install counts carry a small known over-count.

## Logs

Set the level with `debugLevel` in `configure`. Default `"error"`; an unrecognized `debugLevel` falls back to it.

`Grovs.setDebugLevel("info")` changes the configured client's level at any time. A value set before `configure` doesn't carry over, and an unrecognized value silences every log line, so pass only `"info"`, `"warn"` or `"error"`. Warnings (a rejected event name, an ignored alias pattern) print only at `"warn"` or `"info"`.
