spatie/laravel-support-form
Add a non-intrusive Tailwind-styled support chat bubble to any Laravel page. Opens a support form, auto-fills user info when logged in, includes URL/IP metadata, honeypot spam protection, and is easily customizable via views, translations, and events.
Installation:
composer require spatie/laravel-support-bubble
php artisan vendor:publish --provider="Spatie\SupportBubble\SupportBubbleServiceProvider" --tag="support-bubble-config"
php artisan migrate
Publish the config, assets, and views to customize defaults.
First Use Case:
Add the chat bubble to your layout (e.g., resources/views/layouts/app.blade.php):
@supportBubble
This renders the default bubble with minimal configuration.
Configuration:
Update .env with your support email:
SUPPORT_BUBBLE_EMAIL=support@example.com
Customize further in config/support-bubble.php (e.g., bubble position, colors, or form fields).
Integration with Layouts:
Use the @supportBubble directive in your base template to ensure the bubble appears on all pages. For selective pages, conditionally render it:
@if(request()->is('/contact') || request()->is('/pricing'))
@supportBubble
@endif
Customizing the Form: Extend the default form by publishing views:
php artisan vendor:publish --tag="support-bubble-views"
Modify resources/views/vendor/support-bubble/form.blade.php to add/remove fields (e.g., custom dropdowns or file uploads).
Handling Submissions:
Listen for form submissions via the SupportBubbleSubmitted event:
use Spatie\SupportBubble\Events\SupportBubbleSubmitted;
SupportBubbleSubmitted::listen(function (SupportBubbleSubmitted $event) {
// Log, notify Slack, or process the submission
Log::info('Support bubble submission', $event->supportBubbleData);
});
Dynamic Bubble Visibility: Toggle the bubble based on user segments (e.g., logged-out users only):
// config/support-bubble.php
'visible' => function () {
return !auth()->check();
},
Localization: Translate the bubble and form using Laravel’s localization:
php artisan vendor:publish --tag="support-bubble-lang"
Update resources/lang/en/support-bubble.php and add translations for other locales.
Custom Styling: Override TailwindCSS classes in the published views or use inline styles:
<div class="support-bubble custom-class" x-data="supportBubble()">
<!-- Custom content -->
</div>
Extend the supportBubble() Alpine.js component in a custom JS file.
API-Based Submissions: Replace the default email logic to store submissions in a database or send via API:
// app/Providers/SupportBubbleServiceProvider.php
public function boot()
{
SupportBubbleSubmitted::listen(function ($event) {
SupportBubble::create($event->supportBubbleData);
// Or send to a third-party API
});
}
Multi-Tenant Support: Scope submissions to tenants using a trait or middleware:
// app/Models/SupportBubble.php
use Spatie\Multitenancy\Tenancy;
class SupportBubble extends Model
{
public static function boot()
{
parent::boot();
static::creating(function ($model) {
$model->tenant_id = Tenancy::tenant()->id;
});
}
}
A/B Testing: Randomize bubble visibility or styling for experiments:
'visible' => function () {
return request()->has('ab_test') && request()->ab_test === 'show_bubble';
},
Honeypot Misconfiguration:
support-bubble::form) is hidden but included in the form. Example:
<div class="hidden">
<input type="text" name="honeypot" />
</div>
honeypot_field in config/support-bubble.php).Alpine.js Conflicts:
^3.0 in package.json:
"alpinejs": "^3.10.2"
php artisan view:clear
CSRF Token Issues:
@csrf
VerifyCsrfToken middleware.Database Schema Mismatches:
SupportBubble model errors:
php artisan migrate
TailwindCSS Conflicts:
// tailwind.config.js
content: [
'./resources/**/*.blade.php',
'./vendor/spatie/laravel-support-bubble/**/*.blade.php',
],
Log Submissions: Temporarily log all submissions to debug data:
SupportBubbleSubmitted::listen(function ($event) {
\Log::debug('Support Bubble Data', $event->supportBubbleData->toArray());
});
Check Published Assets:
Verify published views and config files exist in resources/views/vendor/support-bubble and config/support-bubble.php.
Disable JavaScript: Test the bubble with JS disabled to ensure fallback functionality works (e.g., direct form submission).
Inspect Network Requests:
Use browser dev tools to verify form submissions reach the expected endpoint (/support-bubble).
Custom Validation:
Extend validation rules in app/Providers/SupportBubbleServiceProvider:
use Illuminate\Support\Facades\Validator;
SupportBubbleSubmitted::listen(function ($event) {
$validator = Validator::make($event->supportBubbleData->toArray(), [
'message' => 'required|max:1000',
'custom_field' => 'sometimes|string',
]);
if ($validator->fails()) {
// Handle validation errors
}
});
Webhook Notifications: Send submissions to a webhook (e.g., Slack, Zapier):
SupportBubbleSubmitted::listen(function ($event) {
Http::post('https://hooks.slack.com/services/...', [
'text' => 'New support request: ' . $event->supportBubbleData->message,
]);
});
Dynamic Form Fields:
Use Laravel Collective’s Form facade or Alpine.js to conditionally render fields:
@if($showCustomField)
<div x-data="{ open: false }">
<button @click="open = !open">Toggle Field</button>
<input x-show="open" type="text" name="custom_field">
</div>
@endif
Rate Limiting: Prevent abuse by rate-limiting submissions:
use Illuminate\Support\Facades\RateLimiter;
SupportBubbleSubmitted::listen(function ($event) {
$key = 'support_bubble|' . request()->ip();
if (!RateLimiter::tooManyAttempts($key, 5)) {
// Process submission
} else {
abort(429, 'Too many submissions');
}
});
Local Testing:
Use Laravel’s fake() to test submissions without sending emails:
Mail::fake();
$event->supportBubbleData->send(); // Will not send in tests
How can I help you explore Laravel packages today?