npm package: @owntag/consent
Description: A lightweight, customizable cookie consent banner.
Author: Owntag — https://owntag.eu/
Latest version: 0.4.6

# owntag-consent 🍪

A lightweight, customizable cookie consent banner, as currently in use on [owntag.eu](https://owntag.eu).
Feel free to use it as well or as a starting point for your own implementation.

## ✨ Features

- **Lightweight**: No external dependencies, keeping your site fast.
- **Customizable**: Easily customize the look and feel to match your brand.
- **Multiple Consent Categories**: Supports essential, analytics, and marketing categories.
- **Full Consent Control**: Run code only when users have consented to all categories and services.
- **Developer Friendly**: Easy to integrate and use with a comprehensive global API.
- **CSS Isolated**: Uses modern CSS isolation techniques to prevent style conflicts with host websites.

## 🚀 Quick Start

### Installation

```bash
npm install owntag-consent
```

### Usage

Using `owntag-consent` is designed to be as simple as possible. Just import the `ConsentBanner` class and instantiate it. The banner will automatically handle its own CSS injection and will appear for new visitors without any extra effort.

```javascript
import { ConsentBanner } from 'owntag-consent';

new ConsentBanner({
	logo: '/path/to/your/logo.svg',
	title: 'Cookie Settings',
	description: 'We use cookies to improve your experience. Please select your preferences below.',
	// For a full list of configuration options, please refer to the source.
});
```

## 🔌 API

Once instantiated, the consent banner exposes a global API through `window.owntagCMP` that allows you to interact with the consent state programmatically.

### Available Methods

| Method | Description | Returns |
|--------|-------------|---------|
| `show()` | Shows the consent banner | `void` |
| `hide()` | Hides the consent banner | `void` |
| `getConsents()` | Returns an array of consented service IDs | `string[]` |
| `setConsents(consents)` | Sets the consent state for services | `void` |
| `clear()` | Clears all consents and shows the banner | `void` |
| `hasFullConsent()` | Checks if user has consented to all categories and services | `boolean` |
| `runWithFullConsent(callback)` | Executes callback only if user has full consent | `void` |

### Full Consent Methods

The banner provides specialized methods to handle scenarios where you need complete user consent across all categories and services.

#### `hasFullConsent()`

Returns `true` if the user has consented to **all** services across **all** categories (both essential and non-essential).

```javascript
if (window.owntagCMP.hasFullConsent()) {
  console.log('User has given complete consent!');
  // Initialize privacy-sensitive features
}
```

#### `runWithFullConsent(callback)`

Executes the provided callback function **only** if the user has given full consent. If full consent hasn't been achieved yet, the callback is queued and will execute immediately when the user grants full consent (e.g., by clicking "Accept All"). This is useful for conditionally loading third-party scripts, analytics, or other privacy-sensitive code.

```javascript
// This code runs when user has consented to everything
// If called before consent: queued until user clicks "Accept All"
// If called after consent: executes immediately
window.owntagCMP.runWithFullConsent(() => {
  // Load third-party tracking scripts
  loadGoogleAnalytics();
  loadFacebookPixel();
  
  // Initialize advanced features
  initializeChatWidget();
  loadPersonalizationEngine();
});
```

#### What constitutes "Full Consent"?

Full consent means:
- All services in **non-essential** categories have been explicitly consented to
- All services in **essential** categories are consented (automatically granted for required categories)
- The user has either clicked "Accept All" or manually enabled all individual services

#### Usage Patterns

**Queue callbacks early (recommended):**
```javascript
// Call this anywhere in your code - callbacks are automatically queued
window.owntagCMP.runWithFullConsent(() => {
  // Runs immediately if consent exists, or when user grants consent
  initializeAdvancedTracking();
  loadThirdPartyScripts();
});
```

**Check on page load:**
```javascript
document.addEventListener('DOMContentLoaded', () => {
  window.owntagCMP.runWithFullConsent(() => {
    // This runs immediately if user previously gave full consent
    initializeAllFeatures();
  });
});
```

**React to consent changes:**
```javascript
document.addEventListener('consentBanner.accept', (event) => {
  // Check if this accept action resulted in full consent
  if (window.owntagCMP.hasFullConsent()) {
    initializeAdvancedTracking();
  }
});
```

## 🛠️ Development

### Prerequisites

- Node.js (v14 or higher)
- npm or yarn

### Installation

1. Clone the repository:

```bash
git clone https://github.com/your-username/owntag-consent.git
cd owntag-consent
```

2. Install dependencies:

```bash
npm install
```

### Running the Demo

To see the consent banner in action, run the demo:

```bash
npm run demo
```

This will start a local development server. Open the URL provided in your terminal to see the banner in action.

### Running Tests

To run the test suite:

```bash
npm test
```

## 📜 License

This project is licensed under the MIT License.

## 🛠️ Technology Stack

- **Frontend Framework**: Vanilla JavaScript with Vite
- **Styling**: Pure CSS with modern isolation techniques
- **Testing**: Vitest with JSDOM
- **Build Tool**: Vite
- **Package Manager**: npm

## 🔧 CSS Isolation

### Modern CSS Isolation Techniques

The consent banner uses several modern CSS features to ensure complete isolation from host websites:

- **CSS Reset**: Uses `all: initial` for complete style reset
- **CSS Containment**: Leverages `contain: layout style paint` for performance isolation
- **CSS Custom Properties**: Enables easy theming while maintaining isolation
- **Scoped Selectors**: All styles are scoped with specific class names using BEM methodology
- **High Specificity**: Uses `!important` declarations to override any conflicting styles
- **Modern Features**: Includes backdrop-filter, CSS custom properties, and system font stacks

## ⚙️ Configuration

The `ConsentBanner` can be configured by passing an object to the constructor. Below is a list of all available options:

| Option      | Type     | Default          | Description                                                                          |
| :---------- | :------- | :--------------- | :----------------------------------------------------------------------------------- |
| `logo`      | `string` | `'/vite.svg'`    | The path to your logo file.                                                          |
| `title`     | `string` | *(i18n)*         | The main title of the banner. Overrides the i18n value.                              |
| `description`| `string` | *(i18n)*         | The main description text of the banner. Overrides the i18n value.                   |
| `cookieName`| `string` | `'owntag_consent'`| The name of the cookie used to store consent preferences.                              |
| `cookiePath`| `string` | `'/'`            | The path for the consent cookie.                                                     |
| `cookieDomain`| `string` | *(auto-detect)*  | The domain for the consent cookie. Defaults to the eTLD+1 of the current host.       |
| `activeColor`| `string` | `'#4F46E5'`      | The accent color used for buttons and toggles.                                       |
| `footer`    | `string` | `undefined`      | Custom HTML to be rendered in the footer of the banner.                              |
| `imprintUrl`| `string` | `undefined`      | URL for the Imprint link. If provided, the link will be displayed.                   |
| `privacyPolicyUrl`| `string` | `undefined`      | URL for the Privacy Policy link. If provided, the link will be displayed.            |
| `categories`| `array`  | *(see default)*  | An array of consent categories and their associated services.                        |
| `language`  | `string` | `'en'`           | The language for the banner's text. Supported defaults are `'en'` and `'de'`.          |
| `translations`| `object` | `{}`             | A custom translations object to override the defaults. See the i18n section. |

### Internationalization (i18n)

The banner comes with built-in translations for English (`en`) and German (`de`). You can select a language using the `language` option.

```javascript
new ConsentBanner({
  language: 'de' // Use German translations
});
```

To provide your own translations or support a different language, you can pass a `translations` object. The object key should be the language code.

```javascript
new ConsentBanner({
  language: 'fr',
  translations: {
    fr: {
      title: 'Paramètres des cookies',
      description: 'Nous utilisons des cookies pour améliorer votre expérience de navigation.',
      acceptAll: 'Tout accepter',
      denyAll: 'Tout refuser'
    }
  }
});
```

## 🛠️ Development

### Prerequisites

- Node.js (v18 or higher)
- npm

### Installation

1. Clone the repository:

```bash
git clone https://github.com/your-username/owntag-consent.git
cd owntag-consent
```

2. Install dependencies:

```bash
npm install
```

### Running the Demo

To see the consent banner in action, run the demo:

```bash
npm run demo
```

This will start a local development server. Open the URL provided in your terminal to see the banner in action.

### Running Tests

To run the test suite:

```bash
npm test
```

## 📜 License

This project is licensed under the MIT License.