Sitecore.Social – Auto-posting to social media on publish

Using the built-in Social Connected module in Sitecore, when new content is published, you can configure messages to go out to a myriad of social networks like Twitter, Facebook, etc… to promote this new content.

wow

I know, right?

How About Some Background?

From Content Editor, with your new content item selected, select the Publish tab, then click on the Messages button in the Social chunk.

Social button

This will open a dialog for you to configure your message for each social channel.  (You can also access this from Experience Editor.  While on your new page in EE, the Social chunk is available from the Home tab.)

NOTE: If you get a message stating that no social applications have been configured, go through this document on doc.sitecore.net to setup your Social Connector.

select-a-network

Select the network you want to configure.  In this example, we’ll select Twitter, but you are by no means limited to the networks pre-configured!

configure-a-network.png

In this dialog, you can configure the following for your message:

  • The message you want communicated to your social network
  • The link inserted into your social message
  • A marketing campaign associated with the promotion
  • The account to use for this particular social network
  • Whether or not this message should be posted automatically, once published

That last option is the subject of this post…

post-automatically.png

Getting to the Point – (a.k.a TL;DR;)

My understanding of this feature, and until a few days ago, I had found no documentation refuting this perception, was that, with this option selected, the configured message would post to the social network immediately after the content was posted.

Well, after quite a bit of time debugging and decompiling assemblies, I found that this was NOT TRUE.

If you look at the publish:itemProcessed event:

<event name="publish:itemProcessed" patch:source="Sitecore.Social.config">
   <handler type="Sitecore.Social.Client.MessagePosting.Handlers.ItemPublishedHandler, Sitecore.Social.Client"  method="PostSocialMessages" patch:source="Sitecore.Social.config"/>
</event>

…and then find the ItemPublishedHandler class in the Sitecore.Social.Client assembly:

public class ItemPublishedHandler
{
    public void PostSocialMessages(object sender, EventArgs args)
    {
        if (!ExecutingContext.Current.IoCState.IoCLoaded())
            return;
        this.DoPostSocialMessages(args);
    }

    protected void DoPostSocialMessages(EventArgs args)
    {
        try
        {
            using (new SiteContextSwitcher(SiteContext.GetSite("shell")))
            {
                using (new SecurityDisabler())
                {
                    ItemProcessedEventArgs processedEventArgs = args as ItemProcessedEventArgs;
                    if (processedEventArgs == null || processedEventArgs.Context.Result.Operation != PublishOperation.Created && processedEventArgs.Context.Result.Operation != PublishOperation.Updated || processedEventArgs.Context.VersionToPublish == null)
                        return;
                    IMessageManager messageManager = ExecutingContext.Current.IoC.Get<IMessageManager>();
                    foreach (Message message in messageManager.GetMessagesByContainer(processedEventArgs.Context.VersionToPublish.Uri.ToString()).Where<Message>((Func<Message, bool>)(message => message.PostingConfiguration is ContainerPostingConfiguration)).ToList<Message>())
                    {
                        ContainerPostingConfiguration postingConfiguration = (ContainerPostingConfiguration)message.PostingConfiguration;
                        if (!postingConfiguration.ContainerPublished)
                        {
                            postingConfiguration.ContainerPublished = true;
                            messageManager.UpdateMessage(message);
                        }
                    }
                }
            }
        }
        catch (Exception ex)
        {
            ExecutingContext.Current.IoC.Get<ILogManager>().LogMessage(ex.Message, Sitecore.Social.Infrastructure.Logging.LogLevel.Error, (object)this, ex);
        }
    }
}

What this is doing, essentially, is flagging this message for posting – on a schedule!

If you check the logs after a publish, you will see this message:

Job started: Sitecore.Social.Client.Tasks.PostFlaggedMessages

If you search for this job in config, you will find:

<agent type="Sitecore.Social.Client.Tasks.PostFlaggedMessages, Sitecore.Social.Client" method="Run" interval="01:00:00" patch:source="Sitecore.Social.config">
   <param desc="Social accounts root (item path or ID)">/sitecore/system/social/accounts</param>
</agent>

If you search for the PostFlaggedMessages class in Sitecore.Social.Client, you will find:

public class PostFlaggedMessages : ContentManagementInstanceTask
{
    ...

    protected override void DoRun()
    {
        this.LogManager.LogMessage("Processing messages posting...", Sitecore.Social.Infrastructure.Logging.LogLevel.Info, (object)this);
        using (new SiteContextSwitcher(SiteContext.GetSite("shell")))
        {
            IEnumerable<Identifier> accountIds = this.GetAccountIds(new Item[1]
                {
        CurrentDatabase.Database.GetItem(this.AccountsRoot)
                });
            if (accountIds == null)
                return;
            IMessageManager messageManager = ExecutingContext.Current.IoC.Get<IMessageManager>();
            foreach (Message message in messageManager.GetMessagesReadyToPostAutomatically(accountIds))
                messageManager.PostMessage(message.Id);
        }
        this.LogManager.LogMessage("Done.", Sitecore.Social.Infrastructure.Logging.LogLevel.Info, (object)this);
    }
}

The key line in this method is the call to messageManager.GetMessagesReadyToPostAutomatically(accountIds).  If you look at the definition of this method on the IMessageManager interface, you find some of the best code documentation I’ve seen in a Sitecore assembly.  Ever.

/// <summary>
/// Gets messages that are ready to be posted automatically.
/// </summary>
/// <param name="accountIds">The account ids.</param>
/// <returns>The messages list. If no messages are found an empty list is returned.</returns>
/// <remarks>
/// This method will search messages by the following parameters:
/// <list type="bullet">
/// <item><description>Content posting configuration.</description></item>
/// <item><description>Content item is published.</description></item>
/// <item><description>"Post automatically" is checked.</description></item>
/// <item><description>Message is not in a workflow. Or message is in a final workflow state.</description></item>
/// <item><description>Message is not posted.</description></item>
/// </list>
/// </remarks>
IEnumerable<Message> GetMessagesReadyToPostAutomatically(IEnumerable<Identifier> accountIds);

It is looking for messages that meet the following criteria:

  • The content has a social posting configuration
  • The content item has been published
  • Post automatically is checked
  • The message is not in a workflow or the message is in a final workflow state
  • The message has not been posted

So, when you select the Post Automatically checkbox but wonder why your social message doesn’t get posted as soon as the content is published, now you know why!

If you REALLY don’t want to wait for the schedule to come back around, you can choose to click the Post Now button in the message configuration.

post-now

Happy Sitecore trails, my friends!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: