Skip to content

Extending UmbSocial

UmbSocial publishes Umbraco notifications around its data and its publishing. A site can change or refuse posts and channels before they are saved, hide posts from reads, change what is sent to a network, and hear about every outcome, without changing UmbSocial itself.

Register handlers in a composer as usual:

MyComposer.cs
using UmbSocial.Core.Notifications;
using Umbraco.Cms.Core.Composing;
using Umbraco.Cms.Core.DependencyInjection;
using Umbraco.Extensions;
public class MyComposer : IComposer
{
public void Compose(IUmbracoBuilder builder)
{
builder.AddNotificationAsyncHandler<SocialPostSavingNotification, NoPostsAtWeekends>();
builder.AddNotificationAsyncHandler<SocialPostDispatchingNotification, AddCampaignTags>();
}
}
Data Before (change it, or cancel) After On read
Posts SocialPostSavingNotification (create and update), SocialPostDeletingNotification SocialPostSavedNotification, SocialPostDeletedNotification SocialPostsLoadedNotification
Channels SocialChannelSavingNotification (add and update), SocialChannelRemovingNotification SocialChannelSavedNotification, SocialChannelRemovedNotification
Publishing SocialPostDispatchingNotification (what is sent to one channel) SocialPostTargetPublishedNotification, SocialPostTargetFailedNotification

Each notification has its own page under Notifications.

Cancel a “…ing” notification with CancelOperation(...) and an Error or Warning event message. Nothing is saved, and the result carries the code <area>.cancelled:<your message>:

Notification Code when cancelled
SocialPostSavingNotification post.cancelled:<message>
SocialPostDeletingNotification post.cancelled:<message>
SocialChannelSavingNotification channel.cancelled:<message>
SocialChannelRemovingNotification channel.cancelled:<message>
SocialPostDispatchingNotification dispatch.cancelled:<message> (the target is Failed)

The message is the first error or warning message you added. notification.Cancel = true also cancels, with the message cancelled. In the management API the code comes back in the codes of the problem details (HTTP 400), except for a channel update or removal, where it comes back in the response’s warnings (see Management API).

NoPostsAtWeekends.cs
using UmbSocial.Core.Notifications;
using UmbSocial.Core.Posts;
using Umbraco.Cms.Core.Events;
public sealed class NoPostsAtWeekends : INotificationAsyncHandler<SocialPostSavingNotification>
{
public Task HandleAsync(SocialPostSavingNotification notification, CancellationToken cancellationToken)
{
if (notification.Target.When == When.At
&& notification.Target.AtUtc is { DayOfWeek: DayOfWeek.Saturday or DayOfWeek.Sunday })
{
notification.CancelOperation(new EventMessage("Social", "We don't post at weekends", EventMessageType.Error));
}
return Task.CompletedTask;
}
}

The result is post.cancelled:We don't post at weekends.

AddCampaignTags.cs
using UmbSocial.Core.Notifications;
using Umbraco.Cms.Core.Events;
public sealed class AddCampaignTags : INotificationAsyncHandler<SocialPostDispatchingNotification>
{
public Task HandleAsync(SocialPostDispatchingNotification notification, CancellationToken cancellationToken)
{
var post = notification.Target;
if (post.LinkUrl is { } link)
{
var separator = link.Contains('?') ? "&" : "?";
post.LinkUrl = $"{link}{separator}utm_source={Uri.EscapeDataString(post.Network)}&utm_medium=social";
}
return Task.CompletedTask;
}
}
  • Social’s own rules always run after your handlers, on what the handlers leave: validation, size caps, https-only links, the network limits, the edition’s channel allowance and history window. A handler can’t get around them. A handler that makes a post invalid gets the post refused with the usual codes.
  • Some checks run before the handlers, because there is nothing to hand them: an unknown post or channel, a sealed post, a post being sent (post.in_flight), a post with an Unknown target (post.outcome_unknown).
  • On update, Existing is the stored post or channel, for comparison. Changes made to it are ignored.
  • SocialPostsLoadedNotification changes what a read returns. It is never stored.
  • On SocialPostDispatchingNotification, links must stay absolute https URLs (dispatch.invalid_url otherwise, and nothing is sent). The text isn’t counted again, so keep it within the network’s limit, or the network refuses it.
  • A handler that throws fails the operation. UmbSocial doesn’t hide handler errors.
  • The publishing notifications run on the background server that sends posts, outside any request. Keep them quick: they run once per channel per post.

Register any Automate provider as a network with builder.AddSocialNetwork(...). See Custom networks.

ISocialMediaUrls (how a post’s image becomes a public URL) is registered so that a site’s own implementation wins. The main services (IPostService, IChannelService, IScheduleService) are public interfaces registered in Umbraco’s dependency injection, so your code can use them, and decorate or replace them. See Replacing services and Services.

Each channel publishes through an ordinary Automate automation, so you can add steps to it on the Automate canvas, such as an approval or a notification. See Automate integration for what to keep.