Plugin System
Plugins extend the Consenti backend with custom lifecycle hooks. They run server-side, are instantiated once per createConsenti() call, and can access the full storage adapter.
Plugin contract
ts
import { ConsentiServerPlugin } from '@consenti/api'
import type { ConsentDbRecord, CreateConsentInput, PluginContext } from '@consenti/api'
export class MyPlugin extends ConsentiServerPlugin {
name = 'my-plugin'
async initialize(ctx: PluginContext): Promise<void> {
// Called once after storage.connect() resolves.
// ctx.storage gives you the full StorageAdapter.
// ctx.config gives you the server config.
}
async destroy(): Promise<void> {
// Called on graceful shutdown — close connections, clear timers.
}
// ── Optional hooks ──────────────────────────────────────────────────────────
async beforeConsentSave(data: CreateConsentInput): Promise<CreateConsentInput> {
return data // mutate or validate before DB write
}
async afterConsentSave(record: ConsentDbRecord): Promise<void> {
// fires after consent is persisted — perfect for webhooks, analytics
}
async afterConsentUpdate(record: ConsentDbRecord): Promise<void> {
// fires after PUT /consent/:visitorId
}
}Registering plugins
ts
import { createConsenti } from '@consenti/api'
import { WebhookPlugin } from '@consenti-plugin-webhook'
import { SlackPlugin } from '@consenti-plugin-slack'
const app = createConsenti({
storage: { driver: 'sqlite', path: './consenti.db' },
auth: { mode: 'local', adminEmail: '[email protected]', adminPassword: 'secret' },
plugins: [
new WebhookPlugin('https://your-endpoint.example.com/hook'),
new SlackPlugin({ webhookUrl: process.env.SLACK_WEBHOOK }),
],
})Available hooks
| Hook | When it fires |
|---|---|
initialize(ctx) | After storage.connect() resolves — once at startup |
destroy() | On graceful shutdown |
beforeConsentSave(data) | Before a new consent record is written — can mutate the payload |
afterConsentSave(record) | After a new consent record is persisted |
beforeConsentUpdate(data) | Before an existing consent record is updated |
afterConsentUpdate(record) | After an existing consent record is updated |
beforeProfileFetch(id) | Before a profile is fetched — can redirect to a different profile ID |
afterProfileFetch(profile) | After a profile is fetched — can mutate the profile |
beforeUserCreate(data) | Before an admin user is created |
afterUserCreate(user) | After an admin user is created |
Error handling
If a plugin throws in any hook, Consenti logs the error with console.warn and continues — a broken plugin never blocks consent from being recorded.
Official plugins
BigQuery
Stream consent records to Google BigQuery for analytics
@consenti-plugin-bigquerySegment
Fire Consent Given events to Segment / Twilio Engage
@consenti-plugin-segmentSnowflake
Load consent records into Snowflake data warehouse
@consenti-plugin-snowflakeCommunity plugins
Publish your own under any package name. The only requirement is extending ConsentiServerPluginand declaring @consenti/api as a peer dependency.
package.json
json
{
"name": "@your-scope/consenti-plugin-custom",
"peerDependencies": {
"@consenti/api": ">=0.1.0"
}
}