name: klytos-consent-manager description: Guide for implementing GDPR/CCPA-compliant cookie consent in Klytos CMS. Use when configuring consent settings, managing plugin cookie declarations, setting up the consent banner, auditing compliance, integrating third-party scripts (Google Analytics, Meta Pixel, Matomo, etc.), or working with the JavaScript consent library. Covers configuration, PHP API, JavaScript API, MCP tools, hooks, build integration, and plugin developer guide.
Klytos Consent Manager
Overview
The Consent Manager provides GDPR/CCPA-compliant cookie consent for Klytos's static frontend. It controls which cookies and external scripts load based on visitor consent.
Architecture: Client-side JavaScript library (consent-manager.js) configured at build time with admin-defined settings. Plugins declare their cookies/scripts via the PHP API or MCP tools; the JS library enforces consent at runtime.
Key Files
| File | Purpose |
|---|---|
installer/core/consent-manager.php |
PHP ConsentManager class — config, declarations, audit |
installer/core/assets/consent-manager.js |
Client-side JS library (~983 lines, complete) |
installer/admin/consent.php |
Admin page — config form, audit table, exports |
installer/core/mcp/tools/consent-tools.php |
6 MCP tools for consent management |
installer/core/build-engine.php |
Build integration — copies JS, injects <script> tags |
installer/templates/parts/head.html |
Template — {{consent_manager_script}} placeholder |
Configuration
Stored via OptionsManager key consent_manager.config:
[
'enabled' => false, // Master switch
'banner_text' => 'Este sitio...', // Banner message
'privacy_url' => '/privacy', // Privacy policy link
'cookie_days' => 365, // Consent cookie duration
'categories' => [], // Custom categories (beyond defaults)
]
Default Categories
| Category | Always Active | Description |
|---|---|---|
necessary |
Yes | Session, CSRF, consent cookie |
functional |
No | Chat, personalization, language |
analytics |
No | Google Analytics, Matomo, Plausible |
marketing |
No | Meta Pixel, Google Ads, remarketing |
Categories are extensible via config or the consent.config filter.
PHP API
$cm = $app->getConsentManager();
// Config
$config = $cm->getConfig();
$cm->saveConfig(['enabled' => true, 'banner_text' => '...']);
// Declarations (server-side audit registry)
$cm->savePluginDeclaration([
'plugin_id' => 'google-analytics',
'name' => 'Google Analytics',
'category' => 'analytics',
'description' => 'Collects anonymized visit statistics.',
'vendor' => 'Google LLC',
'privacy_url' => 'https://policies.google.com/privacy',
'cookies' => [
['name' => '_ga', 'duration' => '2 years', 'description' => 'Unique user ID'],
],
'scripts' => ['https://www.googletagmanager.com/gtag/js?id=G-XXXXX'],
]);
$declarations = $cm->getPluginDeclarations();
$cm->deletePluginDeclaration('google-analytics');
$audit = $cm->getAuditReport();
JavaScript API (Frontend)
The JS library is loaded in <head> (no defer) and initialized with config from the build:
// Init (generated by build engine)
ConsentManager.init({ bannerText: '...', privacyUrl: '/privacy', autoShow: true });
// Plugin registration (in plugin JS files)
ConsentManager.register({
pluginId: 'my-plugin',
name: 'My Plugin',
category: 'analytics',
cookies: [{ name: '_mp', duration: '1 year', description: 'Tracking ID' }],
scripts: ['https://cdn.example.com/tracker.js'],
onAccept: function(errors) { /* init tracking */ },
onReject: function() { /* cleanup */ }
});
// Query consent
ConsentManager.hasConsent('analytics'); // true/false
ConsentManager.getConsentState(); // { necessary: true, analytics: false, ... }
ConsentManager.onChange(function(cats) {}); // Listen for changes
// Control
ConsentManager.acceptAll();
ConsentManager.acceptNecessaryOnly();
ConsentManager.updateConsent({ analytics: true, marketing: false });
ConsentManager.showSettings(); // Open settings panel
ConsentManager.revokeAll();
ConsentManager.reset(); // Clear and re-show banner
Blocked Scripts (HTML)
<script type="text/plain" data-consent-category="analytics"
src="https://www.googletagmanager.com/gtag/js?id=G-XXXXX"></script>
Scripts with type="text/plain" are ignored by the browser. When the visitor accepts the category, ConsentManager clones them with type="text/javascript".
MCP Tools
| Tool | Read-only | Description |
|---|---|---|
klytos_get_consent_config |
Yes | Get current configuration |
klytos_set_consent_config |
No | Update configuration (triggers rebuild) |
klytos_list_consent_declarations |
Yes | List all plugin declarations |
klytos_add_consent_declaration |
No | Add/update a plugin declaration |
klytos_delete_consent_declaration |
No | Remove a declaration |
klytos_get_consent_audit |
Yes | Full audit report grouped by category |
Hooks
| Hook | Type | Description |
|---|---|---|
consent.config |
Filter | Modify config before output |
consent.declarations |
Filter | Modify declarations list |
consent.before_save |
Action | Before saving config |
consent.after_save |
Action | After saving config |
consent.init_config |
Filter | Modify JS init config during build |
consent.audit_export |
Filter | Modify audit data before export |
admin.consent.before |
Action | Before admin page renders |
admin.consent.after |
Action | After admin page renders |
Build Engine Integration
During buildAll():
buildConsentManagerJs()— copiescore/assets/consent-manager.jstooutput/assets/js/with cache-bust hashbuildConsentManagerJsTag($basePath)— returns<script>tags (library + init call)- Template placeholder
{{consent_manager_script}}inhead.html— placed before all other scripts/stylesheets
When disabled: no JS file is copied, placeholder resolves to empty string.
Admin Page
URL: admin/consent.php
Sidebar: System section, position 66, icon fa-cookie-bite, capability site.configure
Features:
- Enable/disable toggle
- Banner text, privacy URL, cookie duration
- Audit table showing all declarations grouped by category
- Export JSON/CSV for legal compliance
- Save triggers site rebuild
Plugin Developer Guide
PHP-side (server audit registry)
In your plugin's init.php:
klytos_add_action('klytos.init', function ($app) {
$app->getConsentManager()->savePluginDeclaration([
'plugin_id' => 'my-plugin',
'name' => 'My Plugin',
'category' => 'analytics',
'cookies' => [
['name' => '_mp_id', 'duration' => '1 year', 'description' => 'User identifier'],
],
'scripts' => ['https://cdn.example.com/sdk.js'],
]);
});
JS-side (runtime consent enforcement)
In your plugin's assets/js/hooks.js:
ConsentManager.register({
pluginId: 'my-plugin',
name: 'My Plugin',
category: 'analytics',
cookies: [{ name: '_mp_id', duration: '1 year', description: 'User identifier' }],
scripts: ['https://cdn.example.com/sdk.js'],
onAccept: function() { /* initialize */ },
onReject: function() { /* cleanup */ }
});
Both registrations are recommended: PHP-side for admin audit, JS-side for runtime enforcement.