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

# Consent Plugin

> GDPR-compliant consent management for event tracking

## Overview

The ConsentPlugin gates event tracking behind user consent, helping you comply with GDPR, CCPA, and other privacy regulations.

## Installation

```typescript theme={null}
import { Refine, ConsentPlugin } from '@refine-ai/sdk';

const refine = new Refine({
  apiKey: process.env.REFINE_API_KEY,
  organizationId: 'org_abc123',
  catalogId: 'cat_xyz789',
  privacy: {
    requireConsent: true
  }
});

const consentPlugin = new ConsentPlugin({
  required: true,
  onConsentRequired: () => {
    showConsentBanner();
  }
});

refine.use(consentPlugin);
```

## Options

<ParamField body="required" type="boolean" default="true">
  When true, all event tracking is paused until consent is granted.
</ParamField>

<ParamField body="onConsentRequired" type="() => void">
  Callback fired when an event is attempted but consent hasn't been granted. Use this to show your consent UI.
</ParamField>

## Methods

### grant()

Grant consent and start tracking:

```typescript theme={null}
consentPlugin.grant();
```

When called:

* Event tracking resumes immediately
* Queued events are sent
* Consent state is persisted in localStorage

### deny()

Deny consent and disable tracking:

```typescript theme={null}
consentPlugin.deny();
```

When called:

* Event tracking is disabled
* Queued events are discarded
* Consent state is persisted

### getStatus()

Check current consent status:

```typescript theme={null}
const status = consentPlugin.getStatus();
console.log(status); // 'granted' | 'denied' | 'pending'
```

### reset()

Clear consent state (user can be asked again):

```typescript theme={null}
consentPlugin.reset();
```

## Complete Implementation

```typescript theme={null}
import { Refine, ConsentPlugin } from '@refine-ai/sdk';

// Initialize SDK
const refine = new Refine({
  apiKey: process.env.REFINE_API_KEY,
  organizationId: 'org_abc123',
  catalogId: 'cat_xyz789',
  privacy: {
    requireConsent: true,
    anonymizeIp: true
  }
});

// Initialize consent plugin
const consentPlugin = new ConsentPlugin({
  required: true,
  onConsentRequired: () => {
    // Show banner only if not already decided
    if (consentPlugin.getStatus() === 'pending') {
      document.getElementById('consent-banner')?.classList.remove('hidden');
    }
  }
});

refine.use(consentPlugin);

// UI Event Handlers
document.getElementById('accept-all')?.addEventListener('click', () => {
  consentPlugin.grant();
  hideConsentBanner();
});

document.getElementById('reject-all')?.addEventListener('click', () => {
  consentPlugin.deny();
  hideConsentBanner();
});

document.getElementById('manage-preferences')?.addEventListener('click', () => {
  showPreferencesModal();
});

function hideConsentBanner() {
  document.getElementById('consent-banner')?.classList.add('hidden');
}

function showPreferencesModal() {
  // Your preferences UI
}
```

## Consent Banner HTML

```html theme={null}
<div id="consent-banner" class="hidden">
  <div class="consent-content">
    <h3>We value your privacy</h3>
    <p>
      We use cookies and similar technologies to personalize your experience 
      and analyze site usage. By clicking "Accept All", you consent to our 
      use of cookies.
    </p>
    <div class="consent-buttons">
      <button id="reject-all" class="btn-secondary">Reject All</button>
      <button id="manage-preferences" class="btn-secondary">Manage Preferences</button>
      <button id="accept-all" class="btn-primary">Accept All</button>
    </div>
  </div>
</div>
```

## Behavior Before Consent

When consent is required but not yet granted:

| Action                 | Behavior                                    |
| ---------------------- | ------------------------------------------- |
| Search/Recommendations | Works normally (required for functionality) |
| Event tracking         | Events are queued but not sent              |
| Identity               | Visitor ID generated but not persisted      |

After consent is granted, queued events are sent and identity is persisted.

## Integration with Cookie Consent Tools

### OneTrust Integration

```typescript theme={null}
// Listen for OneTrust consent changes
window.OptanonWrapper = function() {
  const activeGroups = window.OnetrustActiveGroups || '';
  
  if (activeGroups.includes('C0002')) {
    // Performance cookies accepted
    consentPlugin.grant();
  } else {
    consentPlugin.deny();
  }
};
```

### Cookiebot Integration

```typescript theme={null}
window.addEventListener('CookiebotOnAccept', () => {
  if (Cookiebot.consent.statistics) {
    consentPlugin.grant();
  }
});

window.addEventListener('CookiebotOnDecline', () => {
  consentPlugin.deny();
});
```

### Custom CMP Integration

```typescript theme={null}
// Generic CMP integration pattern
function handleConsentChange(consent: { analytics: boolean }) {
  if (consent.analytics) {
    consentPlugin.grant();
  } else {
    consentPlugin.deny();
  }
}

// Register with your CMP
yourCMP.onConsentChange(handleConsentChange);
```

## Persistence

Consent state is stored in localStorage under `refine_consent`:

```javascript theme={null}
// Stored value
localStorage.getItem('refine_consent')
// Returns: "granted" | "denied" | null
```

The consent persists across sessions until:

* User clears browser data
* You call `consentPlugin.reset()`
* User explicitly changes their preference

## Testing Consent Flow

```typescript theme={null}
import { Refine, ConsentPlugin, DebugPlugin } from '@refine-ai/sdk';

const refine = new Refine({
  apiKey: process.env.REFINE_API_KEY,
  organizationId: 'org_abc123',
  catalogId: 'cat_xyz789'
});

// Debug plugin to see what's happening
refine.use(new DebugPlugin({ logEvents: true }));

const consentPlugin = new ConsentPlugin({
  required: true,
  onConsentRequired: () => {
    console.log('Consent required - showing banner');
  }
});

refine.use(consentPlugin);

// Test the flow
console.log('Status:', consentPlugin.getStatus()); // 'pending'

// Try to track something
refine.events.trackSearch('test', [], { surface: 'test', totalResults: 0 });
// Console: "Consent required - showing banner"
// Event is queued but not sent

// Grant consent
consentPlugin.grant();
console.log('Status:', consentPlugin.getStatus()); // 'granted'
// Queued events are now sent

// Test denial
consentPlugin.reset();
consentPlugin.deny();
console.log('Status:', consentPlugin.getStatus()); // 'denied'
// No events will be tracked
```

## Privacy Configuration

Combine with SDK privacy settings:

```typescript theme={null}
const refine = new Refine({
  apiKey: process.env.REFINE_API_KEY,
  organizationId: 'org_abc123',
  catalogId: 'cat_xyz789',
  privacy: {
    respectDoNotTrack: true,  // Honor browser DNT
    anonymizeIp: true,        // Anonymize IPs
    requireConsent: true      // Wait for consent
  }
});
```

## Next Steps

<CardGroup cols={2}>
  <Card title="Debug Plugin" icon="bug" href="/sdk/plugins/debug-plugin">
    Development tools
  </Card>

  <Card title="Auto Track Plugin" icon="wand-magic-sparkles" href="/sdk/plugins/auto-track-plugin">
    Automatic tracking
  </Card>
</CardGroup>
