DEV Community

KIKOUNGA
KIKOUNGA

Posted on

How to Integrate OneSignal Push Notifications in Your Laravel App

Push notifications are essential for keeping users engaged with your app. Whether you're building a mobile app, web application, or both, OneSignal makes it easy to send notifications across platforms. In this guide, I'll show you how to integrate OneSignal into your Laravel application and start sending push notifications in minutes.

What You'll Learn

By the end of this tutorial, you'll know how to:

  • Set up OneSignal in your Laravel application
  • Send notifications to specific users
  • Target user segments and groups
  • Add images and action buttons to notifications
  • Handle notification events
  • Use Laravel's notification system with OneSignal

Prerequisites

Before we start, make sure you have:

  • A Laravel 11 or 12 application
  • PHP 8.3 or higher
  • A OneSignal account (free tier works fine)
  • Your OneSignal App ID and REST API Key

Step 1: Install the Package

First, install the OneSignal package via Composer:

composer require lepresk/laravel-onesignal
Enter fullscreen mode Exit fullscreen mode

The package will auto-register with Laravel, so no need to manually add the service provider.

Step 2: Configure Your Credentials

Publish the configuration file:

php artisan vendor:publish --tag=onesignal-config
Enter fullscreen mode Exit fullscreen mode

Add your OneSignal credentials to your .env file:

ONESIGNAL_APP_ID=your-app-id-here
ONESIGNAL_REST_API_KEY=your-rest-api-key-here
ONESIGNAL_ANDROID_CHANNEL_ID=your-android-channel-id
Enter fullscreen mode Exit fullscreen mode

Getting Your OneSignal API Credentials

If this is your first time with OneSignal, here's how to get your credentials:

  1. Go to onesignal.com and create a free account
  2. Click New App/Website and follow the setup wizard
  3. Once your app is created, go to Settings in the left sidebar
  4. Click on Keys & IDs
  5. Copy your App ID and REST API Key

For the Android Channel ID:

  1. In your OneSignal dashboard, go to Settings → Platforms
  2. Under Android, you'll find your Firebase Server Key section
  3. The channel ID is typically something you define in your Android app (e.g., "default_channel")
  4. If you're only using iOS or web, you can leave this empty

Step 3: Send Your First Notification

Let's send a simple notification to test everything works:

use Lepresk\LaravelOnesignal\Facades\OneSignal;
use Lepresk\LaravelOnesignal\PushMessage;

$message = (new PushMessage())
    ->withTitle('Hello World')
    ->withBody('This is my first push notification!')
    ->toExternalUserIds([123]); // Your user's ID

$response = OneSignal::send($message);

if ($response->isSuccessful()) {
    echo "Notification sent successfully!";
    echo "Notification ID: " . $response->getNotificationId();
    echo "Recipients: " . $response->getRecipients();
}
Enter fullscreen mode Exit fullscreen mode

Understanding External User IDs

External User IDs are identifiers you assign to your users in OneSignal. They map your application's user IDs to OneSignal's internal player IDs. This way, you can send notifications to users using your own database IDs without tracking OneSignal's player IDs.

To set up external user IDs, you'll need to configure them in your mobile app or web SDK when users log in.

Step 4: Targeting Different Audiences

Send to Specific Users

// Single user
$message->toUser(123);

// Multiple users
$message->toExternalUserIds([1, 2, 3, 4, 5]);
Enter fullscreen mode Exit fullscreen mode

Send to Segments

Segments are groups of users you define in your OneSignal dashboard based on criteria like location, language, or custom tags.

// Send to a custom segment
$message->toSegment('Premium Users');

// Send to multiple segments
$message->toSegments(['Premium Users', 'Active Users']);

// Built-in segments
$message->toSubscribedSegment();  // All subscribed users
$message->toActiveSegment();       // Active users
$message->toInactiveSegment();     // Inactive users
Enter fullscreen mode Exit fullscreen mode

Send Based on Tags

Tags are key-value pairs you set on user devices for custom targeting:

$message->toTag('subscription_level', 'premium');
$message->toTag('age_group', '18-25');
$message->toTag('interests', 'technology', '=');
Enter fullscreen mode Exit fullscreen mode

Step 5: Enhance Your Notifications

Add Images

Make your notifications stand out with images:

$message = (new PushMessage())
    ->withTitle('New Product Launch!')
    ->withBody('Check out our latest features')
    ->withImage('https://yourapp.com/images/product-launch.jpg')
    ->toSegment('All Users');
Enter fullscreen mode Exit fullscreen mode

Add Action Buttons

Action buttons let users take immediate action from the notification:

$message = (new PushMessage())
    ->withTitle('Flash Sale!')
    ->withBody('50% off - 2 hours only')
    ->addButton('shop', 'Shop Now', 'https://yourapp.com/sale')
    ->addButton('remind', 'Remind Me Later')
    ->toSegment('Active Users');
Enter fullscreen mode Exit fullscreen mode

The third parameter (URL) is optional. If provided, clicking the button will open that URL.

Multi-language Support

Send notifications in multiple languages:

$message = (new PushMessage())
    ->withTitle('Welcome!', 'en')
    ->withTitle('Bienvenue!', 'fr')
    ->withTitle('¡Bienvenido!', 'es')
    ->withBody('Thanks for joining our app', 'en')
    ->withBody('Merci de rejoindre notre application', 'fr')
    ->withBody('Gracias por unirte a nuestra aplicación', 'es')
    ->toSubscribedSegment();
Enter fullscreen mode Exit fullscreen mode

Set Priority

Control how quickly users receive notifications:

// High priority (immediate delivery)
$message->withHightPriority();

// Normal priority
$message->withDefaultPriority();
Enter fullscreen mode Exit fullscreen mode

Custom Data

Attach custom data to your notifications for handling in your app:

$message = (new PushMessage())
    ->withTitle('New Message')
    ->withBody('You have a new message from John')
    ->addData('type', 'chat')
    ->addData('chat_id', 456)
    ->addData('sender_id', 789)
    ->toUser($userId);
Enter fullscreen mode Exit fullscreen mode

Step 6: Using Laravel's Notification System

For a more Laravel-native approach, integrate with Laravel's notification system:

Create a Notification

php artisan make:notification OrderShipped
Enter fullscreen mode Exit fullscreen mode

Configure the Notification

<?php

namespace App\Notifications;

use Illuminate\Notifications\Notification;
use Lepresk\LaravelOnesignal\PushMessage;

class OrderShipped extends Notification
{
    public function __construct(
        private int $orderId,
        private string $trackingNumber
    ) {}

    public function via($notifiable): array
    {
        return ['push'];
    }

    public function toPush($notifiable): PushMessage
    {
        return (new PushMessage())
            ->withTitle('Order Shipped!')
            ->withBody("Your order #{$this->orderId} is on its way")
            ->addData('order_id', $this->orderId)
            ->addData('tracking_number', $this->trackingNumber)
            ->addButton('track', 'Track Order', "https://yourapp.com/orders/{$this->orderId}")
            ->toUser($notifiable->onesignal_id); // Assuming you store OneSignal user ID in this field
    }
}
Enter fullscreen mode Exit fullscreen mode

Send the Notification

$user = User::find(1);
$user->notify(new OrderShipped($orderId, $trackingNumber));
Enter fullscreen mode Exit fullscreen mode

Step 7: Handle Notification Events

Monitor what happens with your notifications by listening to events:

// In your EventServiceProvider
use Lepresk\LaravelOnesignal\Events\NotificationSending;
use Lepresk\LaravelOnesignal\Events\NotificationSent;
use Lepresk\LaravelOnesignal\Events\NotificationFailed;

protected $listen = [
    NotificationSending::class => [
        LogNotificationAttempt::class,
    ],
    NotificationSent::class => [
        LogNotificationSuccess::class,
    ],
    NotificationFailed::class => [
        HandleNotificationFailure::class,
    ],
];
Enter fullscreen mode Exit fullscreen mode

Example Event Listener

<?php

namespace App\Listeners;

use Lepresk\LaravelOnesignal\Events\NotificationSent;
use Illuminate\Support\Facades\Log;

class LogNotificationSuccess
{
    public function handle(NotificationSent $event): void
    {
        Log::info('Push notification sent', [
            'notification_id' => $event->response->getNotificationId(),
            'recipients' => $event->response->getRecipients(),
        ]);

        // Update your analytics, database, etc.
    }
}
Enter fullscreen mode Exit fullscreen mode

Step 8: Advanced Configuration

The package offers several configuration options in config/onesignal.php:

Set Default TTL (Time to Live)

Control how long OneSignal attempts to deliver notifications:

'defaults' => [
    'ttl' => env('ONESIGNAL_DEFAULT_TTL', 604800), // 7 days
],
Enter fullscreen mode Exit fullscreen mode

Configure Logging

'logging' => [
    'enabled' => true,
    'channel' => 'stack', // Use a specific log channel
    'level' => 'info',
],
Enter fullscreen mode Exit fullscreen mode

Exception Handling

'throw_exceptions' => true, // Throw exceptions on failures
Enter fullscreen mode Exit fullscreen mode

If set to false, failures will be logged but won't throw exceptions.

Real-World Examples

Welcome New Users

$message = (new PushMessage())
    ->withTitle('Welcome to MyApp!')
    ->withBody('We\'re excited to have you here')
    ->withImage('https://myapp.com/welcome-banner.jpg')
    ->addButton('start', 'Get Started', 'https://myapp.com/onboarding')
    ->toUser($newUser->id);

OneSignal::send($message);
Enter fullscreen mode Exit fullscreen mode

Cart Abandonment Reminder

$message = (new PushMessage())
    ->withTitle('Don\'t Forget Your Cart!')
    ->withBody('You left some items behind. Complete your order now.')
    ->addData('cart_id', $cart->id)
    ->addButton('checkout', 'Complete Purchase', 'https://myapp.com/checkout')
    ->setTTL(86400) // 24 hours
    ->toUser($user->id);

OneSignal::send($message);
Enter fullscreen mode Exit fullscreen mode

Daily Digest for Active Users

$message = (new PushMessage())
    ->withTitle('Your Daily Digest')
    ->withBody('See what\'s new today')
    ->withImage('https://myapp.com/digest-banner.jpg')
    ->addButton('view', 'View Digest', 'https://myapp.com/digest')
    ->toActiveSegment()
    ->withDefaultPriority();

OneSignal::send($message);
Enter fullscreen mode Exit fullscreen mode

Troubleshooting

Notification Not Received

  1. Verify your OneSignal credentials are correct
  2. Check that the user has a valid OneSignal player ID
  3. Ensure the user has granted notification permissions
  4. Check OneSignal dashboard for delivery status

Testing in Development

Use OneSignal's test mode and send to your own device first:

$message = (new PushMessage())
    ->withTitle('Test Notification')
    ->withBody('Testing push notifications')
    ->toUser($yourTestUserId);

$response = OneSignal::send($message);
dd($response->getRawResponse()); // See the full response
Enter fullscreen mode Exit fullscreen mode

Common Pitfalls to Avoid

Sending too many notifications
I learned this the hard way. Users will disable notifications if you spam them. Be selective about what deserves a push notification.

Not testing on real devices
The OneSignal dashboard shows if a notification was sent, but only testing on actual devices tells you if it looks good and works properly.

Forgetting about timezones
Sending a promotion at 3 AM local time is not great. Use intelligent delivery or schedule based on user timezones.

Generic messages
"You have a new notification" tells users nothing. Be specific about what happened and why they should care.

Wrapping Up

That's it. You now have OneSignal working in your Laravel app with a clean, maintainable integration. The examples I showed cover most use cases, but there's more in the documentation if you need advanced features like delayed sending or custom notification sounds.

The package is open source, so if you run into issues or want to add features, contributions are welcome on GitHub.

Links:

If you found this helpful or have questions, leave a comment. I'm usually pretty quick to respond.

Top comments (0)