# JavaScript SDK

The `@probo/cookie-banner` SDK is a lightweight, dependency-free JavaScript library built on Web Components. It renders the consent UI, manages visitor consent state, communicates with the the platform API, and activates third-party resources based on consent.

Există trei modalități de a utiliza SDK-ul, în funcție de nevoile dvs.:

## Script Tag (No Bundler)

The simplest option. Add a single `<script>` tag to your HTML — no build tools required:

```html
<script
  src="https://unpkg.com/@probo/cookie-banner/dist/cookie-banner.iife.js"
  data-banner-id="YOUR_BANNER_ID"
  data-base-url="https://your-probo-instance.com/api/cookie-banner/v1/"
  data-position="bottom-left"
></script>

<!-- Required: reopen control in the header or footer -->
<probo-settings-link>Cookie settings</probo-settings-link>
```

This automatically renders a fully styled consent dialog. Place `<probo-settings-link>` in your header or footer so visitors can reopen preferences — see [Settings link](#settings-link).

| Attribute            | Required | Description                                                                                                                                          |
| -------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| `data-banner-id`     | Yes      | Your banner ID from the the platform console                                                                                                                |
| `data-base-url`      | Yes      | The the platform cookie banner API base URL                                                                                                                 |
| `data-position`      | No       | Banner card position: `bottom-left` (default), `bottom-right`, `bottom-center`, `top-left`, `top-right`, or `top-center`                              |
| `data-lang`          | No       | Force a specific language (e.g. `"fr"`). When omitted, the SDK auto-detects from the page or browser. See [Language Detection](#language-detection). |

## Themed Banner (ES Module)

Pentru aplicațiile grupate (React, Vue, Svelte, Next.js etc.), importați banner-ul tematic ca modul ES:

```bash
npm install @probo/cookie-banner
```

Înregistrați componenta și plasați-o în HTML sau șablon:

```js

registerCookieBanner();
```

```html
<probo-cookie-banner
  banner-id="YOUR_BANNER_ID"
  base-url="https://your-probo-instance.com/api/cookie-banner/v1/"
  position="bottom-left"
></probo-cookie-banner>

<!-- Required: reopen control in the header or footer -->
<probo-settings-link>Cookie settings</probo-settings-link>
```

| Attribute       | Required | Description                                                                                                                                          |
| --------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| `banner-id`     | Yes      | Your banner ID from the the platform console                                                                                                                |
| `base-url`      | Yes      | The the platform cookie banner API base URL                                                                                                                 |
| `position`      | No       | Banner card position: `bottom-left` (default), `bottom-right`, `bottom-center`, `top-left`, `top-right`, or `top-center`                              |
| `lang`          | No       | Force a specific language (e.g. `"fr"`). When omitted, the SDK auto-detects from the page or browser. See [Language Detection](#language-detection). |

Since this is a Web Component, it works in any framework. In React, JSX treats it as a custom element. In Vue or Svelte, use it directly in your template. See the [React Integration](/docs/product/cookie-banner/react) guide for a complete walkthrough with a `useConsent` hook, Next.js setup, and TypeScript declarations.

Consultați [Theming](/docs/product/cookie-banner/theming) pentru a afla cum să personalizați culorile, fonturile și stilul.

Pentru accesul programatic la starea de consimțământ din orice modul (nu doar DOM), consultați Managerul de consimțământAPI(/docs/product/cookie-banner/consent-manager).

## Headless Components (Full Control)

Pentru un control complet asupra UI-ului de consimțământ, utilizați componentele fără cap. Acestea sunt blocuri de construcție a componentelor Web ne-stilizate pe care le compuneți și le stilizați singuri:

```js

registerHeadlessComponents();
```

Then build your own layout:

```html
<probo-cookie-banner-root banner-id="YOUR_BANNER_ID" base-url="BASE_URL">
  <probo-banner>
    <div class="my-banner">
      <p data-text="banner_description">We use cookies to improve your experience.</p>
      <!-- Opt-in / opt-out primary actions -->
      <probo-accept-button>
        <button>Accept all</button>
      </probo-accept-button>
      <probo-reject-button>
        <button>Reject all</button>
      </probo-reject-button>
      <probo-customize-button>
        <button>Customize</button>
      </probo-customize-button>
      <!-- Notice presentation (APPI, Mexico, unregulated): single dismiss -->
      <probo-acknowledge-button>
        <button>Got it</button>
      </probo-acknowledge-button>
    </div>
  </probo-banner>

  <probo-preference-panel>
    <div class="my-preferences">
      <probo-category-list>
        <template>
          <div class="category">
            <span data-slot="name"></span>
            <span data-slot="description"></span>
            <probo-category-toggle>
              <input type="checkbox" />
            </probo-category-toggle>
          </div>
          <probo-cookie-list>
            <template>
              <div class="cookie">
                <span data-slot="name"></span>
                <span data-slot="type"></span>
                <span data-slot="duration"></span>
              </div>
            </template>
          </probo-cookie-list>
        </template>
      </probo-category-list>
      <probo-save-button>
        <button>Save preferences</button>
      </probo-save-button>
    </div>
  </probo-preference-panel>

  <!-- CCPA only: shown when state is privacy_choices -->
  <probo-privacy-choices>
    <div class="my-privacy-choices">
      <probo-reject-button>
        <button>Do Not Sell or Share My Personal Information</button>
      </probo-reject-button>
    </div>
  </probo-privacy-choices>
</probo-cookie-banner-root>

<!-- Required outside the root (header or footer) -->
<probo-settings-link>Cookie settings</probo-settings-link>
```

Use [`resolveLayout`](#layout-api) / [`resolveBannerText`](#layout-api) to show the right buttons and copy for the active presentation (`OPT_IN`, `OPT_OUT`, or `NOTICE`).

### Component Reference

| Component                    | Description                                                                                                                                                                                                    |
| ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `<probo-cookie-banner-root>` | Root element. Requires `banner-id` and `base-url`. Optional `lang` attribute to force a language. Manages client lifecycle and state. |
| `<probo-banner>`             | Container for the first-layer banner card. Visibility follows `layout.initial_state` (e.g. closed under CCPA — see [Settings link](#settings-link)).                                                           |
| `<probo-accept-button>`      | Wraps a button that records `ACCEPT_ALL` consent.                                                                                                                                                              |
| `<probo-reject-button>`      | Wraps a button that records `REJECT_ALL` consent (opt-out / Do Not Sell).                                                                                                                                      |
| `<probo-customize-button>`   | Wraps a button that opens the preference panel.                                                                                                                                                                |
| `<probo-acknowledge-button>` | Wraps a button that records `ACKNOWLEDGE` for **NOTICE** presentations (informational dismiss). Do not reuse accept-all for this.                                                                              |
| `<probo-preference-panel>`   | Container for per-category consent toggles.                                                                                                                                                                    |
| `<probo-privacy-choices>`    | CCPA Privacy Choices surface (sale/sharing opt-out + sensitive PI rights statement). Shown when state is `privacy_choices`.                                                                                    |
| `<probo-category-list>`      | Renders a `<template>` once per cookie category. Fills `data-slot="name"` and `data-slot="description"`.                                                                                                       |
| `<probo-category-toggle>`    | Binds the checkbox inside it to the category's consent state.                                                                                                                                                  |
| `<probo-cookie-list>`        | Renders a `<template>` once per cookie in the category. Fills `data-slot="name"`, `data-slot="type"`, and `data-slot="duration"`.                                                                               |
| `<probo-save-button>`        | Wraps a button that saves the current preference draft.                                                                                                                                                        |
| `<probo-settings-link>`      | **Required** header/footer reopen control. Click target comes from `layout.reopen_state`. See [Settings link](#settings-link).                                                                                 |

### Layout API

From 0.12 onward the API returns a structured `layout` on the banner config. Headless integrators should read it instead of branching on `regulation` or `consent_mode`:

```js
  resolveLayout,
  resolveBannerText,
} from "@probo/cookie-banner"; // or "@probo/cookie-banner/headless"

document.addEventListener("probo-ready", (e) => {
  const { config } = e.detail;
  const layout = resolveLayout(config);
  // layout.presentation: "OPT_IN" | "OPT_OUT" | "NOTICE"
  // layout.initial_state / layout.reopen_state: "banner" | "panel" | "privacy_choices" | "hidden"
  // layout.buttons: which actions to show
  // layout.settings_link: "default" | "ccpa_privacy_choices"

  const copy = resolveBannerText(config);
  // copy.title, copy.description, copy.primaryButton, copy.secondaryButton?
});
```

If `layout` is missing, the SDK logs an error and falls back to strict opt-in — that means a self-hosted the platform backend older than **probod v0.246.0**. Update probod when you see that warning.

### Settings link

`<probo-settings-link>` is the sole reopen control. Place it in your site header or footer for every embed (script tag, themed, or headless). If it is missing, the SDK emits a soft `probo-validation` warning — without it visitors cannot reopen preferences.

```html
<style>
  /* Style the host — typography still applies after CCPA replaces the children */
  probo-settings-link {
    font-size: 14px;
    color: #334155;
    text-decoration: underline;
  }
</style>

<footer>
  <probo-settings-link>Cookie settings</probo-settings-link>
</footer>
```

Behavior by presentation / regulation (driven by `layout`):

| Presentation | Typical regulations | Label shown | Banner on first visit | Click opens |
| ------------ | ------------------- | ----------- | --------------------- | ----------- |
| **OPT_OUT** (CCPA) | CCPA / CPRA | Always replaced with the statutory **“Your Privacy Choices”** text and [official opt-out icon](https://www.law.cornell.edu/regulations/california/11-CCR-7015) (English; not translated) | Closed by default | **Privacy Choices** panel (`privacy_choices`) |
| **OPT_OUT** (other) | PIPEDA, LGPD | Your children (e.g. “Cookie settings”), or a localized fallback if empty | Closed by default | Compact opt-out banner |
| **OPT_IN** | GDPR, UK GDPR, FADP, … | Your children, or a localized fallback if empty | Open until the visitor chooses | Preference panel |
| **NOTICE** | APPI, LFPDPPP, unregulated countries | Your children, or a localized fallback if empty | Open (informational dismiss) | Notice banner again |

Atunci când a fost aplicat un semnal de opțiune de renunțare la controlul global al confidențialității (GPC), link-ul de setări poate afișa un mic semn **GPC onorat** lângă etichetă.

The themed embed mounts `<probo-privacy-choices>` for opt-out layouts, but **reopen to that surface is CCPA-only** (`layout.reopen_state = privacy_choices`). Other opt-out regimes reopen the compact banner. Headless integrators should include `<probo-privacy-choices>` when supporting CCPA. The settings link finds the banner root automatically for all three integration methods.

Style `probo-settings-link` itself for font size and color — not inner children. Under CCPA the SDK replaces the children, but host styles still apply. The icon keeps its statutory blue/white colors and scales with `1em`.

## Language Detection

SDK rezolvă automat limba vizitatorului folosind următoarea prioritate:

1. **Explicit attribute** — The `lang` attribute on the component (or `data-lang` on the script tag)
2. **Page language** — The `lang` attribute on the `<html>` element, using the base language subtag (e.g. `fr` from `fr-FR`)
3. **Browser language** — The browser's `navigator.language`, using the base subtag
4. **Default language** — The banner's default language configured in the console (defaults to `en`)

Limba rezolvată este trimisă laAPIatunci când se colectează configurația bannerului.APIreturnează toate textul UI, numele categoriilor și descrierile în limba rezolvată. Dacă nu există nicio traducere pentru acea limbă,APIrevine la limba implicită a bannerului.

### Built-in Languages

Noile bannere includ traduceri pentru aceste limbi:

| Code | Language     | Code | Language   |
| ---- | ------------ | ---- | ---------- |
| `en` | English      | `nl` | Dutch      |
| `de` | German       | `pl` | Polish     |
| `es` | Spanish      | `pt` | Portuguese |
| `fr` | French       | `tr` | Turkish    |
| `id` | Indonesian   | `uk` | Ukrainian  |
| `it` | Italian      | `zh` | Chinese    |
| `ja` | Japanese     |      |            |
| `ko` | Korean       |      |            |

Puteți personaliza aceste traduceri și puteți adăuga noi limbi din consola de platformă.

- Titlul și descrierea bannerului (inclusiv opțiunea de renunțare și variantele de notificare) - Etichete de buton (acceptați toate, respingeți toate, personalizați, salvați, respingeți / recunoașteți) - Titlul și descrierea panourilor de preferințe - Etichete de detaliu ale cookie-urilor (tip, descriere, durată) - Etichete de accesibilitate ARIA - Politica de confidențialitate / politica de cookie-uri - Text de legătură a conținutului (vizuit atunci când resursele sunt blocate) - Etichete de durată (ani, luni, zile, persistente etc.)

### Forcing a Language

Pentru a renunța la auto-detectare, setați limba în mod explicit:

**Script tag:**

```html
<script
  src="https://unpkg.com/@probo/cookie-banner/dist/cookie-banner.iife.js"
  data-banner-id="YOUR_BANNER_ID"
  data-base-url="https://your-probo-instance.com/api/cookie-banner/v1/"
  data-lang="de"
></script>
```

**Themed banner:**

```html
<probo-cookie-banner
  banner-id="YOUR_BANNER_ID"
  base-url="https://your-probo-instance.com/api/cookie-banner/v1/"
  lang="de"
></probo-cookie-banner>
```

**Headless components:**

```html
<probo-cookie-banner-root
  banner-id="YOUR_BANNER_ID"
  base-url="https://your-probo-instance.com/api/cookie-banner/v1/"
  lang="de"
>
  <!-- ... -->
</probo-cookie-banner-root>
```

### Matching the Page Language

In most cases, you don't need to set a language explicitly. If your page has a `lang` attribute on the `<html>` element, the SDK picks it up automatically:

```html
<html lang="fr"></html>
```

This is the recommended approach for multilingual sites that already set the `lang` attribute as part of their i18n setup.

## Events

SDK emite evenimente personalizate care bulează prin DOM. Ascultați elementul rădăcină sau orice strămoș:

| Event                 | Detail                                          | Description                                                                                                                                                                                                                          |
| --------------------- | ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `probo-ready`         | `{ config, gpcApplied, regulation }`            | Fired when the banner configuration has been loaded. `config` includes `language`, `default_language`, `texts`, `layout`, `consent_mode`, `regulation`, `cookie_policy_url`, and categories. `gpcApplied` is `true` if a GPC opt-out was applied. |
| `probo-state`         | `{ state, prev }`                               | Fired when the banner UI state changes. States: `loading`, `banner`, `panel`, `privacy_choices`, `hidden`.                                                                                                                            |
| `probo-consent`       | `{ action, consent_data }`                      | Fired after consent is recorded. Actions: `ACCEPT_ALL`, `REJECT_ALL`, `CUSTOMIZE`, `GPC`, `ACKNOWLEDGE`.                                                                                                                              |
| `probo-validation`    | `{ missing }`                                   | Soft composition warning (e.g. missing `<probo-settings-link>`). Does not block load.                                                                                                                                                |

```js
document.addEventListener("probo-consent", (e) => {
  console.log("Consent action:", e.detail.action);
});
```

## Cum este stocat consimțământul

- **Client-side:** A `probo_consent` cookie stores the visitor's consent state. The cookie's `max-age` is set to the consent expiry configured on the banner (in days). It uses `SameSite=Lax`.
- **Server-side:** Every consent action is recorded via the the platform API with the banner version, visitor ID, action type, anonymized IP address, and user agent. IP addresses are anonymized before storage (IPv4 last octet zeroed, IPv6 masked to /48) — the full IP is never persisted. See [Audit Trail](/docs/product/cookie-banner/overview#audit-trail) for the complete list of stored fields.
- **Visitor identity:** The SDK generates a random visitor ID and stores it in `localStorage`. This ID is used to look up existing consent when the visitor returns.
- **Offline resilience:** If the API is unreachable when consent is recorded, the request is queued in `localStorage` and retried automatically on the next page load.

## Integrations

SDK-urile sunt dotate cu integrări încorporate care sincronizează automat statutul de consimțământ cu serviciile terțelor părți. Integrările sunt activate în mod implicit – acestea sunt activate numai atunci când sunt configurate steagurile corespunzătoare pe categoriile de cookie-uri din consola platformei.

### Google Consent Mode

The SDK pushes [Google Consent Mode v2](https://developers.google.com/tag-platform/security/guides/consent) signals to `gtag()` or `dataLayer`, keeping Google tags in sync with visitor consent.

How it works:

1. On load, the SDK sends a `consent("default", ...)` call that sets all configured consent types to `"denied"`.
2. When the visitor makes a choice, the SDK sends a `consent("update", ...)` call with `"granted"` or `"denied"` for each consent type based on the visitor's per-category choices.

Configuration is driven by the **GCM consent types** field on each cookie category in the the platform console. Map categories to Google consent types like `analytics_storage`, `ad_storage`, `ad_user_data`, or `ad_personalization`. Categories without GCM consent types configured are ignored.

The integration detects `window.gtag` or `window.dataLayer` automatically. If neither is present, it does nothing.

### PostHog

PostHog nu este sincronizat automat de către SDK – dar Managerul de consimțământAPI(/docs/product/cookie-banner/consent-manager) vă oferă tot ce aveți nevoie pentru a-l sincroniza în câteva rânduri și pentru a rămâne în conformitate cuGDPR, CCPA și celelalte reglementări cu care se ocupă bannerul.

See the dedicated guides:

- [How to set up PostHog: GDPR, CCPA, and global privacy laws](/blog/2026-05-27-posthog-cookie-banner-gdpr-ccpa-compliance) — cookieless-only vs consent-aware setup, with a minimum working example for each.
- [PostHog feature flags behind a cookie banner](/blog/2026-08-05-posthog-feature-flags-cookie-consent) — evaluate flags only after analytics consent and `identify()`, and why Track 2 should always use `cookieless_mode: "on_reject"`.

A complete working integration (including a consent-gated feature flag demo) lives in the [`cookie-banner-react`](/docs) example.
