Add Firebase Push Notifications to SaaS laravel Web App
Fermin Perdomo
If you’re building a restaurant SaaS platform with Laravel and want to notify staff in real-time when a customer places a new order or taps "Call Waiter", then this guide is for you!
We'll show you how to integrate Firebase Cloud Messaging (FCM) with a multi-tenant Laravel system and trigger push notifications to multiple devices — including Chrome on desktop, Android tablet, and Android mobile
Step 1: Set Up Firebase
- Go to Firebase Console
- Create or select a project
- Navigate to Project Settings > Cloud Messaging
- Save your Server Key and Sender ID
- Under General, register your Web App
- Grab the Firebase config (apiKey, projectId, etc.)
Step 2: Install Laravel FCM SDK
composer require kreait/firebase-php
In your .env file:
FCM_CREDENTIALS=/full/path/to/firebase-credentials.json
In config/services.php:
'fcm' => [
'credentials' => env('FCM_CREDENTIALS'),
],
Step 3: Create a Firebase Notification Service
// app/Services/FCMService.php
namespace App\Services;
use Kreait\Firebase\Factory;
use Kreait\Firebase\Messaging\CloudMessage;
use Kreait\Firebase\Messaging\Notification;
class FCMService
{
protected $messaging;
public function __construct()
{
$this->messaging = (new Factory)
->withServiceAccount(config('services.fcm.credentials'))
->createMessaging();
}
public function sendToTokens(array $tokens, $title, $body, array $data = [])
{
$notification = Notification::create($title, $body);
$message = CloudMessage::new()
->withNotification($notification)
->withData($data);
return $this->messaging->sendMulticast($message, $tokens);
}
}
Step 4: Store FCM Tokens in Database
Create a model and migration:
php artisan make:model FCMToken -m
In the migration file:
Schema::create('f_c_m_tokens', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('restaurant_id');
$table->string('token');
$table->timestamps();
});
Then run:
php artisan migrate
Step 5: Add Firebase JS to Your Frontend
Paste this into your Blade layout or Vue component:
<script src="https://www.gstatic.com/firebasejs/9.6.10/firebase-app-compat.js"></script>
<script src="https://www.gstatic.com/firebasejs/9.6.10/firebase-messaging-compat.js"></script>
<script>
const firebaseConfig = {
apiKey: "YOUR_API_KEY",
authDomain: "YOUR_PROJECT_ID.firebaseapp.com",
projectId: "YOUR_PROJECT_ID",
messagingSenderId: "YOUR_SENDER_ID",
appId: "YOUR_APP_ID"
};
firebase.initializeApp(firebaseConfig);
const messaging = firebase.messaging();
async function initFCM(restaurantId) {
try {
const permission = await Notification.requestPermission();
if (permission === 'granted') {
const token = await messaging.getToken({
vapidKey: "YOUR_PUBLIC_VAPID_KEY"
});
await fetch('/api/register-fcm-token', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': '{{ csrf_token() }}'
},
body: JSON.stringify({ token, restaurant_id: restaurantId })
});
}
} catch (err) {
console.error('FCM error:', err);
}
}
</script>
Step 6: Create an API Route to Register Tokens
Route::post('/api/register-fcm-token', function (Request $request) {
$request->validate([
'token' => 'required',
'restaurant_id' => 'required|integer',
]);
\App\Models\FCMToken::updateOrCreate(
['token' => $request->token],
['restaurant_id' => $request->restaurant_id]
);
return response()->json(['success' => true]);
});
Step 7: Add the Service Worker
In your public/ folder, create firebase-messaging-sw.js:
importScripts('https://www.gstatic.com/firebasejs/9.6.10/firebase-app-compat.js');
importScripts('https://www.gstatic.com/firebasejs/9.6.10/firebase-messaging-compat.js');
firebase.initializeApp({
apiKey: "YOUR_API_KEY",
projectId: "YOUR_PROJECT_ID",
messagingSenderId: "YOUR_SENDER_ID",
appId: "YOUR_APP_ID"
});
const messaging = firebase.messaging();
messaging.onBackgroundMessage(function(payload) {
const { title, body } = payload.notification;
self.registration.showNotification(title, {
body: body,
data: payload.data
});
});
Register it in your main script:
navigator.serviceWorker.register('/firebase-messaging-sw.js')
.then((registration) => {
messaging.useServiceWorker(registration);
});
Step 8: Trigger Notifications from Laravel
Whenever a new order or "Call Waiter" event occurs:
use App\Services\FCMService;
use App\Models\FCMToken;
$tokens = FCMToken::where('restaurant_id', $restaurantId)->pluck('token')->toArray();
$title = "New Order!";
$body = "Table {$tableNumber} placed an order.";
$data = [
'restaurant_id' => $restaurantId,
'table_number' => $tableNumber,
];
app(FCMService::class)->sendToTokens($tokens, $title, $body, $data);
✅ Done!
Your Laravel app now supports:
✅ Real-time push notifications
✅ Multi-device, multi-table, multi-restaurant structure
✅ Firebase-based delivery via web browser
Newsletter
Get new posts delivered straight to your inbox.
Great Tools for Developers
Git Tower
Get Started - It's FreeA powerful Git client for Mac and Windows that simplifies version control.
Mailcoach
Start freeSelf-hosted email marketing platform for sending newsletters and automated emails.
Uptimia
Start freeWebsite monitoring and performance testing tool to ensure your site is always up and running.
Cloudways
Start freeManaged cloud hosting platform that simplifies server management for developers.
Comments
No comments yet. Be the first to share your thoughts.