Skip to main content

Overview

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

Installation

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

required
boolean
default:"true"
When true, all event tracking is paused until consent is granted.
Callback fired when an event is attempted but consent hasn’t been granted. Use this to show your consent UI.

Methods

grant()

Grant consent and start tracking:
consentPlugin.grant();
When called:
  • Event tracking resumes immediately
  • Queued events are sent
  • Consent state is persisted in localStorage

deny()

Deny consent and disable tracking:
consentPlugin.deny();
When called:
  • Event tracking is disabled
  • Queued events are discarded
  • Consent state is persisted

getStatus()

Check current consent status:
const status = consentPlugin.getStatus();
console.log(status); // 'granted' | 'denied' | 'pending'

reset()

Clear consent state (user can be asked again):
consentPlugin.reset();

Complete Implementation

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
}
<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>
When consent is required but not yet granted:
ActionBehavior
Search/RecommendationsWorks normally (required for functionality)
Event trackingEvents are queued but not sent
IdentityVisitor ID generated but not persisted
After consent is granted, queued events are sent and identity is persisted.

OneTrust Integration

// 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

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

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

Custom CMP Integration

// 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:
// 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
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:
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