# Identity and storage

> What the widget keeps in the visitor's browser, how identify() ties visits to a person, and how that data is cleared.

The widget sets no cookies. What it keeps lives in the visitor's browser storage on your site's own domain, where only your pages can read it: `localStorage`, plus `sessionStorage` and IndexedDB for session recording. It does *read* cookies when a rule uses the **Cookie Value** condition, but never writes them.

## What's stored

Most keys end in `@` and your API key, as in `ge_visitor_id@YOUR_API_KEY`, so two GeoEngage sites on one domain keep separate visitors.

| Key | What it holds |
| --- | --- |
| `ge_visitor_id` | A random ID for this browser. |
| `ge_session` | The current session. A session ends after 15 minutes without activity. |
| `ge_visit_count` | How many sessions this browser has had. The **First Visit** condition matches the first. |
| `ge_last_visit` | When this browser's current visit began. |
| `ge_prev_visit` | When the visit before it began. Read by the **Days Since Last Visit** condition. |
| `ge_user_email` | The email from `identify()`, until `clearIdentity()`. |
| `ge_visitor_attributes` | Attributes from `setAttributes()`, until `clearAttributes()`. |
| `ge_consent_status` | `pending`, `accepted` or `rejected`, from the compliance banner. Read by the **Consent Status** condition. |
| `ge_consent_preferences` | The consent categories the visitor chose on the compliance banner. |
| `geoengage_consent` | `granted` once the visitor has accepted in consent mode. |
| `geoengage_ignore` | `true` in a browser you've [left out of your numbers](https://geoengage.app/docs/analytics#leaving-out-your-own-visits). Only you set it; the widget never does. |
| `geoengage_data_*` | Cached rules, tracking settings and location, so repeat page views start faster. |

The consent keys and `geoengage_ignore` are shared by every site on the domain: they record one person's answer about one website. Two other keys are bookkeeping: `ge_collect` remembers what your plan lets the widget send, and `ge_visit_counted_*` keeps a visit from being counted twice.

## Session recording

With session recording on, the recorder also keeps:

| Where | Key | What it holds |
| --- | --- | --- |
| `sessionStorage` | `ge_tab_id`, `ge_tab_recording_start` | An ID for this browser tab and when its recording began, so each tab is recorded on its own. Gone when the tab closes. |
| `localStorage` | `ge_replay_sample` | Whether this session was picked for recording, when you record less than 100% of visits. |
| IndexedDB | `ge_replay_outbox` | Recorded batches waiting for the server to confirm them. Each is removed once it arrives; anything older than a day is dropped. |
| `localStorage` | `ge_replay_overflow` | The last seconds of a page that closed before they could be sent. The next page sends them. |

`revokeConsent()` deletes the outbox and the overflow at once.

## Identifying visitors

A visitor starts out anonymous: a random ID and nothing else. `GeoEngage.identify(email)` adds an email address, which is stored in `ge_user_email` and sent with every event from then on, until `GeoEngage.clearIdentity()` removes it. Call `identify` when someone signs in, and `clearIdentity` when they sign out.

## Clearing it

- `clearIdentity()` and `clearAttributes()` remove what your own code stored.
- Clearing the site's data in the browser removes everything; the visitor then counts as new. Close the site's tabs first: a page that is still open puts back the visitor and session IDs it was using.
- In consent mode, `revokeConsent()` stops tracking from the next page load. See [Consent mode](https://geoengage.app/docs/widget/consent#revokeconsent).

---

Source: https://geoengage.app/docs/widget/storage
