Skip to main content

Tier 2 — Advanced

⚠️ Beta API — può breakare in MINOR. Annuncio su Slack #avacy-dev 1 settimana prima.

Tier 2 è solo via TypeScript import. Non disponibile su window.Avacy.

Quando usare Tier 2

  • Stai scrivendo uno storage provider custom (es. il consenso deve vivere in IndexedDB invece di cookie, oppure in una WebView nativa che espone un bridge custom)
  • Stai integrando il CMP in un sistema che ha bisogno di osservare cambi di state del CMP in modo programmatico (non solo via DOM events Tier 1)

Per il controllo programmatico sul timing del boot (animazioni hero, SPA, config async) usa la Tier 1 window.Avacy.init — non serve toccare l'import TS.

Indice export

ExportTypePurpose
initfunction(Tier 1 — programmatic boot, vedi Lifecycle)
registerStoreProviderfunctionAggiungere un nuovo store.type
CoreEventsobjectEvent emitter (mitt) sui cambi di state — advanced, usa solo se i DOM events Tier 1 non bastano
getConfigfunctionSnapshot read-only della config merged
TypestypeVedi Types reference

serializeRawConsent / parseRawConsent non sono più esposti: RawConsent è opaco per l'integratore (le custom-build interfacciano con IStoreProvider direttamente).


registerStoreProvider

Registra un'implementazione di IStoreProvider mappata a un store.type arbitrario. Da chiamare prima di init.

import { registerStoreProvider } from '@avacy/cmp-web';
import type { IStoreProvider, RawConsent } from '@avacy/cmp-web';

class IndexedDbStore implements IStoreProvider {
async readConsent(): Promise<RawConsent | null> {
// … leggi da IndexedDB
}
async writeConsent(consent: RawConsent): Promise<void> {
// … scrivi su IndexedDB
}
}

registerStoreProvider('indexeddb', IndexedDbStore);

await init({
store: { type: 'indexeddb', consentKey: 'avacy_consent' },
// …
});

Behavior

  • I tipi built-in 'cookie' e 'local-storage' sono sovrascrivibili (last-write-wins, silenzioso) — utile per override avanzati.
  • Se config.store.type non è registrato a init, throw Error: Store provider 'X' not registered.

See also


CoreEvents

⚠️ Advanced — internal observation hook. Pensato per addon TS o tooling che hanno bisogno di osservare ogni mutazione del state interno. Per la logica consumer-facing usa i DOM events Tier 1 (events.md): coprono i casi normali con un contratto stabile e zero accoppiamento al state shape.

CoreEvents espone bucket interni del CMP — può cambiare in MINOR senza preavviso.

Event emitter (basato su mitt) che notifica ogni mutazione del state interno del CMP. Stesso state che vedi via getData(), ma con notifica push.

import { CoreEvents } from '@avacy/cmp-web';

CoreEvents.on('consent', ({ value, prev }) => {
console.log('consent changed', { value, prev });
});

CoreEvents.on('language', ({ value, prev }) => {
console.log('language changed', { value, prev });
});

Available keys

Una key per ogni bucket di state:

type CoreEventsType = {
core: EventPayload<{ ready: boolean }>;
config: EventPayload<ConfigType>;
language: EventPayload<{ words: LanguageLabels; activeLanguage: string }>;
consent: EventPayload<ConsentState>;
customization: EventPayload<{ privacySettings: PrivacySettingsMap; vendorsCount?: number }>;
glossary: EventPayload<GlossaryEntry[]>;
decodedConsent: EventPayload<DecodedConsent | undefined>;
acmAddtlConsent: EventPayload<{ value: string } | undefined>;
};

Per il signal "core è ready", subscribe a 'core' (non 'ready'): la chiave del bucket è core, il ready: boolean vive dentro.

CoreEvents.on('core', ({ value }) => { if (value.ready) { /* ... */ } });

EventPayload<T> = { value: T; prev: T }.

When to use it (vs DOM events)

CasoUsa
Reagire a consenso utente in script user-facingDOM avacy:consent-saved
Logging strutturato di tutte le mutazioni stateCoreEvents
Bridge nativo, RUM tool, GTMDOM events
Scrivere addon TS che reagisce a cambi di lingua/configCoreEvents

💡 Non duplicare la stessa logica su entrambi. Scegli un canale.


getConfig

Snapshot read-only della config merged (utente + remoto + default).

import { getConfig } from '@avacy/cmp-web';
import type { ConfigType } from '@avacy/cmp-web';

const config: Readonly<ConfigType> = getConfig();
console.log(config.cmpVersion, config.policyVersion);

Ritorna null se init non è ancora chiamato.

💡 Per uso "common" (lettura policyVersion, publisherCountryCode, ecc.), preferisci getData() Tier 1 — espone gli stessi campi più stato UI e altro.


Types reference

UserConfigType

interface UserConfigType extends Partial<ConfigType> {}

Tutti i campi opzionali; defaults applicati internamente da ConfigProvider. Vedi ConfigType per la shape completa.

ConfigType

interface ConfigType {
store: { type: StoreType; consentKey: string };
core: { autoLoad?: boolean };
frameworks: FrameworkItem[];
loggers: LoggerType[];
language: LanguageCode;
assetPath: string;
remoteConfigName?: string;
remoteGVLName?: string;
publisherCountryCode: string;
policyVersion: number;
cmpVersion?: string;
consentExpiryDays: number;
vendorsCount?: number;
ui?: UiConfig;
autoLanguage?: boolean;
customLabels?: Partial<Record<LanguageCode, Partial<LanguageLabels>>>;
filters?: ContextFilters;
}

CmpData

type CmpData = ContextData & {
ui: { cpcOpen: boolean };
};

interface ContextData {
core: { ready: boolean };
config: ConfigType;
language: { words: LanguageLabels; activeLanguage: string };
consent: ConsentState;
customization: { privacySettings: PrivacySettingsMap; vendorsCount?: number };
glossary: GlossaryEntry[];
decodedConsent?: DecodedConsent;
acmAddtlConsent?: { value: string };
}

Returnato da getData() Tier 1. Il "ready" del CMP vive sotto data.core.ready (non al top-level): consistente con i bucket di CoreEvents. L'ui bucket per ora contiene solo cpcOpen — è il punto di estensione futuro per altri segnali di stato visivo.

ConsentState

type ConsentState =
| { ready: false }
| { ready: true; valid: false }
| {
ready: true;
valid: true;
type: 'AcceptAll' | 'RejectAll' | 'CloseBanner' | 'Personalized';
timestamp: number;
purposes: { [framework: string]: { [purposeId: number]: boolean } };
vendors: { [framework: string]: { [vendorId: number]: boolean } };
choices: PrivacyChoice[];
};

purposes e vendors sono viste pre-computate dal choices array per ergonomia (hasConsent only). Per hasLegitimateInterest o casi che richiedono il dettaglio completo, usa choices.

PrivacyChoice

interface PrivacyChoice {
framework: 'tcf' | 'gcm' | 'custom' | 'acm';
type: 'purpose' | 'vendor' | 'specialFeature' | 'customPurpose' | 'feature' | 'specialPurpose';
id: number;
hasConsent?: boolean;
hasLegitimateInterest?: boolean;
// … altri campi opzionali (details)
}

hasConsent e hasLegitimateInterest sono entrambi opzionali: i due tipi 'feature' e 'specialPurpose' sono disclosure-only (TCF) e non hanno toggle di consenso, quindi non possono apparire nei PrivacySelector accettati da acceptAll({except}) / rejectAll({except}) / updateConsent ma possono comparire in consent.choices come metadata.

IStoreProvider

interface IStoreProvider {
readConsent(): Promise<RawConsent | null>;
writeConsent(consent: RawConsent): Promise<void>;
}

L'unica interfaccia da implementare per scrivere uno store custom. RawConsent è una string opaca — non c'è bisogno di parserla per la maggior parte dei casi (read → leggi raw dal tuo storage; write → salva raw nel tuo storage).

OnConsentPayload

type ConsentScreen = 'first' | 'second' | 'api';

type OnConsentPayload =
| { type: 'AcceptAll'; screen: ConsentScreen }
| { type: 'RejectAll'; screen: ConsentScreen }
| { type: 'CloseBanner'; screen: ConsentScreen }
| { type: 'Personalized'; screen: ConsentScreen; privacyChoices: PrivacyChoice[] };

screen è un campo audit obbligatorio (drive il consentScreen nel TCString). Per le chiamate via window.Avacy.* il bundle stampa sempre 'api'; banner/CPC components passano 'first'/'second' direttamente al core.

Altri types esportati

  • ConsentPatchesPartial<Record<PrivacySelector, boolean>>, payload di updateConsent
  • IStoreProviderClass — shape statica della class che registerStoreProvider accetta
  • DecodedConsent, FrameworkDecodedConsent, FrameworkRawConsent, FrameworkRawConsentMap
  • PrivacySetting
  • OnConsentAcceptAllPayload, OnConsentRejectAllPayload, OnConsentCloseBannerPayload, OnConsentPersonalizedPayload
  • UiConfig, StoreType, LoggerType, FrameworkType, FrameworkItem, FrameworkConfigItem
  • CoreEventsType, EventPayload<T>
  • ConsentState, ProviderInstanceMap, ProviderName, GlossaryEntry