Converting a WordPress Plugin Store to HTTPS

A few weeks ago, I was experimenting with https:// on the site for my plugin, ACF Widgets. I added the SSL cert for my domain using Let’s Encrypt and the requests were being handled fine, but I was only enforcing SSL on the checkout page. If you hit the ACF Widgets site with https:// initially, everything worked fine, but my login rules were causing some issues with people logging in to the support forums.

After 4 or 5 people contacted me through other channels telling me they couldn’t log in to get support, I decided to look into it a little more closely. As it turns out, the login pages were trying to work over SSL while people were trying to login with insecure http:// POST requests. Whoops!

To fix this problem, I needed to convert the whole site to use https:// all of the time. This too worked out fine and wasn’t an issue. 3 lines in .htaccess that you can find on a million different blogs. Super easy stuff. What made things more difficult, was upgrading the URL for my plugin to check and receive automatic updates.

The problem with copying .htaccess rules

I think this goes back to a fundamental flaw with humans, in that we want results and we want them immediately. In 99% of the tutorials I found, most of them advocated for an .htaccess rule that looks something like this:

Generally, this will work, and it’s fine. Let’s go through it line by line.

  1. Turn the Rewrite Engine on. This tells apache that we’re going to do a rewrite so it can load the required modules.
  2. Set a condition. In this case, return true if the server is listening on port 80. (The standard port for HTTP)
  3. Redirect the request to the given URL and pass in the URL query parameters.

Like I said, for most sites this works fine. However, when I pushed the next update to my plugin, I noticed I wasn’t getting any update notices. Why wasn’t it working?!

Now, in my most recent plugin update, I updated the store URL to my new https:// domain, so after everyone updated, I know whatever weird issue going on would probably go away. I did some tests and sure enough, requesting the update using the https:// store URL triggered an update. So why wasn’t it working with the http:// URL? What was happening during the redirect that broke things?

Since I have almost 500 customers, sending an email asking everyone to manually re-install this new version of my plugin was unacceptable. I knew I could do better. I decided to dig-in to the inner workings of APACHE and HTTP a little bit to understand what was going on behind the scenes.

A brief history of redirects in HTTP

So from my understanding of reading numerous blogs, is that the original intent of the HTTP/1.1 spec, was that if no redirect status code was specified (ie. 301, 302, etc) that the client was supposed to treat it as the same method as the original request. So if I send a POST request to /my-api-endpoint/ , the client should honor that POST request and it’s data if I do not specify a status code. In APACHE’s mod_rewrite this looks like:

RewriteRule ^(.*)$$1 [R]

Using the [R] flag with no options.

Somewhere along the way (I’ve seen both IE and Netscape blamed) browsers and HTTP clients in popular languages begin to interpret any missing status code as a 302. In the HTTP spec, a 302 request is for GET requests only. Herein lies the problem with our updates.

EDD Software Licensing Update Process

To understand why updates are failing, I also needed to examine the source code for the update script I was using. At the time of this writing, ACF Widgets is build upon Easy Digital Downloads and the Software Licensing Add-On. It works great! Though in my case, updating the store to https:// was obviously causing issues. Digging in to the code, we find this:

And herein lies our problem. EDD SL uses wp_remote_post() to send API requests to the URL of our plugin store, which is fine, nothing wrong with that. However, when our POST request to our EDD store encounters a redirect without a specified status code, cURL redirects to a GET request for the homepage with no query parameters. Since that’s obviously not what we want, the EDD SL update script fails silently (like it should) so we don’t clutter the users dashboard with errors in case our store is down for any reason. In our case though, we want to preserve that POST request and any data we send. So how do we do that?

Enter the Magical Hero Extraordinaire Status Code™, 307

According to HTTP Status Code Spec, a 307 code should behave thusly:

The requested resource resides temporarily under a different URI. Since the redirection MAY be altered on occasion, the client SHOULD continue to use the Request-URI for future requests. This response is only cacheable if indicated by a Cache-Control or Expires header field.

Perfect! That’s exactly what we want! In short, this will preserve our POST request and any data we send. So now we can use this in conjunction with a normal 301 request to route all of our traffic through our newly secured domain.

So line by line, let’s go through this new .htaccess.

  1. Turn on Rewrite Engine
  2. Check for a request on port 80
  3. Check for the GET request method
  4. Redirect (via a 301 for SEO purposes) and ignore all other rewrite rules ([L] flag).

Now if we don’t have a GET request (maybe we have an API that uses PUT, POST, or DELETE) it will get routed through the second rule.

  1. Check for a request on port 80.
  2. Perform a 307 redirect, thus preserving our request method and data. Also, ignore any more rewrite rules ([L] flag).

Now for those of you worried about SEO, don’t worry. Google only cares about your visible stuff, AKA GET requests. You shouldn’t get a penalty for other request types (because Google won’t even know to access them).

As you can see, 307 redirects can be extremely powerful. With the correct caching headers, you can even instruct clients to cache the results while you update your API or tools to use your new secured endpoints, without sacrificing security.

So what next?

Since we now have a our store properly configured to redirect requests from plugins out in the wild, there isn’t anything else to do except wait. Customers will update the plugin to the new version which uses the new https:// store endpoint. If you have detailed stats about version usage for your plugin, you could eventually remove the redirect, though I don’t see a reason to for the vast majority of plugin stores out there. If anything, it’s a good catch all for anything you may add in the future and forget about.

Questions? Comments? Leave ’em down below. I would love to hear from you!

Modifying Custom Taxonomy Forms in WordPress

Today, I was working on a client project and needed to add a little snippet underneath a hierarchical taxonomy form that was registered on a custom post type. Unfortunately, after spending about ten minutes digging through core and googling, I couldn’t find an action hook to use. Luckily, after tracing the output a little further back, I found what I was looking for.

Continue reading “Modifying Custom Taxonomy Forms in WordPress”

Publishing A WordPress Plugin without SVN, Utilizing Ship

So just this past week, I submitted my first plugin to the plugin repository. Needless to say, it was an exciting (yet dull) experience! Since I’m still fairly green to professional development as a whole, there were some aspects of the .org publishing process that were confusing, so I’m writing this post in hopes that someone will find it useful. 🙂
Continue reading “Publishing A WordPress Plugin without SVN, Utilizing Ship”

Adding a custom style button in the WordPress post editor

So my title is a little misleading as what we’re creating is largely based on what your definition of a button. However, the point still stands 🙂

Here is an example of what we’ll be creating today.

Screen Shot 2015-09-21 at 5.01.02 PM
Continue reading “Adding a custom style button in the WordPress post editor”

Crafting Personalized HTML E-Mails with wpMandrill

Recently, I’ve been working on a new little side project called ToDo, a small SPA that allows you to create and manage a ToDo list. It utilizes the new WordPress JSON REST API and it’s awesome. You should definitely check it out!

Edit: ToDo in its current form has unfortunately been “closed”. While you may still find something at the link, I’m not doing anything with it, and will be replacing it with something new, hopefully, in the very near future.
Continue reading “Crafting Personalized HTML E-Mails with wpMandrill”

Why WordPress 4.2.3 should have been a non-issue.

Let me preface the following post by saying this: I am sorry if your site was affected by the WP 4.2.3 update. I’m sure nobody on the core team wanted things to break and if they could go back in time and do things differently, then I think they would.

What happened?

So for the uninformed, on July 23, 2015 the WP core team released a security update that was installed to millions of websites via automatic updates. For a lot of people, this was fine and they weren’t affected by the change. However, another group of sites (some would argue a large portion) were broken due to breaking changes in the WP Shortcode API. This isn’t a post about the shortcode API or the vulnerability though. You can read about the update on the Make WP Core blog.

Why things should not have broken.

Take this section as a grain of salt, and recognize it as my opinion. You don’t have to agree, and I don’t expect everyone too. 

I have been developing on the WordPress platform for about 3 years now. I currently work for a small digital marketing agency in Northern Kansas as the sole developer creating websites for our clients. Before I started working here,  the previous developer had built a lot of sites using premium themes from Themeforest, which as we all know, usually include a bunch of shortcodes for inserting content and functionality across the site. After doing support for a few of these clients, I quickly realized that shortcodes were not a solution for displaying content for our clients. Not only were they messy and difficult for clients to understand (in some instances) but they created a dependency that I was not comfortable with on such a widespread scale. A client accidentally deactivating a plugin could remove some core pieces of content; it was something I just wasn’t comfortable with.

I started to build out themes for our clients using _S and designs from our in house designer. I jumped onto the ACF bandwagon just before the release of v5 and have been using the Pro version on all of our clients’ sites with great success (Elliot’s commitment to backwards compatibility is another post for another time). ACF allowed me to create highly customized interfaces for our clients, while utilizing an API that would work regardless of if ACF was activated or installed (check out Bill Erickson’s post about removing dependencies from ACF). Over time, I have migrated some clients over to a more customized solution when they would come to us after having difficulty manipulating shortcodes and they have loved it.

Now I know what you’re thinking, “But Daron, using ACF ties you to a theme and that’s bad if you’re a blogger who likes flexibility!” And you’re right. Tethering some clients to a specific theme just isn’t an option, but that isn’t an excuse to build solutions that are fundamentally flawed. One of the use cases that really blew my mind, was how people were outputting and manipulating URLs via shortcode. A much better approach would have been to use custom fields and post meta and then calling that data from the theme. Another alternative would be to build a custom plugin with a simple admin interface and some custom metaboxes.

In the Make WP post, Andrew mentioned how people were using the shortcode API in ways that it was never intended for. You don’t need to look any further than the default [gallery] shortcode to see what the core team was talking about. The gallery shortcode is completely self contained. It outputs it’s own HTML and any attributes needed to attach styling to. If you’re building shortcodes to output a link to an image or to a URL, then you’re fundamentally using shortcodes in the wrong way. Using actions and filters, you can display all sorts of things in and around the_content. If you need to link a background image, you should be using the customizer or a custom field/metabox. For one, using a custom metabox is a vastly superior UX as well as giving you the peace of mind that sites won’t break because of a fundamentally flawed implementation. The shortcode codex entry does not mention using shortcodes as a replacement for HTML attributes and it probably never will. If you’re site needs to be that customizable, you should be using custom fields and metaboxes.

If you want to remove the theme dependency from solutions like ACF and CMB2, use a hook and display that data programatically. This is a totally valid way to show custom content:

Just pop that into a plugin file and you’re off to the races. If you need more programatic control over where content is displayed, then you should look into developing a custom theme or using a more inclusive shortcode. Note, the $extra_content variable should include all of the HTML necessary to support itself. You can enqueue CSS as needed from the plugin as well.

Here is another example that was specifically mentioned in the Make WP article and a workaround that doesn’t require hacking a theme.

Using the above snippet, you can wrap the_content in a div and apply a background image to that div. Using CSS you can further position the image how you want. You can even include that CSS in the same plugin, thus removing any theme dependency.

In closing

We as developers are responsible for when things break and it’s only in our best interest to use the tools that we are given to build applications and solutions that will stand the test of time. Hacking APIs is never a good solution to a problem and it’s up to us to use some common sense and read the documentation on the intended uses of the software that we leverage everyday. Sure, people will always find new ways to use software that the developers never intentioned, however, you do not have the right to be upset when you’ve implemented an unofficial workaround for a problem that is easily solved by utilizing other techniques and APIs. The core team did everything they could to avoid breaking things. Problem is, it’s impossibly to foresee every possible unofficial use-case for every API in the software. Stop giving them flack for your experimental implementations of the API.

I know this probably seems like a disorganized rant, and in some ways, it probably is, but I needed to get it out there and off of my mind. Leave a comment if you want to continue the discussion or you can tweet me @Daronspence

Video: Nested Repeater Fields & Restaurant Menus

If you’re interested in using Advanced Custom Fields ( ACF ) to create a restaurant menu, check out the video tutorial I made! You’ll learn about ACF and how to use a repeater field to loop over your user’s inputted data. Leave a comment if you’re interested in seeing more. Suggestions are welcome! 🙂

Lessons learned from writing a premium WordPress plugin

About 3 months ago, I had a killer idea for a WordPress plugin. I had never written a plugin before and my first venture was a daunting one to say the least. I have learned a lot over the past 3 months and so I’d figure I would share some of my experiences with you.

Lesson #1: v1 is Always Terrible

Yeah that’s right, I said it. When I finally released v1 to the public, there were a lot of problems. PHP 5.2 support? Meh, who needs it? I know a lot of premium plugin developers have dropped PHP 5.2 to take advantage of awesome features like closures, however, since my plugin is sort of an “add-on” for another WordPress product, I wanted to maintain compatibility as much as the other service. Needless to say, the first person who complained that their site got whitescreened after activating, definitely was not happy. Also, WordPress multisite support was also not included. Heck, I’ll honest, I had never even installed multisite before someone mentioned it on the support forums. Whoops. Point being, you will always miss stuff in version 1.0. That’s why we have version numbers! Software was designed to be improved. Don’t beat yourself up too much because things aren’t perfect from the starting line.

Lesson #2: You Know Nothing Jon Snow!

Specifically, in regards to how people will use your software. If you develop a product that allows for any user customization at all, someone will think of a way to use, abuse, and re-use your product in ways you could have never imagined. The feature that took me most by surprise, was the ability to include the plugin in a theme. First of all, MIND BLOWN! I never in a million years would have thought that my creation would be so cool, that someone would want to include it in a theme. Especially within the first month?! After recovering from a mild excitement induced heart attack, I then had to find a way to make everything play nice when not activated like a normal plugin.

One thing that I’m grateful I learned because of this, is the order in which hooks and filters are fired. For example, the action hook fired after the `functions.php` is loaded (`after_theme_setup`) is `init`. 99% of plugin and theme functions can be fired on or after `init` without any consequences and still have access to everything they need. All that was required to make my plugin “includable”, was moving any actions from `plugins_loaded` to `after_theme_setup`. Also, actions and filters are freaking cool! I never really understood how to utilize them effectively until I started using them on a more regular basis. Now I find myself skimming through other plugins looking for hooks and filters to extend their functionality too. It’s a great feeling when you find a problem and a quick glance at the codebase assures you that everything is extensible. Easy Digital Downloads is a great example of a plugin with tons of hooks and filters. Pippin has definitely been an inspiration to the way I look at plugin development.

Lesson #3: Open Source is your Friend

For the first couple of versions, I didn’t release the plugin on GitHub. Which ended up hurting me more than I thought it would. The day that I pushed the codebase to GitHub, something strange happened. I felt obligated to track every change I made. If I read a support email or just ran into a bug while testing, I would go to GitHub and open an issue. Even if the fix was just 1 line of code, I would open one. That small amount of perceived accountability, the knowledge that now anyone could look over my code and judge my decisions, made me better. While I haven’t received any contributions yet, I’m excited for what the future holds and more and more people start to use my creations.

A lot of people also have problems with putting “Premium” plugins in open repositories. First of all, everything used with WordPress is automatically subject to it’s license, the GPL. This means anyone can take the code and copy, modify, sell, distribute, etc, as much as they want. So if people really want it, they’ll get it. The benefit of having a project that anyone can contribute too, vastly outweighs any negatives in my opinion.

Lesson #4: You’ll Become an Addict

I finally understand why Pippin has written 100+ plugins in just a few short years. I’m hooked. Just the other day, someone over on a reddit thread in /r/WordPress was looking for a plugin to do something fairly simple from the admin area. I looked at his problem, thought about it for a minute, and then replied telling him to give me an hour to see what I could do. This led to the creation of Post Author Link, which I will eventually release on for everyone to enjoy. It’s a small plugin now at less than 30 lines of actual code, but it works! It solves a problem in an elegant way without being overly complex. The beauty of it is, that I wanted to write it. I wanted to help this random guy on the internet. For the first time, the kindness bug from the WordPress community infected me and I felt compelled to give back however I could. Now I catch myself browsing through sites like Reddit and WP Chat actively looking for people to help. WordPress has given me so much to become successful that I’m excited to give back to the community in any way I can.


Overall, I’ve learned a lot. I’ve learned to deal with abuse from my plugin website’s contact form, 700,000 API calls in less than a month that shut down my website, etc. The little things. My advice to anyone out there thinking about writing a plugin, premium or otherwise, do it. Stop thinking about it and do it. You’re never gonna learn or grow if you sit on your hands and think about all the things you could do. You are the only person standing in the way of your success. Don’t be afraid to screw up, because it happens to the best of us.

Shorter location rules in ACF.

Have you ever used register_field_group() for a packaged theme or plugin? Most people haven’t. In fact, doesn’t even have documentation on the function. Where this function comes into play is if you try to register a field group (and subsequently, fields) with PHP using the ACF API. The easiest way to see this is by using ACF’s built in PHP export. The subsequent block of code that is rendered can be pretty daunting, and in my opinion, a little bloated depending on your application. For people exporting fields for a theme, it’s probably fine, but for someone writing a plugin that dynamically creates fields, this behemoth can be a pain to write and manage. My biggest beef is with the “location” key passed to register_field_group().

“Location” accepts a multidimensional array, mapping each key => value to the boolean-esque rules that are used to assign fields to a particular location in your WP installation. For example, only show this field for this particular page and the user is an administrator. Where this get’s to be a little overwhelming, is when you are registering a field to a lot of different areas, yet ignoring a lot of others. One example I’ve used recently is widgets. I want to add a text field to all the default WP widgets but not all the other ones. My location value may look something like this:

[gist /]

You can see how that can start to get a little ridiculous right? 60 lines for one value? Especially when most of it is repeated! So I wrote a function for generating these giant location arrays when all the values are similar.

[gist /]

In a nutshell you pass an array of locations that all share a similar a similar parent. In the case above, they were all widgets. Then you supply the operator to compare against and an $extended boolean parameter. The $extended variable is for when each location is a new rule. For example, I want to show this field when the widget is “Archives” or when the widget is “Meta.” The default logic to show a field is that all the parameters must match (and operator). We then pass this function to a variable which we use with the location rule of register_field_group().

$locations = acfw_location_rules( $wp_widgets, 'widget', '==', true );

register_field_group( array (
  'location' => $locations,
// rest of the function goes here ...
) );

Hopefully you find uses for this in your own projects. I know for me, it was definitely a lifesaver for generating long arrays for location rules. I will admit, not being able to set to parameter for something like both “Widgets” and “Administrators” is a limitation, but I’m working on an elegant solution for those instances.

Leave a comment below if you have any questions! I’d be happy to help! Check out if you want to be part of a community all about ACF.

Name Spacing in ACF

Let’s say I’m building a theme for my client “Joey’s Frog Arena.” When I start development, I would namespace all of the theme functions with jfa_, or something similar, and be on my merry way. This is completely normal. Everybody namespaces themes as to avoid conflicts and create a sense of coherence throughout the code.

Something that didn’t occur to me until this specific project was the idea of using a namespace for fields within ACF. So let’s say Joey has 3 different wrestling shows, all of them with 6 participants in each show, totaling 18 different participants. For the sake of simplicity, I’ll call them actors (everyone knows wrestling is fake anyway). So each show is listed as a custom post type, morning, afternoon, & evening shows, and the actors in each show change from week to week. Joey wants his customers to be able to visit the website and see a list of upcoming shows and who is participating in each one.

So I would need to attach a field to each show type that allows Joey to list out the actors for each show. Normally I would call this actors and move on. In the code, I would call this in the template with the_field('actors'); and everything would be handy dandy. Joey would be happy, I would be happy, all is good with the world.

Three months later though, Joey comes back to me and says he wants to add a widget to the homepage that spits out all the actors who are performing that day. So I would make a widget that uses some custom queries to pull of that information in and put it on the page.

Pretty standard stuff right? Just do that 3 times for each post type with some extra stuff added as needed. I finish the feature, Joey pays his bill and I go back to working on other projects. Now let’s jump 1 year into the future.

Joey is back, and he wants some modifications done to the widget I made for him last time. Well, it’s been a year. I don’t remember any of this stuff. Now I have to sift through this code and find where these specific parts are coming from and alter the output of the functions.


Name spacing is a normal part of modern software development. It helps us to stay organized and provides a easy to recognize reference if we have to come back to something later and our documentation just isn’t cutting it. Recently I’ve found myself name spacing all my fields with the name of the field group. This obviously means that choosing the right field group name can be very important! For Joey, I would have had 3 field groups, Morning Show, Afternoon Show, and Evening Show, since those were the 3 post types I was adding fields to. So for the actors field, I would set the label as “Actors” as normal, but the field name would be “morning_show_actors” instead of just actors. Let’s say I had another field called “Location.” That field name would be “morning_show_location.” I hope you can see where this is going.

If I was utilizing a large template to display data from custom queries, I don’t want to have to scroll up and down my document to see what post type I was referencing for a specific field. By including the field group as a namespace, I know exactly what information I’m working with no matter where in the theme I’m using it. This also means I can use a “Find All” in my IDE and search for “morning_show_actors” and only get the one result I want, rather than 3 results for the search term “actors.”

Hopefully you can see the benefit to name spacing and will start to utilize it on your projects. Sure, it’s a pain in the ass to manually alter each field name instead of using the generated name from ACF, but a year or two down the line, you’ll be happy you did when you can’t remember the specifics from a given project.

P.S. After reading this blog post, I’m very disappointed in myself, but I’m putting it out there anyway, despite it’s sloppiness. Oh well. 😉