Cookie consent for Laravel
The banner is one tag in your Blade layout, before @vite. The consents your forms ask for — newsletter, terms — are recorded from your controller with one HTTP call, each with a signed receipt.
Set it up with your AI agent
Connect the Croombit MCP server to your editor or coding agent and paste this. It creates the site, the cookie categories and the banner, and edits your code.
Using Croombit: create a site for this project and keep the cookie categories it comes with. Write the banner text and publish the banner. Create a TEST publishable key for localhost:3000. This is a Laravel app: add the cmp.js tag first in <head> of resources/views/layouts/app.blade.php with the key from config('services.croombit.key'), add the croombit entry to config/services.php, and record the newsletter checkbox of our signup controller with Http::post to /v1/consent using CROOMBIT_SECRET_KEY.The agent works in TEST. Going live takes two steps in the console: verify your domain and swap in a LIVE key — see going live.
Or by hand
1. Keys in config/services.php
// config/services.php
'croombit' => [
'key' => env('CROOMBIT_PUBLISHABLE_KEY'), // pk_test_… locally, pk_live_… in production
'secret' => env('CROOMBIT_SECRET_KEY'), // sk_… — server only
],2. Add the tag to your layout
{{-- resources/views/layouts/app.blade.php --}}
<head>
<meta charset="utf-8">
<script src="https://croombit.com/cmp.js"
data-tc-api-key="{{ config('services.croombit.key') }}"></script>
{{-- …everything else after it --}}
@vite(['resources/css/app.css', 'resources/js/app.js'])
</head>3. Hold back trackers
Tags in your Blade views: type="text/plain" plus data-tc-consent. They stay inert until the visitor grants that category.
<script type="text/plain" data-tc-consent="analytics" async
src="https://www.googletagmanager.com/gtag/js?id=G-XXXX"></script>
<script type="text/plain" data-tc-consent="analytics">
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-XXXX');
</script>4. Record consents from your controller
A plain POST /v1/consent with your secret key — no SDK needed. The Idempotency-Key makes a retry safe. See Record and query consent.
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Str;
// e.g. in the controller that handles your signup form
Http::withToken(config('services.croombit.secret'))
->withHeaders(['Idempotency-Key' => (string) Str::uuid()])
->post('https://api.croombit.com/v1/consent', [
'subject' => 'email:' . $user->email,
'purpose' => 'newsletter',
'state' => $request->boolean('newsletter') ? 'GRANTED' : 'DENIED',
'channel' => 'signup_form',
])
->throw();Questions
I have a Content Security Policy. What do I allow?
script-src https://croombit.com for the banner and connect-src https://api.croombit.com for its calls.
Does it work with Inertia or Livewire?
Yes. The tag lives in the Blade layout that wraps them, so it loads once, before your app.
Related
- Cookie consent for any website
- Cookie consent for Next.js
- Cookie consent for React
- Cookie consent for Vue and Nuxt
- Cookie consent for Astro
- Cookie consent for SvelteKit
- Cookie consent for React Router and Remix
- Cookie consent for Django
- Cookie consent for Ruby on Rails
- Cookie consent for WordPress
- Cookie consent for Webflow
- Cookie consent for Framer
- Cookie consent for Hugo and Jekyll
- Guide: cookie banner
- Console: Cookies (scanner)
- TCF, Consent Mode and GPP
- Google Consent Mode v2: basic vs. advanced