How Do I

Integrate notification channels

Keep Laravel channel payloads intact while applying NotificationCompass preferences.

NotificationCompass sits between Laravel's notification dispatcher and the channel implementation. Your notification keeps its normal via method and channel-specific methods; NotificationCompass only decides whether a registered notification may use each channel.

Register the channels

List the exact channel names returned by via. The definition key must also match the notification class through notification_class, or through a definition provider.

config/notificationcompass.php
'definitions' => [
    'account.activity' => [
        'notification_class' => App\Notifications\AccountActivity::class,
        'channels' => ['mail', 'database', 'broadcast', 'slack', 'vonage'],
        'defaults' => [
            'mail' => true,
            'database' => true,
            'broadcast' => true,
            'slack' => false,
            'vonage' => false,
        ],
        'channel_options' => [
            'mail' => ['mandatory' => true],
            'slack' => ['opt_in' => true],
            'vonage' => ['configurable' => true],
        ],
        'metadata' => [
            'label' => 'Account activity',
        ],
    ],
],

The channel identifier is part of the contract. For example, mail in the definition matches mail returned by via, while a custom channel uses its channel class name.

Send through several channels

Use Laravel's normal notification class when the same event belongs in more than one channel. Each channel is evaluated independently, so disabling Slack does not disable the email or database copy.

app/Notifications/AccountActivity.php
namespace App\Notifications;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\BroadcastMessage;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Messages\VonageMessage;
use Illuminate\Notifications\Notification;
use Illuminate\Notifications\Messages\SlackMessage;

final class AccountActivity extends Notification implements ShouldQueue
{
    use Queueable;

    public function __construct(
        private readonly string $action,
    ) {
    }

    public function via(object $notifiable): array
    {
        return ['mail', 'database', 'broadcast', 'slack', 'vonage'];
    }

    public function toMail(object $notifiable): MailMessage
    {
        return (new MailMessage)
            ->subject('Account activity')
            ->line("The {$this->action} action was completed.");
    }

    public function toDatabase(object $notifiable): array
    {
        return [
            'action' => $this->action,
            'occurred_at' => now()->toIso8601String(),
        ];
    }

    public function toBroadcast(object $notifiable): BroadcastMessage
    {
        return new BroadcastMessage([
            'action' => $this->action,
        ]);
    }

    public function toSlack(object $notifiable): SlackMessage
    {
        return (new SlackMessage)
            ->content("Account activity: {$this->action}");
    }

    public function toVonage(object $notifiable): VonageMessage
    {
        return (new VonageMessage)
            ->content("Account activity: {$this->action}");
    }
}

The queue behavior also remains Laravel's. NotificationCompass evaluates the channel when Laravel dispatches NotificationSending, including queued notifications.

Email and database only

For a notification that should stay inside the application and email inbox, keep the channel list small. This is useful for security alerts where the database record is part of the audit trail.

config/notificationcompass.php
'definitions' => [
    'security.alert' => [
        'notification_class' => App\Notifications\SecurityAlert::class,
        'channels' => ['mail', 'database'],
        'mandatory_channels' => ['mail'],
        'defaults' => [
            'mail' => true,
            'database' => true,
        ],
    ],
],
app/Notifications/SecurityAlert.php
public function via(object $notifiable): array
{
    return ['mail', 'database'];
}

public function toDatabase(object $notifiable): array
{
    return [
        'type' => 'security_alert',
        'message' => 'A new sign-in was detected.',
    ];
}

mandatory_channels keeps the email channel enabled and prevents users from changing it. Users can still manage the database channel unless you also mark it as mandatory.

Broadcast real-time updates

Use Laravel's broadcast notification channel when a frontend should react immediately. The frontend, broadcasting configuration, and private channel authorization remain Laravel responsibilities.

app/Notifications/BuildCompleted.php
use Illuminate\Notifications\Messages\BroadcastMessage;

public function via(object $notifiable): array
{
    return ['database', 'broadcast'];
}

public function toBroadcast(object $notifiable): BroadcastMessage
{
    return new BroadcastMessage([
        'build_id' => $this->buildId,
        'status' => 'completed',
    ]);
}

When broadcast is disabled, Laravel does not publish the event, but the database channel can still store it.

Slack and Vonage

External channels use the same pattern. Keep their Laravel channel configuration and routing methods in place, then add the identifiers to the NotificationCompass definition.

app/Models/User.php
public function routeNotificationForSlack(): string
{
    return $this->slack_webhook_url;
}

public function routeNotificationForVonage(): string
{
    return $this->phone_number;
}
app/Notifications/IncidentOpened.php
public function via(object $notifiable): array
{
    return ['slack', 'vonage'];
}

public function toSlack(object $notifiable): SlackMessage
{
    return (new SlackMessage)->content('A new incident was opened.');
}

public function toVonage(object $notifiable): VonageMessage
{
    return (new VonageMessage)->content('A new incident was opened.');
}

Mark these channels as opt-in when they should start disabled:

config/notificationcompass.php
'incident.opened' => [
    'notification_class' => App\Notifications\IncidentOpened::class,
    'channels' => ['slack', 'vonage'],
    'channel_options' => [
        'slack' => ['opt_in' => true],
        'vonage' => ['opt_in' => true],
    ],
],

The corresponding Laravel channel packages must still be installed and configured by the application. NotificationCompass does not provide transport credentials or channel implementations.

Use a custom channel

Custom channels use the channel value returned by via, usually the fully qualified channel class name. Register that same value in the definition.

app/Notifications/InvoiceReady.php
use App\Notifications\Channels\PortalChannel;

public function via(object $notifiable): array
{
    return [PortalChannel::class];
}
config/notificationcompass.php
'invoice.ready' => [
    'notification_class' => App\Notifications\InvoiceReady::class,
    'channels' => [App\Notifications\Channels\PortalChannel::class],
],

This lets the same preference resolver protect first-party and application-defined channels. If the channel value does not match, NotificationCompass returns a channel_unavailable decision and Laravel skips delivery.

Start by registering the channels your notification already returns from via. Add a channel to the definition only after the Laravel transport and its routing method are ready.