Skip to main content
Create your own
Lesson illustration

Listening for Broadcasted Events with Laravel Echo

Hello! Welcome to the next lesson in our journey to master real-time applications in Laravel.

In our previous session, we did all the heavy lifting on the backend. We defined events, configured them to be broadcast, and, most importantly, set up authorization rules to control access to private and presence channels. The server-side is now ready to send out real-time updates.

Today, we shift our focus entirely to the client-side. This lesson is all about the final piece of the puzzle: configuring Laravel Echo in your frontend JavaScript to subscribe to those channels and receive the events your backend is broadcasting.

By the end of this lesson, you will be able to configure Laravel Echo on the frontend to successfully listen for events broadcast from your Laravel application, bringing your real-time features to life in the browser.


1. What is Laravel Echo?

Before we configure it, let's clarify what Laravel Echo is.

Real-Time Event Broadcasting with Reverb in Laravel 11 : Your Complete Guide

First, let's get a concise definition of Laravel Echo and its role in the broadcasting ecosystem.

Watch this short clip from 06:47 to 07:10 for a clear explanation of what Laravel Echo is.

In short, Laravel Echo is a JavaScript library that provides a fluent, expressive API for subscribing to channels and listening for events. It acts as a wrapper around a lower-level WebSocket client. Since we're using Laravel Reverb, which uses the Pusher protocol, Echo will use the pusher-js library under the hood to manage the WebSocket connection. This saves you from writing complex connection management and subscription logic yourself.

2. Installation and Configuration

To listen for events, your frontend needs two things:

  1. The necessary NPM packages (laravel-echo and pusher-js).
  2. JavaScript code to initialize Echo with the correct connection details.

When you ran php artisan install:broadcasting in a previous lesson to set up Reverb, Laravel likely did this for you. Let's examine the pieces it put in place. If you ever need to set this up manually, the process is the same.

Broadcasting - Client Side Installation

The official Laravel documentation provides the authoritative source for client-side installation. We'll look at the manual setup instructions to understand exactly what's going on.

Read the section titled 'Client Side Installation', focusing specifically on the sub-section for 'Reverb'. Pay close attention to the 'Manual Installation' steps, which detail the required npm packages and the Echo initialization code in resources/js/bootstrap.js.

As you saw, the core of the configuration happens in resources/js/bootstrap.js. A new Echo instance is created and assigned to the global window object, making it accessible throughout your frontend code.

// resources/js/bootstrap.js

import Echo from 'laravel-echo';
import Pusher from 'pusher-js';

window.Pusher = Pusher;

window.Echo = new Echo({
    broadcaster: 'reverb',
    key: import.meta.env.VITE_REVERB_APP_KEY,
    wsHost: import.meta.env.VITE_REVERB_HOST,
    wsPort: import.meta.env.VITE_REVERB_PORT ?? 80,
    wssPort: import.meta.env.VITE_REVERB_PORT ?? 443,
    forceTLS: (import.meta.env.VITE_REVERB_SCHEME ?? 'httpss') === 'https',
    enabledTransports: ['ws', 'wss'],
});

This configuration tells Echo to connect to your Reverb server using the credentials you defined in your .env file. This bootstrap.js file is then typically imported into your main resources/js/app.js, which is compiled by Vite and included in your layout file via the @vite directive.


3. Listening for Events

With Echo installed and configured, you're ready to listen. The syntax is clean and mirrors the channel types we learned about.

Listening to Public Channels

Let's use the BlogPostPublished event from our previous lesson, which was broadcast on the public posts channel. To listen for it, you use Echo.channel() followed by listen().

Broadcasting - Receiving Broadcasts

The official documentation clearly lays out the syntax for listening to events. We'll focus on the primary methods.

Read the sub-section 'Listening for Events'. Focus on the code examples for Echo.channel().listen() and Echo.private().listen().

Here's how you would listen for our public BlogPostPublished event in a Blade template:

<!-- In any Blade file, e.g., resources/views/posts/index.blade.php -->

@extends('layouts.app')

@section('content')
    <!-- Your page content here -->
@endsection

@push('scripts')
<script type="module">
    // Listen for the 'BlogPostPublished' event on the 'posts' channel
    window.Echo.channel('posts')
        .listen('BlogPostPublished', (e) => {
            console.log('A new post was published!');
            console.log(e); // The 'e' object contains the event's public properties
        });
</script>
@endpush

Note: The window. prefix is used because we're accessing the global Echo instance. If you're working within a modern JS module where Echo is imported, you might use it directly.

Listening to Private Channels

Listening to private channels is nearly identical, but you use the Echo.private() method instead. This simple change tells Echo that it must first authenticate the user before subscribing.

Let's listen for the OrderStatusUpdated event from the previous lesson, which was broadcast on the private channel orders.{id}.

<!-- In a specific order view, e.g., resources/views/orders/show.blade.php -->

<script type="module">
    // The order ID is available from your controller, e.g., {{ $order->id }}
    const orderId = {{ $order->id }};

    window.Echo.private(`orders.${orderId}`)
        .listen('OrderStatusUpdated', (e) => {
            console.log('Order status was updated!');
            console.log(e.order);
        });
</script>

Behind the scenes, Echo automatically makes a request to /broadcasting/auth with the channel name. Your backend uses the authorization rule you defined in routes/channels.php to approve or deny the request. If approved, the subscription is confirmed, and your listen callback will fire when events arrive. If denied (e.g., the user is not logged in or doesn't own the order), the subscription fails silently, and the callback is never triggered.

This video demonstrates this entire flow beautifully, from the frontend code to the authentication process for a private channel.

Getting Started with Laravel Reverb

Watch this segment from the official Laravel channel to see a live demonstration of subscribing to a channel and the switch from public to private.

Watch the video from 04:41 to 05:25 to see the Echo.channel().listen() implementation. Then, jump to 07:50 to 09:32 to see how it's changed to Echo.private() and how the authentication flow is handled.


4. Verification and Debugging

How do you know if it's working? Your browser's developer tools are your best friend.

  1. Start your servers: Make sure your web server (php artisan serve), Vite dev server (npm run dev), and Reverb server (php artisan reverb:start) are all running.
  2. Open Developer Tools: Navigate to your page, open the developer tools, and go to the Network tab.
  3. Filter for "WS" (WebSockets): You should see an active WebSocket connection with a 101 Switching Protocols status.
  4. Inspect Messages: Click on the connection and view the Messages or Frames sub-tab. You will see JSON messages for subscription confirmations ("event":"pusher:subscription_succeeded") and incoming broadcast events.

This process is invaluable for debugging. This video clip gives a perfect walkthrough.

Getting Started with Laravel Reverb

This short clip demonstrates exactly where to look in your browser's developer tools to confirm your WebSocket connection is active and receiving messages.

Watch from 05:25 to 06:38. The presenter shows how to find the WebSocket connection in the Network tab and inspect the messages to confirm a successful channel subscription and see the event data arrive in real-time.


5. Advanced Listening Techniques

Echo offers more flexibility than just listening for the event's class name.

Custom Event Names with broadcastAs

Sometimes, you may want to decouple your frontend from your backend's PHP class names. You can define a custom broadcast name in your event class using the broadcastAs method.

// In your Event class, e.g., UserRegistered.php
public function broadcastAs(): string
{
    return 'user.created';
}

To listen for this custom name, you must prefix the event name with a dot (.) in your Echo listener. This tells Echo not to prepend the default App\Events namespace.

// On the frontend
window.Echo.channel('users')
    .listen('.user.created', (e) => { // Note the leading dot
        console.log('A user was created!', e);
    });

The following video demonstrates this feature clearly.

Real-Time Event Broadcasting with Reverb in Laravel 11 : Your Complete Guide

This video shows how to use the broadcastAs method on the backend and how to adjust the listen call on the frontend to match.

Watch from 40:15 to 41:12. This clip covers defining broadcastAs in the event class and then using .listen('.your-custom-name', ...) in the JavaScript.

Listening on Presence Channels

For presence channels (like a chat room), you use Echo.join() instead of private(). This method returns a PresenceChannel object, which has special events for tracking users.

Broadcasting - Joining Presence Channels

The official documentation provides a clear example of joining a presence channel and subscribing to its unique events.

Read the section 'Joining Presence Channels'. Focus on the Echo.join() method and the purpose of the here, joining, and leaving callbacks.

Here's a quick example:

window.Echo.join('chat.1')
    .here((users) => {
        // Runs when you first join. `users` is an array of everyone already here.
        console.log('Currently in room:', users);
    })
    .joining((user) => {
        // Runs when a new user joins the channel.
        console.log(user.name, 'has joined the room.');
    })
    .leaving((user) => {
        // Runs when a user leaves the channel.
        console.log(user.name, 'has left the room.');
    })
    .listen('NewChatMessage', (e) => {
        // You can still listen for regular events on a presence channel.
        console.log('New message:', e.message);
    });

Conclusion

Congratulations! You have now connected both ends of the real-time pipeline. You can broadcast events from your Laravel backend and receive them instantly in the browser using Laravel Echo.

Key Takeaways:

  • Laravel Echo is a JavaScript library that simplifies listening for broadcasted events.
  • The setup is handled in resources/js/bootstrap.js, where you instantiate Echo with your Reverb credentials.
  • Use Echo.channel('name') for public channels and Echo.private('name') for private channels.
  • The .listen('EventName', callback) method is used to receive events, and the callback function receives the event data.
  • Use Echo.join('name') for presence channels to access here, joining, and leaving events.
  • Always use your browser's developer tools (Network > WS tab) to verify your connection and debug issues.

Up Next:

So far, we've only been logging our received data to the console. In the next lesson, "Update a UI component dynamically in response to a received event," we'll take the final step. You'll learn how to use the data from the event callback to manipulate the DOM and provide your users with a truly dynamic, real-time experience without any page refreshes.

Can't find a good explanation? Sign up and we'll make it for you

Sign up