<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Serhii Andriichuk</title>
    <description>The latest articles on DEV Community by Serhii Andriichuk (@andriichuk).</description>
    <link>https://dev.to/andriichuk</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F229661%2F40aa9a38-84ed-4ee2-bb33-cd968abbf0fc.jpeg</url>
      <title>DEV Community: Serhii Andriichuk</title>
      <link>https://dev.to/andriichuk</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/andriichuk"/>
    <language>en</language>
    <item>
      <title>Debug and Test Laravel FCM Push Notifications with Pushbox</title>
      <dc:creator>Serhii Andriichuk</dc:creator>
      <pubDate>Tue, 03 Nov 2026 18:58:06 +0000</pubDate>
      <link>https://dev.to/andriichuk/debug-and-test-laravel-fcm-push-notifications-with-pushbox-4995</link>
      <guid>https://dev.to/andriichuk/debug-and-test-laravel-fcm-push-notifications-with-pushbox-4995</guid>
      <description>&lt;p&gt;You create a push notification in Laravel, send it through Firebase Cloud Messaging (FCM), and... nothing appears on your phone.&lt;/p&gt;

&lt;p&gt;What went wrong?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is the notification payload correct?&lt;/li&gt;
&lt;li&gt;Is Firebase configured properly?&lt;/li&gt;
&lt;li&gt;Is the device token valid?&lt;/li&gt;
&lt;li&gt;Did FCM accept the message?&lt;/li&gt;
&lt;li&gt;Is the problem with the notification content or delivery?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Debugging these issues can take time, especially when you need to change code, trigger the notification again, and check the result.&lt;/p&gt;

&lt;p&gt;I built &lt;strong&gt;Pushbox&lt;/strong&gt;, an open-source Laravel package that helps you test FCM sending and preview push notifications from a visual interface.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Pushbox?
&lt;/h2&gt;

&lt;p&gt;Pushbox is a notification testing and debugging tool for Laravel.&lt;/p&gt;

&lt;p&gt;Its two main features are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Test sending&lt;/strong&gt; — send a notification directly to a real device through FCM and check the sending result.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Notification preview&lt;/strong&gt; — inspect the generated notification content and FCM data payload without sending anything.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It also supports notification variants, translations, and different recipients.&lt;/p&gt;

&lt;p&gt;The screenshots use an order-shipped notification from a demo store. The setup below uses &lt;code&gt;WelcomePush&lt;/code&gt; to keep the code example small.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ft0p4egjx1z79c4fq5m6r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ft0p4egjx1z79c4fq5m6r.png" alt="Pushbox workspace with notification content, data payload, and an expanded Android preview" width="800" height="613"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Install Pushbox
&lt;/h2&gt;

&lt;p&gt;Pushbox supports Laravel 12/13 and PHP 8.4/8.5.&lt;/p&gt;

&lt;p&gt;Install the package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require andriichuk/pushbox
php artisan pushbox:install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For FCM support, install the Laravel notification channel:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require laravel-notification-channels/fcm:^6.2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open &lt;code&gt;/pushbox&lt;/code&gt; in your browser.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Register a notification
&lt;/h2&gt;

&lt;p&gt;Let's create a simple FCM notification.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan make:notification WelcomePush
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Notifications\Notification&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;NotificationChannels\Fcm\FcmChannel&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;NotificationChannels\Fcm\FcmMessage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;NotificationChannels\Fcm\Resources\Notification&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nc"&gt;FcmNotification&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;WelcomePush&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Notification&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;via&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="nv"&gt;$notifiable&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;array&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;FcmChannel&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;toFcm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="nv"&gt;$notifiable&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;FcmMessage&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FcmMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FcmNotification&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'Welcome!'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'Hello '&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$notifiable&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="s1"&gt;'developer'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="s1"&gt;'!'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="s1"&gt;'screen'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'welcome'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now register it in &lt;code&gt;routes/pushbox.php&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Notifications\WelcomePush&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Andriichuk\Pushbox\Facades\Pushbox&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nc"&gt;Pushbox&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;WelcomePush&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your notification is now available in Pushbox.&lt;/p&gt;

&lt;p&gt;You can select it from the interface, inspect its content, and test sending it.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Send a test push notification to your device
&lt;/h2&gt;

&lt;p&gt;This is especially useful when your notification is not arriving and you want to check whether the FCM sending request works.&lt;/p&gt;

&lt;p&gt;First, configure Firebase credentials using the &lt;a href="https://github.com/laravel-notification-channels/fcm" rel="noopener noreferrer"&gt;Laravel FCM notification channel&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Enable test sending in your &lt;code&gt;.env&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PUSHBOX_ALLOW_SEND=true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can optionally configure a default device token:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PUSHBOX_FCM_TOKEN=your-device-token
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or enter your FCM token directly in the Pushbox interface under &lt;strong&gt;Device settings&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Make sure the token belongs to the same Firebase project as your credentials.&lt;/p&gt;

&lt;p&gt;For the failure example below, I’m deliberately using an invalid demo token. Use your own device’s FCM token when testing delivery.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fiiyl8o92wi3zd5feeqre.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fiiyl8o92wi3zd5feeqre.png" alt="Device settings with an intentionally invalid demo token for reproducing a send failure" width="800" height="680"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open &lt;code&gt;/pushbox&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Select your notification.&lt;/li&gt;
&lt;li&gt;Check the generated payload.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Send notification&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Check the sending result and your device.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Pushbox sends the notification immediately through FCM.&lt;/p&gt;

&lt;p&gt;The result can be:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Accepted&lt;/td&gt;
&lt;td&gt;FCM accepted the sending request&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Failed&lt;/td&gt;
&lt;td&gt;The sending request failed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Skipped&lt;/td&gt;
&lt;td&gt;The notification wasn't sent&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fw9pp085zpzoqv8mcusk8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fw9pp085zpzoqv8mcusk8.png" alt="Pushbox reports that Firebase accepted the send request" width="798" height="164"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; An accepted result does not guarantee that the notification was delivered or displayed on the device.&lt;/p&gt;

&lt;p&gt;But it helps narrow down the problem.&lt;/p&gt;

&lt;p&gt;If sending fails, you can investigate your Firebase configuration, credentials, device token, or message. If FCM accepts the request but nothing appears on the phone, you'll need to investigate device-side delivery and handling.&lt;/p&gt;

&lt;h3&gt;
  
  
  Inspect a failed send
&lt;/h3&gt;

&lt;p&gt;Here’s Firebase rejecting the invalid demo token. Pushbox displays the failure in the workspace and provides a shortcut back to &lt;strong&gt;Device settings&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq11rsqlqua5cxltn63q7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq11rsqlqua5cxltn63q7.png" alt="Pushbox explains that Firebase rejected the device token" width="800" height="198"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Expand &lt;strong&gt;Technical details&lt;/strong&gt; to inspect the status, masked target, notification class, FCM channel, and the provider’s error response. Here, Firebase reports that the registration token is invalid.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9jplskhhlh93ls03z425.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9jplskhhlh93ls03z425.png" alt="Expanded technical details showing the masked target and real Firebase invalid-registration-token error" width="800" height="662"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can test the notification without triggering the normal application flow every time.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Preview the notification payload before sending
&lt;/h2&gt;

&lt;p&gt;Sometimes the problem isn't Firebase.&lt;/p&gt;

&lt;p&gt;The notification itself may contain an incorrect title, body, translation, or data payload.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;toFcm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="nv"&gt;$notifiable&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;FcmMessage&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FcmMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FcmNotification&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'Your order is ready'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'Order #1234 is ready for pickup.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'screen'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'orders'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'order_id'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'1234'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pushbox lets you inspect the generated notification and its data fields before sending it.&lt;/p&gt;

&lt;p&gt;You can check:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Notification title and body&lt;/li&gt;
&lt;li&gt;FCM data payload&lt;/li&gt;
&lt;li&gt;Values generated for a specific recipient&lt;/li&gt;
&lt;li&gt;Different notification variants&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Expand &lt;strong&gt;Raw payload&lt;/strong&gt; to inspect the serialized FCM message. &lt;strong&gt;Platform settings&lt;/strong&gt; shows values such as Android’s time to live.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2dq1otd3ir9xsncemydm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2dq1otd3ir9xsncemydm.png" alt="The raw FCM JSON, custom data fields, and Android time-to-live setting in Pushbox" width="800" height="1178"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is useful when debugging notifications that open the wrong screen, display incorrect text, or contain missing data.&lt;/p&gt;

&lt;p&gt;You don't need a physical device just to inspect the payload.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Test notifications with different recipients
&lt;/h2&gt;

&lt;p&gt;Notification content often depends on the user.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'Hello '&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$notifiable&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="s1"&gt;'developer'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="s1"&gt;'!'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To preview a notification with a specific recipient:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Models\User&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Notifications\WelcomePush&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Andriichuk\Pushbox\Facades\Pushbox&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nc"&gt;Pushbox&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;factory&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
        &lt;span class="s1"&gt;'name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Ada'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;WelcomePush&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can inspect the notification generated for Ada.&lt;/p&gt;

&lt;p&gt;Using &lt;code&gt;factory()-&amp;gt;make()&lt;/code&gt; avoids creating an actual user record.&lt;/p&gt;

&lt;p&gt;This makes it easier to reproduce different notification scenarios during development.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Compare notification variants
&lt;/h2&gt;

&lt;p&gt;Sometimes you need to test multiple versions of a notification.&lt;/p&gt;

&lt;p&gt;Pushbox lets you organize notifications into categories and register named variants.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;Pushbox&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;factory&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Ada'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;category&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Onboarding'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Pushbox&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;WelcomePush&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="s1"&gt;'Another greeting'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;WelcomePush&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WelcomePush&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This example registers a named variant. You can return a differently configured notification instance to compare actual content changes.&lt;/p&gt;

&lt;p&gt;It's useful when working with different notification messages or testing alternative payloads.&lt;/p&gt;

&lt;p&gt;In the demo, the &lt;strong&gt;Long order reference&lt;/strong&gt; variant provides a longer title and body to check text wrapping.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F30homf7wrknonacub5nh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F30homf7wrknonacub5nh.png" alt="The long-order-reference variant with its expanded Android notification preview" width="800" height="1044"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Check collapsed and expanded previews
&lt;/h3&gt;

&lt;p&gt;Switch between &lt;strong&gt;Collapsed&lt;/strong&gt; and &lt;strong&gt;Expanded&lt;/strong&gt; to check how much text fits. Long titles and bodies can be truncated in the collapsed preview. The Android preview is an approximation; actual rendering depends on the device and client app.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffj2zmlhqr92cjssmlfv5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffj2zmlhqr92cjssmlfv5.png" alt="The collapsed Android preview truncates the long notification title and body" width="800" height="1453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Preview notifications in different languages
&lt;/h2&gt;

&lt;p&gt;If your application supports multiple languages, you probably need to check how push notifications look for each locale.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;FcmNotification&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'notifications.welcome_title'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'notifications.welcome_body'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pushbox supports a locale selector.&lt;/p&gt;

&lt;p&gt;Publish the configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan vendor:publish &lt;span class="nt"&gt;--tag&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;pushbox-config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Configure available languages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// config/pushbox.php&lt;/span&gt;

&lt;span class="s1"&gt;'locales'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s1"&gt;'en'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'English'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'uk'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Ukrainian'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can switch between languages in the interface and inspect the generated notification.&lt;/p&gt;

&lt;p&gt;This helps catch missing or incorrect translations before sending them to users.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Restrict access
&lt;/h2&gt;

&lt;p&gt;Pushbox is a developer tool, so don't leave it publicly accessible.&lt;/p&gt;

&lt;p&gt;You can disable it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PUSHBOX_ENABLED=false
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or protect it using a Laravel Gate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Support\Facades\Gate&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nc"&gt;Gate&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;define&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'viewPushbox'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;?User&lt;/span&gt; &lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$user&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
        &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;can&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'use-developer-tools'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pushbox also supports middleware and IP allowlists.&lt;/p&gt;

&lt;p&gt;Configure access restrictions before using it in a publicly accessible environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;Debugging push notifications shouldn't require repeatedly triggering your application's normal notification flow just to check a payload or test FCM sending.&lt;/p&gt;

&lt;p&gt;With Pushbox, you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Send test notifications directly to a real device.&lt;/li&gt;
&lt;li&gt;Check whether FCM accepted or rejected a sending request.&lt;/li&gt;
&lt;li&gt;Preview notification content and payloads before sending.&lt;/li&gt;
&lt;li&gt;Test different recipients, variants, and translations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's not a replacement for Firebase delivery diagnostics, but it makes the Laravel side of push notification debugging easier.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/andriichuk/pushbox" rel="noopener noreferrer"&gt;https://github.com/andriichuk/pushbox&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pushbox is open-source and MIT-licensed.&lt;/p&gt;

&lt;p&gt;I'd love to hear how other Laravel developers debug push notification issues.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do you currently test FCM sending and inspect notification payloads in your projects?&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>debugging</category>
      <category>laravel</category>
      <category>php</category>
      <category>testing</category>
    </item>
  </channel>
</rss>
