spatie/laravel-help-space
Laravel package to integrate HelpSpace. Validates incoming HelpSpace sidebar requests and lets you return HTML (views/strings) with customer context based on ticket data like email, so HelpSpace can render rich sidebar info in the help desk UI.
Installation:
composer require spatie/laravel-help-space
Publish the config file (if needed):
php artisan vendor:publish --provider="Spatie\HelpSpace\HelpSpaceServiceProvider"
Configure HelpSpace:
Add your HelpSpace API key to .env:
HELP_SPACE_API_KEY=your_api_key_here
First Use Case:
Register a sidebar callback in AppServiceProvider or a dedicated service provider:
use Spatie\HelpSpace\Facades\HelpSpace;
use Spatie\HelpSpace\Http\Requests\HelpSpaceRequest;
HelpSpace::sidebar(function (HelpSpaceRequest $request) {
return view('helpspace.sidebar', [
'user' => User::where('email', $request->email())->first(),
]);
});
Verify Webhook:
Ensure your Laravel app is publicly accessible and the HelpSpace webhook URL (e.g., https://your-app.com/helpspace/sidebar) is correctly configured in your HelpSpace dashboard.
Dynamic Sidebar Content:
Use the HelpSpaceRequest to fetch user-specific data and render dynamic views:
HelpSpace::sidebar(function (HelpSpaceRequest $request) {
$user = User::with(['orders', 'subscriptions'])->where('email', $request->email())->first();
return view('helpspace.sidebar.user', compact('user'));
});
Conditional Responses: Handle cases where no user is found or data is incomplete:
HelpSpace::sidebar(function (HelpSpaceRequest $request) {
$user = User::where('email', $request->email())->first();
return $user ? view('helpspace.sidebar.user', compact('user')) : 'User not found';
});
Authentication Validation: Validate the incoming request signature to ensure it’s from HelpSpace:
HelpSpace::validate(function (HelpSpaceRequest $request) {
return $request->isValid(); // Automatically checks signature
});
Caching Responses: Cache frequent requests to improve performance:
HelpSpace::sidebar(function (HelpSpaceRequest $request) {
return Cache::remember("helpspace_{$request->ticketId}", now()->addHours(1), function () use ($request) {
return view('helpspace.sidebar.user', ['user' => User::find($request->userId)]);
});
});
Integration with Ticket Data:
Use ticketId or ticketNumber from the request to fetch related ticket data:
HelpSpace::sidebar(function (HelpSpaceRequest $request) {
$ticket = Ticket::where('external_id', $request->ticketId)->first();
return view('helpspace.sidebar.ticket', compact('ticket'));
});
Middleware for Shared Logic: Create middleware to handle shared logic (e.g., logging, rate limiting):
namespace App\Http\Middleware;
use Closure;
use Spatie\HelpSpace\Http\Requests\HelpSpaceRequest;
class HelpSpaceLoggingMiddleware
{
public function handle(HelpSpaceRequest $request, Closure $next)
{
\Log::info("HelpSpace request for ticket {$request->ticketId}");
return $next($request);
}
}
Register it in AppServiceProvider:
HelpSpace::middleware(HelpSpaceLoggingMiddleware::class);
Blade Components: Use Blade components for reusable sidebar sections:
HelpSpace::sidebar(function (HelpSpaceRequest $request) {
return view('helpspace.sidebar', [
'user' => User::find($request->userId),
'recentOrders' => Order::where('user_id', $request->userId)->latest()->take(3)->get(),
]);
});
In resources/views/helpspace/sidebar.blade.php:
@component('helpspace.components.user-info', ['user' => $user])
@endcomponent
@component('helpspace.components.recent-orders', ['orders' => $recentOrders])
@endcomponent
API-Driven Sidebars: Fetch data from external APIs (e.g., Stripe, Shopify) and render it:
HelpSpace::sidebar(function (HelpSpaceRequest $request) {
$customer = \Stripe\Customer::retrieve($request->stripeCustomerId);
return view('helpspace.sidebar.stripe', compact('customer'));
});
Localization: Support multiple languages in the sidebar:
HelpSpace::sidebar(function (HelpSpaceRequest $request) {
$locale = $request->header('Accept-Language') ?? config('app.locale');
app()->setLocale($locale);
return view('helpspace.sidebar', ['user' => User::find($request->userId)]);
});
Webhook URL Mismatch:
helpspace/sidebar).routes/web.php:
Route::middleware(['web', 'helpspace'])->get('/helpspace/sidebar', fn() => HelpSpace::handle());
Signature Validation Failures:
HELP_SPACE_API_KEY is incorrect or the request signature fails, HelpSpace will show an empty sidebar..env and ensure the request includes the X-HelpSpace-Signature header.Rate Limiting:
HelpSpace::sidebar(function (HelpSpaceRequest $request) {
return Cache::remember("helpspace_{$request->ticketId}", now()->addMinutes(5), function () {
return view('helpspace.sidebar', ['user' => User::find($request->userId)]);
});
});
Missing User Data:
HelpSpace::sidebar(function (HelpSpaceRequest $request) {
return User::where('email', $request->email())->exists()
? view('helpspace.sidebar.user')
: view('helpspace.sidebar.guest');
});
CORS Issues:
Log Requests: Log incoming HelpSpace requests for debugging:
HelpSpace::validate(function (HelpSpaceRequest $request) {
\Log::debug('HelpSpace Request', [
'email' => $request->email(),
'ticketId' => $request->ticketId(),
'headers' => $request->header(),
]);
return $request->isValid();
});
Test Locally:
Use ngrok to expose your local Laravel app to HelpSpace for testing:
ngrok http 8000
Configure HelpSpace to use your ngrok URL (e.g., https://your-ngrok-url.ngrok.io/helpspace/sidebar).
Check Laravel Logs:
Inspect storage/logs/laravel.log for errors during HelpSpace requests.
Custom Validation:
Extend the HelpSpaceRequest class to add custom validation logic:
namespace App\Http\Requests;
use Spatie\HelpSpace\Http\Requests\HelpSpaceRequest;
class CustomHelpSpaceRequest extends HelpSpaceRequest
{
public function rules()
{
return array_merge(parent::rules(), [
'custom_field' => 'required|string',
]);
}
}
Update the provider to use your custom request:
HelpSpace::requestClass(CustomHelpSpaceRequest::class);
Dynamic Routes: Register dynamic routes for different sidebar types:
Route::middleware(['web', 'helpspace'])->group(function () {
Route::get('/helpspace/sidebar/user', fn() => HelpSpace::handle('user'));
Route::get('/helpspace/sidebar/ticket', fn() => HelpSpace::handle('ticket'));
});
Handle each type in the provider:
HelpSpace::sidebar('user', function (HelpSpaceRequest $request) { ...
How can I help you explore Laravel packages today?