# Consent Cookie



OptinStack stores the visitor's current consent state in a first-party cookie named `optinstack`.

The runtime reads this cookie during initialization to decide whether a visitor has already made a consent choice, which categories are granted, and whether the banner should appear again.

## Cookie format [#cookie-format]

The cookie value is URL-encoded JSON. After decoding, it has this shape:

```json
{
  "id": "f3f5cc3b-9c49-4f7b-9d30-4f5a5f6c2a10",
  "choices": {
    "necessary": true,
    "analytics": false,
    "marketing": false,
    "preferences": false
  },
  "timestamp": 1760000000000,
  "configVersion": "site-config-version"
}
```

| Field                 | Description                                                        |
| --------------------- | ------------------------------------------------------------------ |
| `id`                  | Consent record ID for the current saved choice.                    |
| `choices.necessary`   | Always `true`. Essential consent cannot be declined.               |
| `choices.analytics`   | Whether analytics consent is granted.                              |
| `choices.marketing`   | Whether marketing consent is granted.                              |
| `choices.preferences` | Whether preferences consent is granted.                            |
| `timestamp`           | Unix timestamp in milliseconds when this consent choice was saved. |
| `configVersion`       | Published configuration version that created the stored choice.    |

The cookie is written with `path=/` and expires based on the consent duration configured in the dashboard.

## Cross-subdomain sharing [#cross-subdomain-sharing]

When cross-domain consent sharing is enabled for a project on Business or Enterprise, OptinStack writes the consent cookie for the registrable site domain. For example, a site configured for `example.com` can share the same `optinstack` cookie across:

* `example.com`
* `www.example.com`
* `app.example.com`
* `docs.example.com`

That means a visitor who accepts consent on `www.example.com` can carry the same consent state to `app.example.com`, as long as both pages are under the same registrable domain and use the same OptinStack project configuration.

For sharing to work reliably, every subdomain should install the same project snippet and be served over HTTPS when secure cookies are enabled. Sharing is not available for localhost, preview hosts on unrelated domains, or separate production domains.

Browser cookies cannot be shared across unrelated domains, such as `example.com` and `example.net`. For that case, each domain needs its own consent state.

<Callout type="info">
  Cross-subdomain consent sharing requires a Business or Enterprise plan. In OptinStack, cross-domain consent sharing
  means sharing across subdomains of the same site domain. It does not bypass browser restrictions for unrelated
  domains.
</Callout>

Preview or staging hostnames from Webflow, Framer, and similar platforms usually live on a different registrable domain than your production site. They can be used to test banner behavior, but browser consent state will not carry from that preview hostname to your production hostname.

## Reading consent from a subdomain [#reading-consent-from-a-subdomain]

If another page on a subdomain needs to check consent before the runtime API is available, it can read the `optinstack` cookie directly:

```js
function readOptinStackConsent() {
  const value = document.cookie
    .split('; ')
    .find((part) => part.startsWith('optinstack='))
    ?.split('=')
    .slice(1)
    .join('=');

  if (!value) return null;

  try {
    return JSON.parse(decodeURIComponent(value));
  } catch {
    return null;
  }
}

const consent = readOptinStackConsent();

if (consent?.choices.analytics) {
  // Analytics consent is granted.
}
```

When the OptinStack runtime is loaded, prefer the JavaScript API because it validates the stored consent, handles expiry and configuration changes, and keeps subscribers updated:

```js
await window.OptinStack.ready;

if (window.OptinStack.analytics) {
  // Analytics consent is granted.
}
```

## Renewal and configuration changes [#renewal-and-configuration-changes]

The runtime may ignore or replace the stored cookie when:

* The cookie has expired based on your configured consent duration.
* Consent renewal is enabled and the saved choice is older than the allowed duration.
* The published configuration version changed and visitors must be prompted again.
* The visitor chooses to change consent through the banner, preferences dialog, or JavaScript API.

Use `window.OptinStack.renew()` when you intentionally want to clear stored consent and re-prompt the visitor.
