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

# What consent gates

> Wire your consent banner to allGood, and see exactly what is and isn't held back.

The account-side setup is on [Consent provider](/mk/developer/web-edge/consent-provider). This page is what your **website** has to do, and precisely what is gated.

<Tip>
  Just need the settings-level version, not the bridging code? See [Connect your consent platform](/mk/settings/web-edge/consent-provider).
</Tip>

## Your job on the page

Write the visitor's decision to the JavaScript global named in your settings. The default is `window.__consent`.

```js theme={null}
// granted
window.__consent = { analytics: true, marketing: true, necessary: true, version: "2.1" };

// denied
window.__consent = { analytics: false, marketing: false, necessary: true, version: "2.1" };
```

A plain boolean works too — `window.__consent = true`. Anything else, including nothing at all, reads as *not answered yet*, and the tag keeps waiting.

**Set it as early as you can**, ideally before the allGood tag loads. A value already present means no waiting at all.

### OneTrust

```html theme={null}
<script>
  function agSyncConsent() {
    // C0002 is OneTrust's default Performance/Analytics category.
    var groups = window.OnetrustActiveGroups || "";
    window.__consent = {
      analytics: groups.indexOf("C0002") !== -1,
      marketing: groups.indexOf("C0004") !== -1,
      necessary: true,
    };
  }
  window.OptanonWrapper = function () { agSyncConsent(); };
  window.addEventListener("OneTrustGroupsUpdated", agSyncConsent);
</script>
```

Check your own OneTrust configuration for the right category ids — `C0002` and `C0004` are the defaults, but they're editable.

### Cookiebot

```html theme={null}
<script>
  function agSyncConsent() {
    var c = window.Cookiebot && window.Cookiebot.consent;
    if (!c) return;
    window.__consent = {
      analytics: !!c.statistics,
      marketing: !!c.marketing,
      necessary: true,
    };
  }
  window.addEventListener("CookiebotOnAccept", agSyncConsent);
  window.addEventListener("CookiebotOnDecline", agSyncConsent);
  window.addEventListener("CookiebotOnLoad", agSyncConsent);
</script>
```

### Anything else

Set the provider to **Custom**, keep the signal source as it is, and write the same object from your own banner's callbacks.

## What the tag does, precisely

With **No tracking before opt-in** on, which is the default:

```
something happens (page view, identify, track)
   → held in memory rather than sent
   → read the consent signal
        granted   → send everything held, and send normally from now on
        denied    → throw away what was held, and send nothing more this page load
        no answer → keep checking, a couple of times a second
                      answered within half a minute → as above
                      still nothing → drop what was held
```

Four consequences worth designing around:

1. **A denial sticks for that page load.** A later yes doesn't restart it. A real visitor who changes their mind gets a fresh tag on their next page load, which is why this is acceptable — and it means pre-decision browsing is never delivered late, which is the point.
2. **Nothing is lost on a yes.** Everything held is sent, so a page view that happened before the banner was answered still arrives.
3. **What's held is finite.** On a page that fires a great many events before consent is answered, the oldest are dropped.
4. **Silence eventually gives up.** If your platform never writes the value — wrong path, banner that never loads — the tag holds, then quietly stops. This is the "nothing is recorded, no errors" case.

With the setting off, none of the above applies: events send immediately.

## The gating matrix

| Surface                                    | Gated?  | Notes                                               |
| ------------------------------------------ | ------- | --------------------------------------------------- |
| Page views from the tag                    | **Yes** | Held until granted                                  |
| `identify()`                               | **Yes** | Same                                                |
| `track()`                                  | **Yes** | Same                                                |
| Events sent to the API directly            | **Yes** | Refused without evidence of consent                 |
| **Form submission via the tag**            | **No**  | Always sent                                         |
| **Form submission via the API**            | **No**  | Never refused for consent                           |
| A hosted allGood landing page being served | **No**  | Records a view and sets the cookie regardless       |
| A tracked email click                      | **No**  | Works without consent; the link has to go somewhere |

### Why forms aren't gated

A submission is an explicit action by the visitor. Form processing rests on a different lawful basis from analytics consent, and refusing a lead because someone declined analytics cookies would be the wrong behaviour.

What forms *do* carry is the evidence: the exact consent statement the visitor was shown, stamped onto the record by allGood rather than supplied by the page. See [Consent text versions](/mk/developer/web-edge/consent-provider).

<Warning>
  Serving a landing page that allGood hosts records a page view and sets the identity cookie **before** anyone consents. The gate covers the tag and event capture; it doesn't cover the page-serve path. If a page must not do that, put it on your own site with the tag, where the gate does apply.
</Warning>

## The identity cookie

| Property                    | Value                                                   |
| --------------------------- | ------------------------------------------------------- |
| Name                        | `_ag_id`                                                |
| Value                       | A random identifier containing nothing about the person |
| Domain                      | Your allGood subdomain only                             |
| Lifetime                    | One year                                                |
| Set by                      | allGood only, never by page script                      |
| Readable by your JavaScript | No                                                      |

It proves a browser reached an allGood surface before. It does **not** prove anyone consented, which is why the two checks are separate.

## Testing the gate

The [hosted test page](/mk/developer/web-edge/test-your-setup) has Grant, Deny and Clear buttons that write the consent global exactly as a real banner would. Use them to watch events hold, then flush.
