> ## Documentation Index
> Fetch the complete documentation index at: https://docs.wendung.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Analytics consent

> Choose whether to collect aggregate pageviews while consent is pending, start full analytics after consent, and stop on withdrawal.

Full analytics uses a random anonymous ID and a session ID in the visitor's browser storage. You can wait for consent before collecting anything, or use `trackPageviews: 'auto'` to collect aggregate pageviews while the choice is pending. Aggregate pageviews contain no visitor or session identifiers.

Your consent manager supplies the visitor's choice. The SDK shows no banner and does not store that choice.

This page describes what the SDK does in each state. Whether your deployment needs consent, and which exemptions apply, is a question for your own legal review.

## The three states

| State | Browser storage | `step()`, `page()`, `identify()` | Network |
| - | - | - | - |
| `pending`, with `trackPageviews: 'auto'` | Nothing is read or written. | Only pageviews are collected. `identify()` and custom `step()` events are dropped. | Aggregate pageview batches are sent. |
| `pending`, with `trackPageviews: true`, `false`, or omitted | Nothing is read or written. | Dropped without queuing for later. | No requests. |
| `granted` | Anonymous ID, session, and identity as usual. | Collected from this moment on. Earlier activity is not replayed. | Batches are sent. |
| `denied` | The SDK's identifiers are removed and not recreated. | Dropped. | Queued events are discarded without being sent. |

Consent defaults to `granted`. Pass the current choice on every page load, using `pending` when the visitor has not chosen. Automatic pageviews are off by default. Set `trackPageviews: true` to wait for consent, or `'auto'` to collect aggregate pageviews while pending.

## Setup

<Steps>
  <Step title="Start pending, or restore the saved choice">
    Read the visitor's earlier choice from wherever you keep it and pass it to `init()`. With no saved choice, start pending.

    ```ts theme={null}
    import { Wendung, type ConsentState } from '@wendung/sdk'

    const saved = localStorage.getItem('analytics-consent') as ConsentState | null

    Wendung.init({
      apiKey: 'pk_your_publishable_key',
      trackPageviews: 'auto',
      consent: saved ?? 'pending',
    })
    ```

    This enables aggregate pageviews while pending and full analytics after consent. Use `trackPageviews: true` if you want no collection before consent.

    With the [script tag](/guides/script-tag), use `data-track-pageviews="auto"` and `data-consent="pending"`.
  </Step>

  <Step title="Apply the choice">
    Call `setConsent()` from your banner or consent manager. Granting consent starts full analytics for subsequent activity. If aggregate collection was active, the SDK sends the pending aggregate batch without recounting the current page. The next recorded pageview starts the consented web session. With `trackPageviews: true`, granting consent records the current page.

    If the visitor is already signed in, call `identify()` again. Calls made while pending were dropped, and earlier aggregate pageviews stay unlinked.

    ```ts theme={null}
    function onAnalyticsChoice(allowed: boolean) {
      localStorage.setItem('analytics-consent', allowed ? 'granted' : 'denied')
      Wendung.setConsent(allowed ? 'granted' : 'denied')
      if (allowed && currentUser) Wendung.identify(currentUser.id)
    }
    ```
  </Step>

  <Step title="Offer withdrawal">
    Keep a control in your settings that calls `setConsent('denied')`. It stops collection, discards anything still queued, and removes the SDK's identifiers from the browser. Events that were already delivered stay in your project; use the data deletion controls in the dashboard for those.

    `getConsent()` returns the current state, which is what a settings toggle reads.
  </Step>
</Steps>

## What aggregate pageviews can measure

Aggregate pageviews contribute to pageview totals and pageview breakdowns. They do not count as unique visitors, current visitors, or sessions. Bounce rate, session duration, views per session, and entry and exit pages describe consented traffic only.

The SDK omits query parameters, fragments, titles, screen dimensions, and visitor identifiers from aggregate pageviews. Pathnames can still contain personal information. See [pageview fields and limitations](/concepts/pageviews#aggregate-pageviews). This option does not establish a consent exemption for your deployment.

## With a consent manager

Connect the manager's callbacks to `setConsent()` and let the manager remain the source of truth. The example uses [CookieConsent](https://cookieconsent.orestbida.com/) with an `analytics` category; other managers expose equivalent hooks.

```ts theme={null}
import * as CookieConsent from 'vanilla-cookieconsent'
import { Wendung } from '@wendung/sdk'

Wendung.init({ apiKey: 'pk_your_publishable_key', consent: 'pending' })

const apply = () =>
  Wendung.setConsent(
    CookieConsent.acceptedCategory('analytics') ? 'granted' : 'denied',
  )

CookieConsent.run({
  categories: { necessary: { enabled: true, readOnly: true }, analytics: {} },
  onFirstConsent: apply,
  onConsent: apply,
  onChange: apply,
})
```

`onConsent` also applies the saved choice on later visits. This example leaves automatic pageviews off. Add `trackPageviews: 'auto'` to `init()` if you also want aggregate pageviews while pending and full pageviews after consent.

## In React

A small hook keeps the SDK, your storage, and the UI in one place.

```tsx theme={null}
import { useState } from 'react'
import { Wendung, type ConsentState } from '@wendung/sdk'

const STORAGE_KEY = 'analytics-consent'

export function useAnalyticsConsent() {
  const [consent, setConsent] = useState<ConsentState>(Wendung.getConsent())

  const choose = (choice: 'granted' | 'denied') => {
    localStorage.setItem(STORAGE_KEY, choice)
    Wendung.setConsent(choice)
    setConsent(choice)
  }

  return { consent, choose }
}
```

Render your notice while `consent === 'pending'` and a switch in settings bound to `consent === 'granted'`. The Wendung dashboard itself works this way: it asks once after sign-in and keeps the switch under **Account**.

## What the SDK does not do

* It does not store the choice. Pass it to `init()` on every page load.
* It does not replay activity from before consent, and it does not record which notice the visitor saw. Keep that record in your consent manager if you need to demonstrate consent.
* It does not retract batches that were already delivered.
* It does not collect aggregate pageviews after denial. `denied` stops all analytics, including with `trackPageviews: 'auto'`.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.