mmoollllee/filament-consent-control
Filament Consent Control adds configurable cookie and privacy consent management to Filament panels, with ready-made banners, preference controls, and admin tools to help Laravel apps meet GDPR requirements.
This is the Filament admin layer on top of mmoollllee/laravel-consent-control (auto-installed) and the consent-control npm runtime. Day to day, it exists to solve one problem: letting content editors embed YouTube/Vimeo/Maps iframes in a RichEditor without those embeds loading before the visitor consents. If you don't need editor-side embedding or a settings screen, you don't need this package.
Install in three steps:
composer require mmoollllee/filament-consent-control
php artisan vendor:publish --tag=consent-control-config
php artisan vendor:publish --tag=consent-control-assets
Then register the plugin on your panel — it is inert until you opt into a feature:
$panel->plugins([
\Mmoollllee\FilamentConsentControl\ConsentControlPlugin::make(),
]);
Where to look first:
config/consent-control.php (published from the base package) — the single source of truth for categories, texts, and driver. Read this before touching the plugin.ConsentControlPlugin::make()->settingsPage() — only add this once the editor flow works.First use case to validate: add the consent-iframe tool to one RichEditor, paste a YouTube URL, save, and inspect the DB. You should see .consent-message--wrapper markup with data-src — not an <iframe>. Then load the frontend page with the npm consent-control runtime present and confirm the iframe only appears after consent. That second half is the part people forget; the Filament package handles authoring, not gating on the public site.
Verify requirements before committing: PHP 8.2+, Laravel 11.28+/12, Filament 5. The Filament 5 Schema API requirement is hard — this will not work on a Filament 3 or 4 panel, so check your composer.json before you plan any work around it.
Editor-authoring pattern (the core workflow). Attach the consent-iframe action to RichEditor toolbars where embeds are legitimate — typically a "Content" or "Blog post" resource, not every editor in the panel. Editors paste a normal YouTube/Vimeo link; the package normalises it (YouTube → youtube-nocookie, Vimeo → player embed) and stores blocked markup. The URL normalisation means you should tell editors to paste the watch URL, not hand-built embed code, or you lose the privacy-friendly rewrite.
Render-side contract. Treat the stored HTML as a contract with the frontend runtime:
.consent-message--wrapper + data-src is the gate.consent-control JS on the public site swaps in the iframe after consent.strip_tags, custom Blade cleaning) can silently break gating. If you run HTMLPurifier or similar, allowlist the wrapper class and data-src.Settings page — two modes, pick one:
ConsentControlPlugin::make()->settingsPage() registers a ready-made page writing through the eloquent driver. Good for a single-panel app where a non-developer should tweak consent copy/categories at runtime.ConsentSettingsForm inside your own resource or page when you need custom authorization, navigation grouping, or multi-tenant scoping. This is the better fit for anything beyond a single site.Don't do both for the same settings — you'll get two write paths to the same config and confusing cache behaviour.
Multi-panel / multi-tenant. Register the plugin only on the panel whose users should author gated embeds. If you run separate admin and content-team panels, put the editor plugin on the content panel and the settings page on the admin panel.
Testing pattern. Filament 5 panels are Livewire-testable; assert on the stored value rather than rendered output — i.e. that saved content contains data-src and does not contain a live <iframe src=. That single assertion catches most regressions in this area.
The plugin does nothing by default — and that's by design. ConsentControlPlugin::make() alone registers nothing user-visible. If the toolbar button or settings page is missing, the first thing to check is whether you actually called settingsPage() / attached the editor action, not whether the package installed.
Publish tags belong to the base package. consent-control-config and consent-control-assets come from laravel-consent-control, not this package. If you already had the base package installed, those files likely already exist and vendor:publish will no-op — use --force deliberately, and diff before overwriting a tuned config.
Existing content is not retro-migrated. Any iframe embedded before you installed this stays a raw <iframe> in the database and keeps loading third-party requests. You need a backfill or a re-save of affected records. Audit with a query for <iframe in your rich-content columns before you claim GDPR compliance.
Don't "fix" the missing iframe. The most common misdiagnosis: a developer sees data-src in the DOM, assumes rendering is broken, and renders the real iframe server-side. That defeats the entire package. The iframe appearing only after consent is correct behaviour, and it requires the npm runtime to be loaded on the page.
youtube-nocookie and CSP. Your Content-Security-Policy frame-src must allow https://www.youtube-nocookie.com and https://player.vimeo.com. Note that youtube-nocookie is a different origin from youtube.com — CSPs copied from older projects will block the embed and look like a package bug.
Normalisation may drop parameters. The auto-rewrite of pasted links is convenient but be sceptical of query strings — start times (?t=), playlist IDs, and Vimeo privacy hashes (?h=) are exactly the kind of thing a naive URL rewrite loses. Test with a real link containing a timestamp before rolling out to editors.
v0.1.0 with a "Fixed" section is a signal. A first release that already lists fixes to the JS/PHP command name mismatch (setConsentIframe) and "undefined helpers" indicates the pre-release state was unstable. Pin an exact version in composer.json, avoid depending on internal class names or the JS command string, and re-test the editor after every bump.
Translations aren't covered by a publish tag. Labels are described as translatable, but the install steps don't publish lang files. Check whether translations live in the package's lang/ directory (overridable via lang/vendor/...) before promising a localised admin UI.
Evaluate the bus factor. Single-maintainer, 0.x, and the stack spans three repos (this package → laravel-consent-control → consent-control npm) plus a hard Filament 5 dependency. That's a lot of moving parts for a compliance-relevant feature. If consent gating is a legal requirement for you, budget for the possibility of vendoring or forking the render path.
How can I help you explore Laravel packages today?