Notifications in a nutshell
Umbraco raises notifications before and after things happen: saving, publishing, deleting, moving, a member logging in, and many more.
- "…ing" notifications such as
ContentPublishingNotificationrun before the action, and can cancel it. - "…ed" notifications such as
ContentPublishedNotificationrun after it, and are perfect for side effects such as clearing a cache, calling an API or sending an email.
Step 1: React after publishing
using Umbraco.Cms.Core.Events;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Notifications;
namespace MySite.Notifications;
public class LogPublishedContentHandler(ILogger<LogPublishedContentHandler> logger)
: INotificationHandler<ContentPublishedNotification>
{
public void Handle(ContentPublishedNotification notification)
{
foreach (IContent item in notification.PublishedEntities)
{
logger.LogInformation("Published {Name} ({Key}) of type {Type}", item.Name, item.Key, item.ContentType.Alias);
}
}
}Step 2: Stop publishing when something's missing
using Umbraco.Cms.Core.Events;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Notifications;
namespace MySite.Notifications;
public class BlockEmptyTitleHandler : INotificationHandler<ContentPublishingNotification>
{
public void Handle(ContentPublishingNotification notification)
{
foreach (IContent item in notification.PublishedEntities)
{
if (item.HasProperty("title") && string.IsNullOrWhiteSpace(item.GetValue<string>("title")))
{
notification.CancelOperation(new EventMessage(
"Missing title", $"Add a title to \"{item.Name}\" before publishing.", EventMessageType.Error));
}
}
}
}The editor sees your message as an error, and the page isn't published.
Step 3: Register them with a composer
Umbraco finds composers automatically when the site starts:
using Umbraco.Cms.Core.Composing;
using Umbraco.Cms.Core.Notifications;
namespace MySite.Notifications;
public class NotificationsComposer : IComposer
{
public void Compose(IUmbracoBuilder builder)
{
builder.AddNotificationHandler<ContentPublishedNotification, LogPublishedContentHandler>();
builder.AddNotificationHandler<ContentPublishingNotification, BlockEmptyTitleHandler>();
}
}For handlers that call APIs or databases, implement INotificationAsyncHandler<T> and register it with AddNotificationAsyncHandler.
Rules of thumb
- Keep handlers fast. They run while the editor waits. For slow work, queue it and run it in the background.
- Don't publish or save inside a handler for the same event, or you'll trigger an infinite loop.
- Load balancing: handlers run on the server where the action happened. Use cache refresher notifications for things every server must do.
No code? Use webhooks
Umbraco has built-in webhooks under Settings › Webhooks. Choose an event such as Content Published, enter a URL, and Umbraco posts the details there. That's ideal for triggering a static site rebuild, or a Zapier or n8n workflow.
Need a hand?
umbraco.ninja has more than 20 years of Umbraco experience. If you'd rather not do this yourself, we'll set it up, test it and hand it over.
Get a fixed-price quote