One of the few convenient things about WordPress are shortcodes. I’ve implemented a basic, extensible shortcode system on this website.

Written by Josho Brouwers on

In my first post here on the dev blog, I decried WordPress and lavished praise on ProcessWire. But while I would prefer never to use WordPress for any of my sites, I have to admit that it has one feature that is very useful: shortcodes.

With WordPress’s Shortcode API, you can add blocks of code anywhere in a body of text by just typing a specific phrase in between square brackets. When the page is loaded, or rather, when the code is executed, the Shortcode API replaces whatever shortcode you added with actual code. A simple example of a shortcode is the following:

[video src="file.mp4"]

As you can see, this example shortcode is used to embed a video on the webpage. You will also notice that, like e.g. HTML tags, shortcodes can also support attributes: in this particular example, the shortcode tells the system what file to embed.

Adding custom shortcodes

Shortcodes are actually quite simple to implement. In essence, all the system does is perform a search-and-replace of a particular string. In the previous example, the system executes a regular expression search-and-replace (i.e. preg_replace), where the shortcode itself is replaced by the HTML code block needed to embed the video. This prevents end users from having to copy-paste an embed code, which is often not possible anyway. ProcessWire’s default textarea editor, for example, strips out most code when you save the page.

For this website, I knew I needed shortcodes in a few places. Most obviously, for the newsletter page I needed to be able to insert a subscription box anywhere on the page. Fortunately, this is easy to do in ProcessWire. I created a new module that I turned into a text formatter. Text formatters are modules that you can attach to a text or text area field in the ProcessWire backend. They are executed when the system renders the field in question.

My custom module in this case simply goes through a list of shortcodes, stored in an array. When it runs across the string newsletter (in square brackets) it replaces it with a code block to load a simplified Mailchimp subscription form. The code block is defined elsewhere in the module and saved to a variable that can be easily loaded into the same, multidimensional array. (Alternatively, you could implement two separate arrays, one “find” and the other “replace”, but then you’d have to keep the same order in both and I like to keep things as error-proof as possible.)

I’m using my custom shortcode module also to do another important thing, namely handle footnotes. Or rather, “notes”, as they are not saved to memory and appended to the bottom of the article. Notes can be added simply in the text by surrounding the appropriate phrase or phrases with double accolades. When the module runs across such strings, it automatically replaces it with some custom code: a short amount of JavaScript handles the displaying/hiding of notes when they are clicked.Show This is an example note.

You might wonder: why did I chose to have notes display inline rather than collect them at the bottom of the page? Well, I don’t think you should wrest control away from the user. If they click a note and are then taken to the bottom of the page, they might lose track of where they were in the text, even when you implement a link back up. It interrupts the flow. The way that notes are implemented now, the note simply expands in a natural way.

Closing thoughts

The advantage of using a separate module to handle these custom bits of code is that it can be easily re-used on another website when necessary. I’ve also had situations with other websites where a module would have been overkill, since you only ever really needed to insert a code block in a particular body of text once: in those cases, I just performed a simpler search-and-replace directly at the level of the template file.

So even in a system that you might dislike, in the way that I dislike WordPress, you can often still find features that you think will be useful for your own projects. Shortcodes offer convenient ways to add blocks of code to pages without having to directly enter code via the backend.

A ready-made module is also available called “Hanna Code”, which offers an essentially native implementation of shortcodes. I didn’t know about this module when I rolled my own, but I’ll be sure to take it for a test drive.