Tier 2 — Advanced
⚠️ Beta API — può breakare in MINOR. Annuncio su Slack
#avacy-dev1 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
| Export | Type | Purpose |
|---|---|---|
init | function | (Tier 1 — programmatic boot, vedi Lifecycle) |
registerStoreProvider | function | Aggiungere un nuovo store.type |
CoreEvents | object | Event emitter (mitt) sui cambi di state — advanced, usa solo se i DOM events Tier 1 non bastano |
getConfig | function | Snapshot read-only della config merged |
| Types | type | Vedi Types reference |
serializeRawConsent/parseRawConsentnon sono più esposti:RawConsentè opaco per l'integratore (le custom-build interfacciano conIStoreProviderdirettamente).
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.typenon è registrato ainit, throwError: Store provider 'X' not registered.
See also
IStoreProvider— interfaccia da implementare
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, ilready: booleanvive dentro.CoreEvents.on('core', ({ value }) => { if (value.ready) { /* ... */ } });
EventPayload<T> = { value: T; prev: T }.
When to use it (vs DOM events)
| Caso | Usa |
|---|---|
| Reagire a consenso utente in script user-facing | DOM avacy:consent-saved |
| Logging strutturato di tutte le mutazioni state | CoreEvents |
| Bridge nativo, RUM tool, GTM | DOM events |
| Scrivere addon TS che reagisce a cambi di lingua/config | CoreEvents |
💡 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.), preferiscigetData()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
ConsentPatches—Partial<Record<PrivacySelector, boolean>>, payload diupdateConsentIStoreProviderClass— shape statica della class cheregisterStoreProvideraccettaDecodedConsent,FrameworkDecodedConsent,FrameworkRawConsent,FrameworkRawConsentMapPrivacySettingOnConsentAcceptAllPayload,OnConsentRejectAllPayload,OnConsentCloseBannerPayload,OnConsentPersonalizedPayloadUiConfig,StoreType,LoggerType,FrameworkType,FrameworkItem,FrameworkConfigItemCoreEventsType,EventPayload<T>ConsentState,ProviderInstanceMap,ProviderName,GlossaryEntry