PRIV ProtocolPRIV Docs
Compliance SDK

Consent Manager

API reference for the ConsentManager class - store and manage GDPR consent preferences.

Consent Manager

The ConsentManager handles all consent state operations including storage, API sync, and change notifications.


Initialization

import { ConsentManager, createConsentManager } from '@priv/compliance-sdk';

// Using class
const consent = new ConsentManager({
  siteId: 'your-site-id',
  api: {
    endpoint: 'https://api.priv.io/v1',
    apiKey: 'your-api-key',
  },
});

// Using factory function
const consent = createConsentManager({
  siteId: 'your-site-id',
});

Configuration

ConsentManagerConfig

interface ConsentManagerConfig {
  /** Unique site identifier (required) */
  siteId: string;

  /** API configuration for server sync */
  api?: {
    endpoint: string;
    apiKey: string;
    timeout?: number; // Default: 5000ms
  };

  /** Storage type for preferences */
  storage?: 'localStorage' | 'sessionStorage'; // Default: 'localStorage'

  /** Storage key name */
  storageKey?: string; // Default: 'priv_consent'

  /** Consent version for invalidation */
  version?: string; // Default: '1.0'

  /** Default category states */
  defaultCategories?: Partial<ConsentState>;

  /** Callback on consent change */
  onConsentChange?: (preferences: ConsentPreferences) => void;
}

Methods

getConsent()

Get the current consent preferences.

const preferences = consent.getConsent();

if (preferences) {
  console.log('Categories:', preferences.categories);
  console.log('Timestamp:', preferences.timestamp);
  console.log('Version:', preferences.version);
  console.log('User Hash:', preferences.userIdHash);
}

Returns: ConsentPreferences | null

interface ConsentPreferences {
  categories: {
    necessary: boolean;    // Always true
    analytics: boolean;
    marketing: boolean;
    personalization: boolean;
    social: boolean;
  };
  timestamp: number;       // Unix timestamp
  version: string;         // Consent version
  userIdHash: string;      // SHA-256 hash of user fingerprint
}

setConsent(categories)

Set consent for specific categories.

// Set multiple categories
await consent.setConsent({
  analytics: true,
  marketing: false,
  personalization: true,
});

// Only update one category
await consent.setConsent({
  analytics: true,
});

Parameters:

NameTypeDescription
categoriesPartial<ConsentState>Categories to update

Returns: Promise<void>

Note: The necessary category is always set to true regardless of input.


hasConsent()

Check if the user has made a consent decision.

if (!consent.hasConsent()) {
  // Show consent banner
  showConsentBanner();
}

Returns: boolean


hasCategory(category)

Check if a specific category is consented.

// Check before loading analytics
if (consent.hasCategory('analytics')) {
  loadGoogleAnalytics();
}

// Check before loading marketing pixels
if (consent.hasCategory('marketing')) {
  loadFacebookPixel();
}

Parameters:

NameTypeDescription
categoryConsentCategoryCategory to check

Returns: boolean

Available Categories:

type ConsentCategory =
  | 'necessary'
  | 'analytics'
  | 'marketing'
  | 'personalization'
  | 'social';

acceptAll()

Accept all consent categories.

// User clicks "Accept All"
document.getElementById('accept-all')?.addEventListener('click', async () => {
  await consent.acceptAll();
  hideBanner();
});

Returns: Promise<void>

Sets all categories to true:

  • necessary: true
  • analytics: true
  • marketing: true
  • personalization: true
  • social: true

rejectAll()

Reject all non-necessary categories.

// User clicks "Reject All"
document.getElementById('reject-all')?.addEventListener('click', async () => {
  await consent.rejectAll();
  hideBanner();
});

Returns: Promise<void>

Sets categories to:

  • necessary: true (cannot be disabled)
  • analytics: false
  • marketing: false
  • personalization: false
  • social: false

revokeConsent()

Completely revoke consent and clear stored preferences.

// User wants to reset their preferences
document.getElementById('revoke-consent')?.addEventListener('click', async () => {
  await consent.revokeConsent();
  showConsentBanner();
});

Returns: Promise<void>

This method:

  1. Removes stored preferences from localStorage
  2. Notifies the API about revocation
  3. Triggers change listeners with default (rejected) state

getUserIdHash()

Get the privacy-preserving user identifier hash.

const userHash = await consent.getUserIdHash();
console.log('User Hash:', userHash);
// "a7b8c9d0e1f2a3b4c5d6e7f8..."

Returns: Promise<string>

The hash is generated from:

  • Site ID
  • User agent
  • Screen dimensions
  • Timezone
  • A persistent salt (stored locally)

This provides consistent identification without storing PII.


onConsentChange(callback)

Subscribe to consent changes.

// Subscribe
const unsubscribe = consent.onConsentChange((preferences) => {
  console.log('Consent changed:', preferences.categories);

  if (preferences.categories.analytics) {
    loadAnalytics();
  } else {
    unloadAnalytics();
  }
});

// Later, unsubscribe
unsubscribe();

Parameters:

NameTypeDescription
callback(preferences: ConsentPreferences) => voidChange handler

Returns: () => void - Unsubscribe function


Integration Examples

With Google Analytics

const consent = new ConsentManager({ siteId: 'my-site' });

consent.onConsentChange((prefs) => {
  if (prefs.categories.analytics) {
    // Load GA4
    window.gtag?.('consent', 'update', {
      analytics_storage: 'granted',
    });
  } else {
    // Revoke GA4
    window.gtag?.('consent', 'update', {
      analytics_storage: 'denied',
    });
  }
});

With Google Tag Manager

consent.onConsentChange((prefs) => {
  window.dataLayer?.push({
    event: 'consent_update',
    consent: {
      analytics: prefs.categories.analytics,
      marketing: prefs.categories.marketing,
      personalization: prefs.categories.personalization,
    },
  });
});

With Third-Party Scripts

consent.onConsentChange((prefs) => {
  // Analytics
  if (prefs.categories.analytics) {
    loadScript('https://www.googletagmanager.com/gtag/js?id=GA_ID');
    loadScript('https://plausible.io/js/script.js');
  }

  // Marketing
  if (prefs.categories.marketing) {
    loadScript('https://connect.facebook.net/en_US/fbevents.js');
    loadScript('https://www.googleadservices.com/pagead/conversion.js');
  }

  // Social
  if (prefs.categories.social) {
    loadScript('https://platform.twitter.com/widgets.js');
  }
});

Type Definitions

/** Consent categories */
type ConsentCategory =
  | 'necessary'
  | 'analytics'
  | 'marketing'
  | 'personalization'
  | 'social';

/** Consent state for each category */
type ConsentState = Record<ConsentCategory, boolean>;

/** User consent preferences */
interface ConsentPreferences {
  readonly categories: ConsentState;
  readonly timestamp: number;
  readonly version: string;
  readonly userIdHash: string;
}

/** Consent manager interface */
interface IConsentManager {
  getConsent(): ConsentPreferences | null;
  setConsent(categories: Partial<ConsentState>): Promise<void>;
  hasConsent(): boolean;
  hasCategory(category: ConsentCategory): boolean;
  acceptAll(): Promise<void>;
  rejectAll(): Promise<void>;
  revokeConsent(): Promise<void>;
  getUserIdHash(): Promise<string>;
  onConsentChange(callback: (preferences: ConsentPreferences) => void): () => void;
}

Next Steps