A lot of our clients are becoming increasingly interested in using social media as a platform for posting updates about new content on their sites. As busy people, they often don’t have time to do this themselves. Wouldn’t it be better if their site would automatically post updates whenever new content was added, and potentially to multiple different targets: RSS, Twitter, Facebook, and so on?
This was the goal we were presented with. The RSS part was easy; on most of our sites we can handle this problem just by doing a search for the top recently published content and formatting it appropriately. We had done some one-off examples of Twitter integration before, but it seemed like it was time to put together something more powerful for reuse on future projects.
So, our additional internal goals became:
- come up with a system where we can implement support for Twitter now, but easily add support for more targets in the future.
- support pulling in data from different types of content sources.
- support queueing content to be published so that publication can be scheduled and batched.
- if something goes wrong during publication, save the content and try again later.
Most of our websites are built using the Symfony framework (http://www.symfony-project.org), which has excellent support for developing plugins. We have built a variety of plugins over the last few years which we collectively refer to as “Armature”; so, this new functionality would get packaged as a plugin called “armSyndicationPlugin”.
The architecture that we devised depends on multiple independent components. These components are passed as arguments to a central control component called a “syndicator”. The syndicator class is then used as the basis of a command-line symfony task which is the primary interface to the functionality.
The independent components we identified include:
- content items, which define a standard set of fields for content items and know how to convert themselves to and from a serialized JSON format.
- content sources, which know how to read content from some external source and convert it into a collection of content items.
- publication targets, which know how to take one or more content items and publish them.
- it’s also possible to make aggregate content sources and publication targets, which draw content from multiple sources or publish it to multiple targets.
- the syndication queue, which knows how to store and retrieve content items from the database.
- the syndicator, which knows how to use a content source to retrieve content and then put it in the queue, and how to retrieve content from the queue and use a publication target to publish it.
All of this is configured via a yaml configuration file that looks like this:
You interact with it using a symfony command line task. That looks like this:
So far we’ve only implemented an rss-feed based content source, and a Twitter publication target. Our plan is to ultimately expand this to include content sources based on database access, and publication targets including Facebook and more. What’s nice about this approach is that we can implement sensible default behavior in base versions of the classes and then extend them per project to do any required customization. For instance, by default the Twitter publication target just uses the title of the content item (suitably truncated for Twitter if necessary) plus a bit.ly shortened link. But, it’s easy to make a subclass which changes the rules about how the Twitter post should look, such as adding a prefix or a tag to each tweet.