Get insights into all your Laravel notifications with Paragraphs new package

Last updated on by

Get insights into all your Laravel notifications with Paragraphs new package image

When Laravel introduced Notification classes back in 2016, it allowed all of us to begin sending any transactional communications to our customers in a very simple, intuitive way. Chances are, by now you got tens of Notification classes in your product and you are sending hundreds or thousands of emails and text messages every single day.

Wouldn’t it be nice to have a better control over it? Let’s say, after a client comes to the customer support, I want to be able to see what exactly did I send to him or her in the last 30 days. What did the notification say – was it accurate information in it or did we cause confusion? How many notifications are we sending every day? Which notification type costs us the most money? Do all notifications look great on phones? Do we have typos, do we have stylistic inconsistencies?

How is notification X triggered? How often do our users open notification Y? Maybe we should just remove it?

And so on.

The point is – the notifications are an important part of our product, it’s how we tell our customers what just happened and what to do or expect next, and so it could be very, very helpful to start managing them better. This would allow us to increase customer satisfaction and decrease our costs.

A new package that helps

Good news is that a tool like that is already available – we at Paragraph just released a Laravel composer package. In just a few seconds you could get way more visibility over your outgoing communications.

The installation is as simple as installing one composer package:

$ composer require paragraph/laravel-notifications

That’s it! The package auto-registered itself and is now hooked into the notification rendering process. If you send any notifications in your Laravel app, you should be able to see new little files popping up in the storage/app/comms folder.

Now that the data is being collected, we have to send it to Paragraph dashboard from time to time, ideally as a scheduled cron command. To do that we need to provide API credentials in the environment file (or the real OS environment):

# Anywhere in your .env file
PARAGRAPH_PROJECT_ID=XXX
PARAGRAPH_API_KEY=YYY

To get your API key and project ID, just create a project on Paragraph which really only takes a minute or less: https://paragraph.ph/repos/import

You can now run a console command that will submit the history and remove any temporary files:

$ php artisan paragraph:submit

Voila, we can see the notification history in Paragraph dashboard now:

The data includes notification channels used, recipient ID (which can be and should be anonymised), current status (if available through an integration) and preview button.

But this is just the start, of course.

Notification triggers

If you click on any notification type in the first column, you will get to a page that has some advanced information about this notification class including its triggers:

Our package automatically discovers the notification journey – when and how it’s triggered, so that you can make sure that everything is working according to the design.

In this example above, we can see that the notification was sent from a listener that was triggered by an event that was fired in a web controller, and therefore the root cause was an action that user took on your website.

Open rate and cost analysis

One the very same page you can see some stats about this specific notification type – how many times it was sent during the given period, the open rate (coming back from an integration, eg. Mailgun API) and total cost spent.

This can allow you to quickly identify transactional emails or text messages that cost company a lot but potentially don’t even get opened often.

Copy review and updates

If you click “View” you can see a rendered HTML of the email that was sent, a full copy of the SMS message and so on:

Click “View in GitHub” to quickly jump to the file containing this text in GitHub and make some easy text updates.

As a bonus, we will also check the copy for any grammar errors and typos and we will display anything we found on the Notification class page.

Localization? Trivial!

Need to translate your notifications into different languages? Oh, too easy! You can use Paragraph’s localization package to automatically submit all your texts to online marketplaces like Gengo and then apply the translations received, no manual work involved.

You can do this using a helper function:

public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)
->line(text('The introduction to the notification.'))
->line(text('Thank you for using our application!'));
}

Or a Blade component:

<p>
<x-text comment="This paragraph explains how Paragraph can help localize an app">
Need to translate your notifications into different languages? Oh, too easy!
You can use Paragraph’s localization package to automatically submit all
your texts to online marketplaces like Gengo and then apply the
translations received, no manual work involved.
</x-text>
</p>

Performance impact

You might be wondering what’s the impact on your application performance. After all, we are running some extra code every time there is a notification being sent and there could be thousands or millions of notifications delivered every day.

Our code running time on average is 1ms (millisecond) or less, and the sync component of it tries to do as little as possible to make sure the impact is minimum. The hook saves a rendered snapshot to a temporary file and stops right there – any API calls will be made separately at a later stage, asynchronously.

Snapshot files are compressed with Zip to ensure there is a minimum footprint in terms of hard disk usage, and our code actually runs AFTER the notification is already sent. Moreover, it’s wrapped in the try-catch clause so that any Throwable is caught and your code can proceed as if nothing happened:

try {
$html = $message->getSymfonySentMessage()->getOriginalMessage()->getHtmlBody();
 
$this->save(
$html,
get_class($notification)
);
} catch (\Throwable $e) {
}

Therefore, using this package is very safe from both performance and customer experience perspectives.

Join for free now

Sounds interesting? Then go to Paragraph, import a project https://paragraph.ph/repos/import and you can make your product notifications better, your customers happier and your balance sheet lighter. Joining is absolutely free this month as a part of the public beta launch!

Eric L. Barnes photo

Eric is the creator of Laravel News and has been covering Laravel since 2012.

Filed in:
Cube

Laravel Newsletter

Join 40k+ other developers and never miss out on new tips, tutorials, and more.

image
Paragraph

Manage your Laravel app as if it was a CMS – edit any text on any page or in any email without touching Blade or language files.

Visit Paragraph
Laravel Forge logo

Laravel Forge

Easily create and manage your servers and deploy your Laravel applications in seconds.

Laravel Forge
Tinkerwell logo

Tinkerwell

The must-have code runner for Laravel developers. Tinker with AI, autocompletion and instant feedback on local and production environments.

Tinkerwell
No Compromises logo

No Compromises

Joel and Aaron, the two seasoned devs from the No Compromises podcast, are now available to hire for your Laravel project. ⬧ Flat rate of $7500/mo. ⬧ No lengthy sales process. ⬧ No contracts. ⬧ 100% money back guarantee.

No Compromises
Kirschbaum logo

Kirschbaum

Providing innovation and stability to ensure your web application succeeds.

Kirschbaum
Shift logo

Shift

Running an old Laravel version? Instant, automated Laravel upgrades and code modernization to keep your applications fresh.

Shift
Bacancy logo

Bacancy

Supercharge your project with a seasoned Laravel developer with 4-6 years of experience for just $2500/month. Get 160 hours of dedicated expertise & a risk-free 15-day trial. Schedule a call now!

Bacancy
Lucky Media logo

Lucky Media

Bespoke software solutions built for your business. We ♥ Laravel

Lucky Media
Lunar: Laravel E-Commerce logo

Lunar: Laravel E-Commerce

E-Commerce for Laravel. An open-source package that brings the power of modern headless e-commerce functionality to Laravel.

Lunar: Laravel E-Commerce
LaraJobs logo

LaraJobs

The official Laravel job board

LaraJobs
Larafast: Laravel SaaS Starter Kit logo

Larafast: Laravel SaaS Starter Kit

Larafast is a Laravel SaaS Starter Kit with ready-to-go features for Payments, Auth, Admin, Blog, SEO, and beautiful themes. Available with VILT and TALL stacks.

Larafast: Laravel SaaS Starter Kit
SaaSykit: Laravel SaaS Starter Kit logo

SaaSykit: Laravel SaaS Starter Kit

SaaSykit is a Laravel SaaS Starter Kit that comes with all features required to run a modern SaaS. Payments, Beautiful Checkout, Admin Panel, User dashboard, Auth, Ready Components, Stats, Blog, Docs and more.

SaaSykit: Laravel SaaS Starter Kit
Rector logo

Rector

Your partner for seamless Laravel upgrades, cutting costs, and accelerating innovation for successful companies

Rector

The latest

View all →
DirectoryTree Authorization is a Native Role and Permission Management Package for Laravel image

DirectoryTree Authorization is a Native Role and Permission Management Package for Laravel

Read article
Sort Elements with the Alpine.js Sort Plugin image

Sort Elements with the Alpine.js Sort Plugin

Read article
Anonymous Event Broadcasting in Laravel 11.5 image

Anonymous Event Broadcasting in Laravel 11.5

Read article
Microsoft Clarity Integration for Laravel image

Microsoft Clarity Integration for Laravel

Read article
Apply Dynamic Filters to Eloquent Models with the Filterable Package image

Apply Dynamic Filters to Eloquent Models with the Filterable Package

Read article
Property Hooks Get Closer to Becoming a Reality in PHP 8.4 image

Property Hooks Get Closer to Becoming a Reality in PHP 8.4

Read article