---
title: "GDPR / TCF consent: options, signals and macros reference"
description: "Every consent-verification option on the GDPR card, the order the ad server checks consent in, the request parameters and tag attributes it reads, what the cookie beacons and cookie sync do under a per-request cookie policy, the macros that pass consent downstream, and the troubleshooting-log lines that show the verdict."
type: "reference"
audience: [admin, developer]
keywords: [GDPR, TCF 2.x, IAB vendor id, Check disclosed vendors, Verify CMP, Global CMP List, Enforce TCF policy version, Min TCF policy version, GPC, Sec-GPC, gdprConsentIab, data-gdpr-consent-iab, uc, data-user-consent, cookie-policy, usPrivacy, gpp, gppSid, coppa, $$GDPR$$, $$GDPR_CONSENT_IAB$$, $$COOKIE_POLICY$$, TCF Consent Info, regs.gdpr, user.consent]
ui_path: "Admin → Ad serving → System preferences → GDPR"
---

Fetch the complete documentation index at: https://epom.com/ad-server/docs/llms.txt. Use this file to discover all available pages before exploring further. Append .md to any documentation page URL to get its markdown version.

# GDPR / TCF consent: options, signals and macros reference

Reference for [Configure GDPR / TCF consent enforcement](https://epom.com/ad-server/docs/guides/admin/gdpr-tcf-consent.md): the fields on
the card one by one, how the ad server reaches its verdict, which request parameters it reads,
and how the verdict and the signals travel on.

## Consent-verification options

These tighten what counts as valid consent. All five are off by default, and none of them has any
effect while the policy is *Default*.

| Field | What it does | Default |
|---|---|---|
| **IAB vendor id** | The vendor whose consent the TC string must grant. The request passes only when this id is in the string's vendor-consent list. | 849 (Epom) |
| **Restrict DSP mediation** | Additionally drops **OpenRTB** creatives from the auction for no-consent requests, whatever the restriction says — they are excluded with the reason `GDPR_MEDIATION_RESTRICTED`. No other creative type is affected. | off |
| **Check disclosed vendors** | Also requires the vendor id in the string's **disclosed-vendors** segment, not just the vendor-consent segment. Only works when the CMP actually emits that segment; when it does not, every string fails this check. | off |
| **Verify CMP against the IAB list** | Rejects the string when its `cmpId` is not on the IAB Europe Global CMP List, or is on it but marked deleted. The list is refreshed daily from IAB Europe; until it has been loaded for the first time every `cmpId` is accepted. | off |
| **Enforce TCF policy version** | Rejects strings whose TCF policy version is below **Min TCF policy version**. | off |
| **Min TCF policy version** | The floor for the check above; enabled only when it is ticked. `4` = TCF v2.2. The field limits input to 2–10 in the browser; the server does not check the range and stores whatever it is sent. | 4 |
| **Honour GPC opt-out signal** | Treats a Global Privacy Control opt-out — `gpc=1` on the request, or a `Sec-GPC: 1` header — as no consent. It is checked only for requests in GDPR scope, where it comes before every other consent check; a request outside GDPR scope is not affected. | off |

## How the decision is made

For each ad request the server evaluates, in order:

1. **Is GDPR in scope?** Yes when the ad request carries `gdpr=1`; no when it carries `gdpr=0`;
   and when the parameter is absent, yes when the request carries a `uc` value at all, otherwise
   yes when the IP geolocates to a country on the EEA list. So the gate self-activates for
   European traffic even from tags that never send a `gdpr` flag. Clicks and the tracking hits
   that follow an ad apply the same rule, so they land on the same side of the gate as the ad
   request.
2. **If it is not in scope, or the policy is *Default*** → serve normally.
3. **If it is in scope, check consent**, in this order: an honoured GPC opt-out fails
   immediately; then `uc=1` passes and `uc=0` fails without looking at the string; then a blank
   or undecodable string fails; then a string that is not TCF 2.x fails; then the
   policy-version, CMP-list, vendor-consent and disclosed-vendors checks, in that order.
4. **On a failed check**, apply the restriction: no banner is selected (*Do not serve ads*), or
   the ad serves under the cookie and anonymity rules in
   [What "no consent" actually costs](https://epom.com/ad-server/docs/guides/admin/gdpr-tcf-consent.md#what-no-consent-actually-costs).
   With **Restrict DSP mediation** on, OpenRTB creatives are additionally removed from the
   auction, so a direct creative wins instead.

The EEA list is server-side configuration. It ships with 32 country codes, among them **CH** and
**GB**, which are not EEA members; ask Epom support or your account manager to show or change it.

## Request signals the ad server reads

| Signal | Meaning |
|---|---|
| `gdpr` | `1` = GDPR applies, `0` = does not. Absent → inferred, see step 1 above. Tag attribute: `data-gdpr`. |
| `gdprConsentIab` | The TCF 2.x consent string. Tag attribute: `data-gdpr-consent-iab`; set it and the tag stops asking the CMP. |
| `uc` | Shortcut verdict: `1` = consented, `0` = not. Overrides the consent string. Tag attribute: `data-user-consent`. |
| `cookie-policy` | Per-request cookie switch, `0`–`3` — see [below](#how-do-i-stop-epom-setting-cookies-until-the-visitor-consents). Tag attribute: `data-cookie-policy`. |
| `gpc` / `Sec-GPC` | Global Privacy Control opt-out — `gpc=1` as a request parameter, or `Sec-GPC: 1` as an HTTP header. Read only when **Honour GPC opt-out signal** is on, and only for requests in GDPR scope. |
| `usPrivacy` | The IAB US Privacy string, `1` followed by three of `Y`, `N`, `-` (e.g. `1YNN`). Not part of the GDPR decision; forwarded to DSPs with **Pass privacy signals to DSPs** on. |
| `gpp`, `gppSid` | The IAB GPP string and the comma-separated section ids that apply. Not part of the GDPR decision; forwarded to DSPs with **Pass privacy signals to DSPs** on. |
| `coppa` | `1` for child-directed traffic. Not part of the GDPR decision; forwarded to DSPs with **Pass privacy signals to DSPs** on. |

**How the JavaScript tag gets the string.** The standard Epom tag looks for a `__tcfapi` v2 CMP
on the page (and, when the CMP lives in an ancestor frame, talks to it through the
`__tcfapiLocator` frame by `postMessage`), waits up to 5 seconds, and sends the result as `gdpr`
and `gdprConsentIab`. `data-gdpr-consent-iab` on the tag makes it skip the CMP lookup entirely.
Server-to-server, VAST and header-bidding integrations have to pass the string themselves.

**Header-bidding callers** do not use those names: `/hb/bid` reads the consent string from
`user.consent` or `user.ext.consent`, and the applies-flag from `regs.gdpr` or `regs.ext.gdpr`. A
bare `regs.gdpr = 0` with no consent string is deliberately ignored rather than forwarded — it is
the shape a CMP that timed out leaves behind, and forwarding it would let an EEA visitor through
ahead of the country fallback.

**Only TCF 2.x is accepted.** A string that decodes to any other version is treated as no
consent, silently. There is no TCF 1.1 support: the ad tag reads no `__cmp`, and the
`/rest-api/tcf/1.1/…` endpoints answer **404**.

## How do I stop Epom setting cookies until the visitor consents?

The per-request switch is `cookie-policy` — `data-cookie-policy="1"` on a JavaScript tag,
`&cookie-policy=1` on a VAST, native or API request URL, and `&cookie-policy=$$COOKIE_POLICY$$`
on a VAST or ad URL inside a creative or template so the inner request inherits the outer one's
value. Values: `0` normal; `1` no cookies read or set and no server-side capping; `2` no cookies,
server-side capping still on; `3` no user-ID cookie only, other cookies and capping on. Any value
other than `0` is carried into that ad's impression and click URLs, so the tracking hits stay
cookie-free too. (`uc=0` / `data-user-consent="0"` is different: it marks the visitor as not
consenting, and the network's no-consent **Restriction** decides what that means.)

A format that loads a second ad request of its own (a video slider's inner VAST, an outstream
player) does not see the outer tag's attribute. If cookies still appear with `cookie-policy=1`
set, look for an inner request URL without `$$COOKIE_POLICY$$`.

GDPR overrides a tag's own cookie policy only for in-scope requests that fail the consent check;
every other request keeps whatever the tag asked for.

**The cookie beacons read it too.** `set-cookie.gif` and the multi-cookie beacon
(`/multi-cookie.gif`, `.js`, `.html`) store nothing at all under `cookie-policy=1` or `2` —
neither a cookie nor the `localStorage` copy the tag keeps for Safari. The `cookie-policy` and
`gpc` parameters themselves are never stored as data, so a beacon URL can carry the privacy signal
without it turning into a cookie of its own.

**Cookie sync reads it as well.** A `/multi-cookie.*` call whose policy forbids the user ID
(`1`, `2` or `3`) performs no sync: the Epom user ID is not resolved, so it is neither carried
through the endpoint-domain chain nor handed to the partner URL through `$$UUID$$`, and the
third-party hop is skipped. The beacon still answers — a pixel, or the script without the sync —
and plain data cookies the call was given are still set where the policy allows them.

## Passing consent downstream

Two macros carry the GDPR signal into any banner code, click or impression URL, piggyback or
server-side tracker:

| Macro | Expands to |
|---|---|
| `$$GDPR$$` | The applies flag, `0` or `1`. The IAB spelling `${GDPR}` is accepted and normalised to it. |
| `$$GDPR_CONSENT_IAB$$` | The consent string. `${GDPR_CONSENT_XXXX}` (XXXX = any vendor id, digits only) is accepted and normalised to it. |

`$$GDPR$$` always resolves, to `0` or `1`. `$$GDPR_CONSENT_IAB$$` is **removed** when no string
reached the request, so a partner URL gets no `gdpr_consent=` at all rather than an empty one. See
the [macros reference](https://epom.com/ad-server/docs/reference/macros.md#compliance).

Four more forward the other privacy signals the request carried into banner code and the VAST tags
of demand you call by URL: `$$US_PRIVACY$$`, `$$GPP$$`, `$$GPP_SID$$` and `$$COPPA$$`. Each is
removed when the request did not carry its value.

OpenRTB demand gets the signals in the bid request itself once
[Pass privacy signals to DSPs](https://epom.com/ad-server/docs/guides/admin/gdpr-tcf-consent.md#pass-privacy-signals-to-dsps) is on. While
it is off, the macros above in the partner's endpoint URL or custom parameters on the
[DSP partner](https://epom.com/ad-server/docs/guides/admin/dsp-partners.md) remain the only route. Either way the signals change nothing
about whether an ad is served — that is still the policy and restriction — and they are forwarded
as they came, without being enforced: a US opt-out or a COPPA flag does not by itself anonymise
the bid request.

## Troubleshoot a single request

When delivery drops and you need to know whether GDPR is the reason, run a
[troubleshooting log task](https://epom.com/ad-server/docs/guides/admin/system-ops.md#capture-ad-requests-with-a-troubleshooting-log-task)
(**Admin → Audit & diagnostics → Troubleshooting log tasks**) over the affected traffic. Two lines
answer the question:

- `TCF Consent Info: version=… , cmpId=… , vendorId=… , vendorConsent=… , vendorDisclosed=… ,
  vendorLI=… , checkDisclosedVendors=… , purposes=[…]` — the decoded string as the server read
  it. `vendorConsent=false` means your id is not in the string; `vendorDisclosed=false` with
  `checkDisclosedVendors=true` means the CMP is not emitting the disclosed-vendors segment.
- `No banner can be selected due to failed GDPR policy constraints.` — the request was in scope,
  failed the check, and the restriction is *Do not serve ads*.

The TCF line is written **only when the request carried a consent string at all**. A request with
no string produces no TCF line — so a log that shows the refusal line and nothing else is telling
you the string never arrived, which is a CMP or tag problem, not a settings problem. A request
served under *Do not use any cookies or server-side processing* notes the skipped server-side
capping in the same log.

## Related

- [Configure GDPR / TCF consent enforcement](https://epom.com/ad-server/docs/guides/admin/gdpr-tcf-consent.md)
- [Macros](https://epom.com/ad-server/docs/reference/macros.md#compliance)
- [Configure DSP partners](https://epom.com/ad-server/docs/guides/admin/dsp-partners.md)
- [Server-side trackers](https://epom.com/ad-server/docs/guides/conversions/server-side-trackers.md)
- [Actions log and troubleshooting log tasks](https://epom.com/ad-server/docs/guides/admin/system-ops.md)