Insights

Scheduled Publishing in Sitecore

Automate publishing in Sitecore using a Scheduler task.

Setting Up Publishing Schedules in Sitecore

In Sitecore, a common misconception is that items can be published and unpublished using the Publish and Unpublish fields. However, this is not true. While this feature does provide some control over content release, it still requires manual intervention. The publishing process must be initiated by someone for the changes to be reflected on Edge or the Website.

Setting up publishing schedules in Sitecore

This manual process was sufficient until a recent request from a client. They requested scheduling and automatic publishing of items, but did not want to implement workflows. Their goal was to streamline their content management process by eliminating the need for manual publishing for few items scheduled at a future date.

In response to this need, we devised a system that allows content editors to place items into a designated folder for automatic publishing. Here's how it works: each item placed in this folder is set with a specific time, and when that time arrives, the item gets published automatically.

To make this possible, we created a scheduler task that runs at predetermined intervals. This task has a specific duty - it looks into the Schedule Publish folder and reviews each item in it. For each item, it checks the Publish Datetime field. If the time set in this field has arrived, the task publishes the item. If the time hasn't yet arrived, the task skips the item and moves on to the next one.

This new system provides a more efficient way of publishing items in Sitecore. It eliminates the need for manual publishing and allows for precise control over the timing of content release. This is particularly useful in environments where content needs to be updated regularly, without fail.

Scheduled Publishing Vs. Auto Publish

Sitecore Scheduled Publishing empowers content authors with the ability to strategically plan and schedule content releases. This feature offers flexibility by allowing authors to set specific dates and times for items or versions to go live, making it particularly well-suited for coordinated marketing campaigns, product launches, or adhering to editorial calendars. With granular control at the item or version level and seamless integration with Sitecore workflows, Scheduled Publishing is a manual yet powerful tool for managing content release timelines.

In contrast, Auto Publish refers to a continuous and automatic publishing process that operates in near real-time or at short intervals. This functionality eliminates the need for manual intervention when content changes are made. Auto Publish is advantageous in scenarios where content is frequently updated and requires immediate reflection on the live site, making it efficient for news websites, dynamic catalogs, or any context where real-time content dissemination is crucial. The choice between Sitecore Scheduled Publishing and Auto Publish depends on the specific content release strategy and update frequency required by the website.

In this case, our client chose not to use workflows, so we adhered to use scheduler task to automate publishing.

The steps followed for the solution include

Creating Schedule Publish Item Template

Each Schedule Publish item would have fields like

  • Item(Droptree)
  • Publish Related Items(Checkbox)
  • Publish Sub Items(Checkbox)
  • Is Published(Checkbox)
  • Publish DateTime(DateTime)

Setting up publishing schedules in Sitecore

Creating Schedule Publish Folder

The scheduler task points to this folder and it has the Schedule Publish Item template as an insert option.

Setting up publishing schedules in Sitecore

Creating Scheduler Command & Task

Create a scheduler command and enter the assembly-qualified type in the Type field and the method name in the Method field.

Setting up publishing schedules in Sitecore

Create a scheduler task and fill the required fields as in image below

Setting up publishing schedules in Sitecore

Next, you need to register your scheduler command in the Sitecore configuration.

<scheduling>
<agent name="AutoPublish" type="YourNamespace.AutoPublish,Your Assembly" method="Run" interval="0:01:00" patch:after="agent[@type='Sitecore.Tasks.CompactClientDataAgent']"/>
</scheduling>

Code Behind the Scheduler Task

public class AutoPublish
    {
        public void Execute(Item[] items, CommandItem command, ScheduleItem schedule)
        {
            Sitecore.Diagnostics.Log.Info("Scheduled task started: " + Sitecore.DateUtil.ToServerTime(DateTime.Now), this);
            Item schedulePublishingFolderItem = items.FirstOrDefault();
            if(schedulePublishingFolderItem != null)
            { 

                //var schedulePublishFolder = Context.Database.Items.GetItem(schedulePublishingFolderItem.ID);
                foreach (Item item in schedulePublishingFolderItem.Children)
                {

                    DateField dateField = item.Fields["publishDateTime"];
                    CheckboxField publishedField = item.Fields["isPublished"];
                    CheckboxField publishRelatedField = item.Fields["isRelated"];
                    CheckboxField publishSubItemsField = item.Fields["subItemsRequired"];
                    Sitecore.Data.Fields.ReferenceField itemToBePublishedLink = item.Fields["item"];
                    if (itemToBePublishedLink != null)
                    {
                        Item itemToBePublished = itemToBePublishedLink.TargetItem;
                        DateTime dateInMst = Sitecore.DateUtil.ToServerTime(dateField.DateTime);              
                        if (dateField != null && dateInMst < Sitecore.DateUtil.ToServerTime(DateTime.Now) && !publishedField.Checked)
                        {
                            PublishLinkedItemsRecursively(itemToBePublished, publishRelatedField.Checked, publishSubItemsField.Checked);

                            // Mark the item as published
                            using (new EditContext(item))
                            {
                                publishedField.Checked = true;
                            }
                        }

                        // Check if the item should be deleted after 10 days
                        DateTime createdDateInMst = Sitecore.DateUtil.ToServerTime(item.Statistics.Created);
                        if (publishedField.Checked && Sitecore.DateUtil.ToServerTime(DateTime.Now) - createdDateInMst > TimeSpan.FromDays(10))
                        {
                            DeleteItem(item);
                        }
                    }
                }
            }
        }

        private void PublishLinkedItemsRecursively(Item item, bool publishRelated, bool publishSubItems)
        {
            // Publish logic remains the same as before
            PublishItem(item,publishRelated,publishSubItems);

            //Publish related items if the checkbox is checked
            if (publishRelated)
            {
                foreach (Item linkedItem in GetLinkedItems(item))
                {
                    Sitecore.Diagnostics.Log.Info("Publishing Linked Item of " + item.Name + ":" + linkedItem.Name, this);
                    PublishItem(linkedItem, publishRelated,publishSubItems);
                }
            }

            //Publish sub-items if the checkbox is checked
            if (publishSubItems)
            {
                foreach (Item subItem in item.Children)
                {
                    Sitecore.Diagnostics.Log.Info("Publishing Child Item of " + item.Children + ":" + subItem.Name, this);
                    PublishLinkedItemsRecursively(subItem, publishRelated, publishSubItems);
                }
            }
        }

        private void PublishItem(Item item, bool relatedItem, bool deep)
        {
            Sitecore.Publishing.PublishOptions publishOptions =
     new Sitecore.Publishing.PublishOptions(item.Database,
                                            Database.GetDatabase("experienceedge"),
                                            Sitecore.Publishing.PublishMode.Full,
                                            item.Language,
                                            System.DateTime.Now);           
            // Create a publisher with the publishoptions
            Sitecore.Publishing.Publisher publisher = new Sitecore.Publishing.Publisher(publishOptions);
            if (publisher != null)
            {
                publisher.Options.RootItem = item;
                publisher.Options.Deep = deep;
                publisher.Options.PublishRelatedItems = relatedItem;
                publisher.Options.CompareRevisions = true;
                var handle = PublishManager.Publish(new PublishOptions[] { publishOptions });
                PublishManager.WaitFor(handle);
                //publisher.PublishAsync();
                Sitecore.Diagnostics.Log.Info("Published Item: " + item.ID +" at " + Sitecore.DateUtil.ToServerTime(DateTime.Now), this);
            }         


        }

        private IEnumerable<Item> GetLinkedItems(Item item)
        {
            var links = Globals.LinkDatabase.GetReferrers(item);
            if (links == null)
                return new Item[0];
            var linkedItems = links.Select(i => i.GetSourceItem()).Where(i => i != null);
            return linkedItems;
        }

        private void DeleteItem(Item item)
        {
            // Delete the item
            item.Delete();
        }
    }
}

The AutoPublish class facilitates automated scheduled publishing tasks. When the Execute method is triggered, it processes child items within a specified publishing folder. It begins by logging relevant information, such as the initiation time of the scheduled task. The method then iterates through the child items, checking conditions such as the publication date and the status of checkboxes indicating whether the item is published, related items should be published, or sub-items are required for publishing.

Within the loop, the PublishLinkedItemsRecursively method is invoked to manage recursive publishing of linked and sub-items. This method handles the core logic of item publishing, including checking the publication date against the current server time, ensuring items are not published repeatedly, and executing the necessary actions accordingly. The class logs information at critical stages, providing visibility into the execution timeline.

Moreover, the class incorporates a mechanism to delete items that have been published and remaining in the Schedule Publish folder for over 10 days, contributing to effective content management. The deletion is based on a comparison between the creation date of an item and the current server time.

The PublishItem method encapsulates the core publishing functionality. It utilizes Sitecore's publishing options, allowing for comprehensive control over the publication process. This method handles related and deep publishing based on parameters provided during the execution of the AutoPublish class.

Preventive Measures to Avoid Accidental Item Publishes

As we schedule items for future dates, it's crucial to prevent them from being published during a manual site publish or when related or parent items are published.

In order to safeguard from accidental publishing there are few steps that were implemented as a guidelines for content editors when scheduling items for future publish

  • Whenever an update was made to a particular item, a new version was created for that update. This could be easily achieved with workflows, but our client didn't want to enable workflows at that time.

    Setting up publishing schedules in Sitecore

  • Set the publish from time for that version to a time just before the scheduled time

    Setting up publishing schedules in Sitecore

  • Schedule the item in the schedule publish folder

    Setting up publishing schedules in Sitecore

In conclusion, this blog presents a smart solution for automating publishing in Sitecore. We've streamlined the scheduling and publishing of items by using a Scheduler Task that executes a custom method to get items published. This provides content editors a user-friendly and automated experience. We've also taken precautions such as creating new versions and setting strategic publish-from times for a safe and efficient publishing workflow.

We're enhancing this experience by integrating the power of workflows with scheduled publishing in future. Stay tuned for more information in my upcoming blogs.

Thanks for reading!



Meet Anju Thomas

Sitecore Web Developer

🎞🥘🧩

Anju is a Sitecore Developer with a Bachelor's Degree in Computer Science and over 4 years of experience in Sitecore development. She loves solving Sudoku puzzles, watching movies, eating delicious food and exploring the world.

Connect with Anju