Using Rules Scheduler to publish content on the weekends.

Publishing Content on Relative Dates Using Rules in Drupal 7

A friend of mine is a DUI lawyer who uses a Drupal site for content marketing and lead generation, managed by my friends at EverConvert. They quickly identified the weekend as the best time for the website to directly appeal to visitors who found the site after a Friday or Saturday night arrest. In addition to live chat, they decided to alter the site's appearance by publishing content only during these times that contains large, direct calls to action.

Fortunately, Drupal provides the tools to build this with nary a line of code.

Introducing the Rules Scheduler

The primary module you'll use to create something similar is Rules with its Rules Scheduler sub-module. Most purpose built content scheduling modules that I've seen allow you to set absolute dates for pieces of content to be published or unpublished. However, you wouldn't want to have to enter in every single weekend date to get that content published at the right times. Fortunately, Rules Scheduler allows you to schedule arbitrary actions using relative date strings (in addition to any other format supported by strtotime()).

Before we dive into the configuration I proposed to them, you should understand that the Rules module basically adds a GUI based scripting language to the back end of Drupal. In addition to configuring actions to be performed after certain events when a set of conditions are met, you can create Rules components that are essentially subroutines that can be directly invoked by Rules (or code) without being triggered by events.

To setup a Rules Scheduler based content publishing schedule, you have to create two Rules components: one will publish the piece of content and schedule it to be unpublished on a relative date (i.e. "next Monday"), while the other will unpublish the piece of content and schedule it to be published on a relative date (i.e. "next Friday"). Another Rule will need to react to content being created or updated to initiate the publishing schedule.

Using Fields to Avoid "Magic" Behavior

One of the keys to building a maintainable Drupal site (or module) is to ensure that every "automated" action is explicitly enabled. In the early days of Drupal Commerce development, I adopted an approach to some module behaviors where a feature just automatically worked if certain conditions were met (e.g. the representation of attribute fields on Add to Cart forms). "Neat!" I thought, until I realized that it was difficult to document and even more difficult to ensure users knew to look for said documentation. Much better to include explicit user interface components to enable functionality.

In the case of a scheduling system, you wouldn't want to build the site to just automatically enter every piece of content, or even every piece of content of a certain type, into the publishing pattern. Your client, a.k.a. the end user, really expects (and needs) to see an indicator on a form that submitting it will lead to a desired outcome.

Checkbox enabling the publishing pattern for calls to action.

For my friend's site, my recommendation was simply to add a Boolean field using a checkbox widget to the relevant content type reading, "Schedule this content to be published on Fridays and unpublished on Mondays." If the site required more publishing patterns than just the weekend pattern, I would've used a List (text) field with radio buttons or a select list identifying the different available publishing patterns.

Building the Scheduling System in Rules

Working with Rules is fairly simple if you can write out long hand what it is you're trying to accomplish. Considering all of our constraints here, we need a set of rules that accomplishes the following:

  1. When a call to action is created or saved with the scheduling checkbox checked, delete any scheduled tasks related to the content. (This is possible because Rules Scheduler lets you assign an identifier to scheduled rules, so identifying our scheduled tasks with the node ID will allow us to delete the tasks when needed in the future.)
  2. If the call to action that was just saved isn't published, schedule it to be published next Friday.
  3. If the call to action that was just saved is published, schedule it to be unpublished next Monday.
  4. When a call to action is automatically published on Friday, schedule it to be unpublished next Monday.
  5. When a call to action is automatically unpublished on Monday, schedule it to be published next Friday.
Actions that queue up a publishing schedule.

The first three items will be accomplished through a single rule reacting to two events, "After saving new content of type Call to action" and "After updating existing content of type Call to action." The rule will first delete any scheduled task for the piece of content and then it will invoke two rules components that will schedule the appropriate task based on whether or not the call to action was published.

Components that manage the publishing schedule.

The final two items will be accomplished through rules components that perform the necessary action and then schedule the appropriate task. As mentioned above, we'll use relative time strings ("next monday" and "next friday") and choose task identifiers that include the call to action node IDs ("unpublish-call-to-action-[node:nid]" and [publish-call-to-action-[node:nid]" respectively).

Give it a whirl!

It only took me about 10 minutes to create and test the rules based on the specification above, but if you aren't familiar with the Rules UI, it could take much longer. I believe Rules is worth learning (we built Drupal Commerce around it, after all), but there's something to be said for ready made examples.

I've attached to this post a Features export of the content type and related rules configurations for you to try on your own site. Give Scheduled Calls to Action a whirl and let me know how it works for you in the comments!

(Note: to see the rules configurations and scheduled tasks, enable the Rules UI, Views, and Views UI modules if they aren't already enabled on your site.)

Topics: 
Files: 

Comments

Oooh, just realized I forgot the condition to ensure the checkbox was checked! Will have to update the Feature in the morning (and include a rule that deletes all tasks if it isn't checked). Shock

Aaaand, updated; instead of using a new rule, I simply added the conditions to the rules components I call to initiate the scheduling process for published vs. unpublished calls to action.

Was just playing around with strtotime() and discovered it even supports specifying the time on relative dates, so "next friday 8 PM" would publish the call to action in the evening instead of at 12 AM on Friday morning.

I was unaware that with Rules Scheduler you can setup arbitrary schedules like that, very cool. A module I have also found very useful for scheduling content is the Workbench Scheduler module. It is more focused around being able to create schedules around different node revisions and the workbench moderation states. I do not think you can setup date patterns however, but still worth checking out.

Or you could just use the Scheduler module to do the same thing:
https://www.drupal.org/project/scheduler

Did you read my post? I evaluated Scheduler and did not see in it the capacity to create a recurring schedule of publishing / unpublishing nodes on regular, relative days of the week. (Nor am I aware it lets you opt individual nodes into a predetermined scheduling pattern like this.) Feel free to point to the functionality if I missed it! Smile

Another benefit of using rules over scheduler is that you can add endless conditions to the scheduling routine. For example, "node author has role" on sites where customers pay to publish content like job listings. If their role expires the content will be skipped in the publishing routine.

I read and read your post and I am unable to follow through. Some of the ... within the picture hides the remaining of the text and I do not know what to put for Data Selector, Task Identifier and etc. :\
Is there like a step by step tutorial?

Thanks!

And how is the performance of the rules scheduler? Does it run in a batch? If I have hundreds or thousands of nodes, will it perform? I see that is has it's own drush command which seems like could be programmed to run while the site has low traffic and alleviate this problems. Nice!