Laravel Customer Notification Software

Multi-Channel Notification Platform for Laravel

Laravel Customer Notification Software

Multi-Channel Notification Platform for Laravel

Our customer notification software provides a unified platform for sending transactional and marketing messages across SMS, email, and push notifications. Built on Laravel, it offers a single API, centralized template management, user preference controls, and comprehensive delivery analytics.

Multi-Channel Support

Send messages through any channel from a single API:

ChannelUse CasesDelivery Rate
SMSOrder confirmations, alerts, OTPs99%+
EmailReceipts, newsletters, reports97%+
PushIn-app alerts, reminders85%+
WhatsAppCustomer support, order updates98%+

Unified API

<?php

namespace App\Services\Notifications;

use App\Models\NotificationTemplate;
use App\Models\User;
use Illuminate\Support\Facades\Notification;

class UnifiedNotificationService
{
    public function send(User $user, string $templateKey, array $data = []): void
    {
        $template = NotificationTemplate::where('key', $templateKey)->firstOrFail();

        $channels = $user->notificationPreferences()
            ->where('enabled', true)
            ->pluck('channel')
            ->toArray();

        if (empty($channels)) {
            $channels = ['sms']; // Default fallback
        }

        $notification = new DynamicNotification($template, $data);

        Notification::send($user, $notification->via($channels));
    }
}
---

## Notification Templates

Manage all notification content from a central interface:

```php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    public function up(): void
    {
        Schema::create('notification_templates', function (Blueprint $table) {
            $table->id();
            $table->string('key')->unique();
            $table->string('name');
            $table->text('description')->nullable();
            $table->text('sms_body')->nullable();
            $table->text('email_subject')->nullable();
            $table->longText('email_body')->nullable();
            $table->text('push_title')->nullable();
            $table->text('push_body')->nullable();
            $table->json('variables')->nullable();
            $table->json('channels')->nullable(); // ['sms', 'email', 'push']
            $table->boolean('is_active')->default(true);
            $table->timestamps();
        });
    }
};
---

Render templates with dynamic data:

```php
<?php

namespace App\Services\Notifications;

use App\Models\NotificationTemplate;
use Illuminate\Support\Str;

class TemplateRenderer
{
    public function render(NotificationTemplate $template, string $channel, array $data): string
    {
        $content = match ($channel) {
            'sms' => $template->sms_body,
            'email' => $template->email_body,
            'push' => $template->push_body,
            default => throw new \InvalidArgumentException("Unknown channel: {$channel}"),
        };

        foreach ($data as $key => $value) {
            $content = Str::replace("{{$key}}", (string) $value, $content);
        }

        return $content;
    }

    public function getAvailableVariables(NotificationTemplate $template): array
    {
        preg_match_all('/\{\{(\w+)\}\}/', $template->sms_body . $template->email_body . $template->push_body, $matches);

        return array_unique($matches[1]);
    }
}
---

## User Preferences

Let users control how and when they receive notifications:

```php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    public function up(): void
    {
        Schema::create('user_notification_preferences', function (Blueprint $table) {
            $table->id();
            $table->foreignId('user_id')->constrained()->cascadeOnDelete();
            $table->string('type', 64); // order_confirmation, marketing, shipping, etc.
            $table->string('channel', 32); // sms, email, push, whatsapp
            $table->boolean('enabled')->default(true);
            $table->time('quiet_hours_start')->nullable();
            $table->time('quiet_hours_end')->nullable();
            $table->timestamps();

            $table->unique(['user_id', 'type', 'channel']);
        });
    }
};
---

```php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class UserNotificationPreference extends Model
{
    protected $guarded = [];

    public static function getEffectiveChannel(User $user, string $type): ?string
    {
        $preferences = static::where('user_id', $user->id)
            ->where('type', $type)
            ->where('enabled', true)
            ->get();

        if ($preferences->isEmpty()) {
            // Default: SMS if phone exists, otherwise email
            return $user->phone ? 'sms' : 'email';
        }

        $now = now()->format('H:i');

        foreach ($preferences as $pref) {
            if ($pref->quiet_hours_start && $pref->quiet_hours_end) {
                if ($now >= $pref->quiet_hours_start && $now <= $pref->quiet_hours_end) {
                    continue; // Skip during quiet hours
                }
            }

            return $pref->channel;
        }

        return null; // All channels in quiet hours
    }
}
---

## Delivery Analytics

Track every message's journey with detailed analytics:

```php
<?php

namespace App\Console\Commands;

use App\Models\SmsMessage;
use Illuminate\Console\Command;

class NotificationAnalytics extends Command
{
    protected $signature = 'notifications:analytics {--days=30} {--format=table}';
    protected $description = 'Show notification delivery analytics';

    public function handle()
    {
        $since = now()->subDays($this->option('days'));

        $totalSms = SmsMessage::where('created_at', '>=', $since)->count();
        $totalEmail = EmailMessage::where('created_at', '>=', $since)->count();
        $totalPush = PushNotification::where('created_at', '>=', $since)->count();

        $channelStats = [
            ['SMS', $totalSms,
                SmsMessage::delivered()->where('created_at', '>=', $since)->count(),
                SmsMessage::failed()->where('created_at', '>=', $since)->count()],
            ['Email', $totalEmail,
                EmailMessage::delivered()->where('created_at', '>=', $since)->count(),
                EmailMessage::failed()->where('created_at', '>=', $since)->count()],
            ['Push', $totalPush,
                PushNotification::delivered()->where('created_at', '>=', $since)->count(),
                PushNotification::failed()->where('created_at', '>=', $since)->count()],
        ];

        $this->table(
            ['Channel', 'Total', 'Delivered', 'Failed', 'Success Rate'],
            array_map(function ($stat) {
                $rate = $stat[1] > 0
                    ? round(($stat[2] / $stat[1]) * 100, 1) . '%'
                    : 'N/A';
                return [...$stat, $rate];
            }, $channelStats)
        );

        // Trending notification types
        $topTypes = SmsMessage::where('created_at', '>=', $since)
            ->selectRaw('type, COUNT(*) as count')
            ->groupBy('type')
            ->orderByDesc('count')
            ->limit(5)
            ->get();

        $this->newLine();
        $this->info('Top Notification Types:');
        $this->table(
            ['Type', 'Volume'],
            $topTypes->map(fn($t) => [$t->type, number_format($t->count)])->toArray()
        );
    }
}
---

## Pricing

| Feature | Starter | Professional | Enterprise |
|---------|---------|-------------|-----------|
| Channels | SMS + Email | SMS + Email + Push | All channels |
| Templates | 10 | Unlimited | Unlimited |
| Users | 1,000 | 10,000 | Unlimited |
| API Rate Limit | 100/min | 1,000/min | 10,000/min |
| Analytics | Basic | Advanced | Custom |
| Support | Email | Email + Chat | 24/7 Phone |
| **Price** | **$99/mo** | **$299/mo** | **Custom** |

Each plan includes 10,000 SMS messages. Additional messages billed at $0.005 each (volume discounts available).

## Integration Guide

### Installation

```bash
composer require laravelsms/notification-platform

php artisan vendor:publish --tag=notification-platform-config
php artisan migrate
---

### Configuration

```php
<?php

// config/notification-platform.php
return [
    'default_channels' => ['sms', 'email'],
    'track_opens' => true,
    'track_clicks' => true,
    'queue' => 'notifications',
    'channels' => [
        'sms' => [
            'driver' => env('SMS_DRIVER', 'laravelsms'),
            'from' => env('SMS_FROM', 'YourApp'),
        ],
        'email' => [
            'driver' => env('MAIL_MAILER', 'smtp'),
            'from' => env('MAIL_FROM_ADDRESS'),
        ],
        'push' => [
            'driver' => env('PUSH_DRIVER', 'firebase'),
            'api_key' => env('FIREBASE_API_KEY'),
        ],
    ],
];
---

### Sending Notifications

```php
<?php

namespace App\Http\Controllers;

use App\Services\Notifications\UnifiedNotificationService;
use Illuminate\Http\Request;

class OrderController extends Controller
{
    public function __construct(
        protected UnifiedNotificationService $notifications
    ) {}

    public function ship(int $orderId)
    {
        $order = Order::findOrFail($orderId);
        $order->update(['status' => 'shipped']);

        $this->notifications->send(
            $order->user,
            'order_shipped',
            [
                'order_number' => $order->order_number,
                'tracking_url' => $order->tracking_url,
                'estimated_delivery' => $order->estimated_delivery->format('M d'),
            ]
        );

        return redirect()->back()->with('success', 'Order marked as shipped.');
    }
}
---

## Platform Dashboard

The included dashboard gives you:

- **Real-time delivery metrics** — Live view of messages sent, delivered, and failed
- **Channel breakdown** — Per-channel performance comparison
- **Template performance** — Which notification types drive the most engagement
- **User preference reports** — How users configure their notification settings
- **Cost analysis** — Per-channel cost breakdown with billing projections

## Start Free Trial

Try the full platform free for 14 days. No credit card required.

[Start Free Trial](/contact)

Already have our [Laravel SMS API](/services/laravel-sms-api)? The notification platform extends it with multi-channel support and template management. Need enterprise features? See our [enterprise SMS solution](/services/enterprise-sms-solution-laravel) or [custom development](/services/custom-laravel-sms-development) options.

Ready to Get Started?

Contact us today to discuss your Laravel SMS needs.

Start Free Trial