The Lesson of the Advanced Custom Fields Pro / Secure Custom Fields Debacle: Don’t GPL Your Paid Plugins

I’ve been using Advanced Custom Fields Pro since it was a solo project run by Elliot Condon. When you contacted ACF for support, you dealt with Elliot directly. I still think of it that way, even though several years ago, Elliot (after growing the business apparently beyond the scale he was interested in managing) sold ACF to WordPress plugin company Delicious Brains, which itself was later acquired by WP Engine.

Make no mistake: for me and countless other developers, ACF is the reason we can use WordPress as a general purpose Content Management System (CMS). It’s the reason I stopped building my own custom CakePHP-based CMS!

WordPress started as blogging software, and based on all available evidence, the core team, or really its BDFL, Matt Mullenweg, still sees it that way. I suspect it burns Matt up inside that a large contingent of us developers who have made WordPress the most popular CMS in the world only use WordPress because ACF makes it possible, and that we’re using WordPress specifically in ways he never envisioned it being used.

I doubt Matt’s ongoing war against WP Engine is that much about ACF. But it’s unmistakable that with WordPress.org’s (read: Matt’s) recent hostile takeover (don’t call it a fork, because this isn’t how forks work) of the free version of Advanced Custom Fields, renamed to “Secure Custom Fields,” and their even more recent actual fork of the paid Advanced Custom Fields Pro, also confusingly renamed to “Secure Custom Fields” and released for free in the Plugin Directory, WP.org/Matt sees ACF as, at least, a useful pawn in that war.

The thing that really confused me though was how could they get away with it? Advanced Custom Fields Pro is a paid plugin, distributed directly on its own website, to paying customers only.

In order to appear in the WordPress Plugin Directory, plugins are required to carry an open source license, with GPL v2 being the preferred choice. The free version of ACF in the Plugin Directory is, of course, GPL. But the Pro version…?

Strangely, after the news broke about this, I started seeing counterarguments that WP.org absolutely had the right to do it, because there wasn’t any other copyright in the ACF Pro code.

What?

So I checked for myself. Standard practice in WordPress plugins is for the license terms to be included in either the readme.txt file, the plugin’s main PHP file, or both. Here’s the top of the readme.txt file in the latest version of ACF Pro (6.3.11):

Well, there it is. ACF Pro is GPL v2. But just to make sure we didn’t miss anything, here’s what’s in the main PHP file:

I did a multi-file search in the plugin code for any instance of the word “copyright” and came up empty.

Well, that’s not good.

In case you’re not familiar with the GPL/open source, uhhh… yeah. This says in effect that WP.org absolutely has the legal right to fork and freely distribute not just the free version of Advanced Custom Fields, but the paid Pro version as well.

But just because it’s legal, doesn’t mean it’s ethical. And reading pages of the ACF site such as their terms for embedding ACF Pro in other plugins and themes, it is clear that their intentions, while generous, are more restrictive than the GPL.

I’m not really sure how, in all of these years, it never occurred to Elliot, or Delicious Brains, or WP Engine, that they needed to change the license terms for Advanced Custom Fields Pro. There’s nothing to stop them from doing that. Earlier versions of the plugin released under GPL will always be GPL. But newer versions could have switched to a more restrictive copyright, which would have (legally) prevented WP.org from forking ACF Pro.

As it happens, I now find myself somewhat in the position Elliot Condon was in back when I first started using Advanced Custom Fields Pro over a decade ago: a solo developer of a plugin that has both a free version in the Plugin Directory, and a paid Pro version.

My plugin is far more niche than ACF, so I doubt it will ever be valuable enough for a company like Delicious Brains to snap up, or that any company that would snap it up would itself become valuable enough to be acquired by a hosting behemoth like WP Engine.

I’m less valuable than a pawn. But that doesn’t mean my work isn’t of value to me. And that’s why, although the free version of ICS Calendar in the Plugin Directory — by necessity — carries a GPL license, the Pro version emphatically does not. (The latest version’s terms were reworded in the wake of this situation to be even more emphatic.)


Update: After posting this, I read the terms of the GPL more closely, and I think the issue may be that, because ACF Pro is coded in such a way that the free version’s code is deeply integrated with the Pro code, they may legally have no choice but to make ACF Pro GPL as well.

I believe it is within the terms of the GPL, and is fairly common practice among paid plugins (including mine), to put any GPL code libraries into a vendors (or similar) folder, and keep the proprietary code separate. (That’s how ICS Calendar Pro works.)

Since the GPL was written with full operating systems in mind, interpreting its wording in the context of something like a WordPress plugin, which doesn’t exist in compiled form and can’t function outside of a much larger system, can get a little fuzzy. What can or can’t be included in that vendors folder?

This leads to a broader consideration: Do I believe in the principles of open source? Or am I just using open source software opportunistically? Can I both support and contribute to open source and make money off of my software, even if it relies (partially) on other people’s open source projects to function?

I think it is naive to suggest anyone who is actually making a living working with open source software is not in that compromised position. Automattic (Matt’s company) relies on open source software just as much as WP Engine, and does far more to blur the lines between the free and commercial sides of the WordPress ecosystem than WP Engine does. (WordPress.com, anyone?)

There is no money in pure open source. That’s kind of the point. But even the most ardent anti-capitalist still needs money to survive in any modern society. And that money has to come from somewhere, whether that’s working for a for-profit company that benevolently “gives back” to the open source community by committing employee time to working on open source projects, or from indie developers releasing the basic versions of their software for free and selling paid “premium” add-ons to provide a source of income.

New CSS to fix Chrome breaking old CSS (image size/aspect ratio)

Last week I had several clients report to me that their websites were suddenly displaying images at the wrong size — too small. I checked their sites (in Safari, my default browser), and everything looked fine.

Then I realized, it was a bug in the new version of Chrome. (At least, it seems like a bug to me, when CSS code I’ve been using consistently for over a decade suddenly doesn’t render properly in just one browser, right after that browser has been updated.)

Here’s the code I had been using:

img {
  height: auto;
  width: auto;
  max-width: 100%;
}

I discovered that by just removing the width: auto; line, the images rendered at the intended size, and this didn’t seem to break anything in other browsers either. Sweet!

Unfortunately today I had a client contact me with what I initially thought was the same issue. But then they said it was affecting Firefox and Edge as well. (Windows user!) Sure enough it’s also a problem in Safari.

But this time, it’s not that the images are rendering too small; it’s that they’re getting stretched and distorted. Then I realized I had already applied my fix for that client’s site, and it was causing this new issue.

Fortunately there’s another simple CSS fix. (I briefly considered the aspect-ratio property, but that’s not flexible enough for what I’m trying to do.) It’s a newer CSS property that I haven’t used much: object-fit.

It’s really quite simple though. Here’s the new code I’m using that seems to resolve the issue completely. But I suppose I’ll get another email from someone next week describing another edge case where it doesn’t work. Stay tuned…

img {
  height: auto;
  max-width: 100%;
  object-fit: contain;
}

Update (11/21/2024): OK, so maybe as with the PNG-to-HEIC-to-JPEG glitch, this was actually more of a WordPress 6.7 issue. By the way, I reported the PNG glitch and it got patched in 6.7.1, as did this issue… assuming it’s the same issue I’m describing here, which kind of sounds like it. In retrospect it does seem kind of odd that Chrome and WordPress would both introduce image-related issues on the same day. Much more likely that WordPress introduced multiple issues — or, well, maybe just revealed browser issues, but still. Gotta blame someone.

Coming soon: On the ethics and economics of open source software

If you are the regular reader of my blog, you may notice that I’ve unpublished a recent series of rants over the current and escalating war between Automattic (really, Matt Mullenweg himself) and WP Engine.

I’ve unpublished them because they were angry and unfocused rants, as I struggled to get a handle on why what is happening is happening, and what it really means to (and for) me, as well as the larger WordPress community.

This afternoon I channeled that frustration into some long-overdue household tasks — fixing a kitchen cabinet door, shampooing the carpet in the upstairs hallway, clearing out the clogged drain of a bathroom sink — and those few hours of manual labor gave me time to sift through the thoughts and feelings piling up in my brain.

I realized that the heart of the matter is a lack of common agreement on the nature of free open source software (FOSS) — specifically, both the ethics and the economics of FOSS. Now that I’ve realized what is at the heart of my recent frustration and anger, I can start thinking — and writing — more constructively about it, rather than firing off aimless missives.

A more coherent mini-essay on this topic is forthcoming. But for now, the earlier angry posts are unpublished. Gone, but not forgotten. And, well, not really gone. Thanks to WordPress.

Stay tuned…

In the meantime, read this. Then this. Then consider this.

Elementor and the popularity feedback loop

I hate Elementor.

If you don’t know what Elementor is, good. If you do, you probably either hate it too, or else you’ve never used WordPress without it. (And even if you haven’t ever used WordPress without it, you still might hate it.)

In my experience, Elementor is hot garbage, and it makes the overall WordPress experience bad.

It’s not just Elementor. There are several “page builder” plugins for WordPress, and they’re all terrible. Divi, WP Bakery, Beaver Builder, etc. They all deviate wildly from the way WordPress is intended to work. Since 2018 WordPress has had the Block Editor (a.k.a. Gutenberg) built-in, which is essentially a page builder itself. Now that Gutenberg has matured enough to be useful, those other page builders are completely unnecessary.

Among the page builders, I think Elementor is the worst. Why? Mainly because of its ubiquity.

Elementor is extremely popular, in part because there’s a companion theme/gateway drug called Hello Elementor. It is the most popular third-party WordPress theme, as evidenced by its lofty position at the top of the WordPress theme download screen, surrounded by the official annual themes and one other third-party theme, Astra. (I actually really like Astra, because for the most part, it does things the WordPress way.)

Why is Hello Elementor so popular? Presumably people do like it. But I think it is also an example of what I would call the popularity feedback loop. It’s a natural, and harmful, side effect of a page like this, also commonly seen on e-commerce sites.

If you sort things by popularity, with the most popular items at the top, those are what people are going to see first. And most people don’t want to spend a lot of time considering options. They may trust popular opinion, or they may be too impatient to consider their options carefully, or they may just not care at all. So they click on the first thing that catches their attention, thereby making the popular thing even more popular, and dooming less popular options to oblivion, regardless of their quality.

The people choosing to default these lists to ranking by popularity may think they’re making an objectively straightforward choice, but they’re not considering how the popularity feedback loop might have much more of an effect on the rankings than quality, because they’re falsely assuming that people are making careful, rational choices.

There’s another reason in this specific context why it matters. New users don’t understand the WordPress ecosystem. They don’t know about third-party themes and plugins. They don’t know what does or does not adhere to “the WordPress way.”

So, a new user comes in and wants to pick a theme for their site. Their eye is drawn to the Hello Elementor screenshot, which has been carefully designed to be attention-grabbing, especially compared to the rather pedestrian appearance of the official themes.

That’s all fine in and of itself. Third-party themes are great! But when you activate the Hello Elementor theme, it immediately starts prompting you to install the Elementor page builder plugin as well. If you’re not an experienced user, what are you supposed to do with this? You probably install it, of course. And now you’re in page builder land. It’s not WordPress anymore. The experience is completely different.

But what is it about page builders that’s so bad? (And this part really applies to Gutenberg to a large extent as well.) They’re supposed to be making it easier to design your web pages, right? Well… there’s only so much you can do to make designing a web page easier. There’s no way to deal with things like margins or padding without understanding what margins and padding are. The page builders end up being CSS GUIs. Maybe you’re not writing the code, but you still need to know the concepts to get anywhere. So you end up either creating a convoluted mess, or at best you do learn the concepts, but in a compromised way, that is inextricably tied to that page builder plugin. It’s lock-in.

I could go on, but I think there are two main ways to address the problem of the popularity feedback loop, at least as it applies specifically to WordPress themes, but also more generally:

  1. Don’t default to a “most popular” view. I know it takes a lot more work, and is a lot more subjective, but the best default would be a “recommended” view. Some editorial decisions need to be made. Consider popularity, of course, but also consider context. Which themes are the best for a newcomer? Which ones offer the most pure WordPress experience?
  2. Make the “most popular” list conditional. This is a more automated version of #1. Maybe you don’t have a carefully curated editorial list of recommendations, but at the very least, determine some criteria that can restrict what shows up in the list. For starters, maybe a theme cannot load with an admin notice pushing users to install a plugin. Would Hello Elementor be such a problem if it didn’t immediately lure new users into installing a page builder plugin too? Probably not.

Ultimately, I have my own selfish motivations in all of this. I develop a number of WordPress plugins myself, and I need to provide user support for them. And a significant percentage of my overall user support load — I would say it’s around 15-20% — is around conflicts with Elementor.

An even dumber workaround for how dumb CSS hyphenation is

Look, it’s all well and good that CSS has a hyphens property. The problem is, that property is really dumb. It’s all-or-nothing, with no rhyme or reason to whether a word absolutely needs to be hyphenated. It will literally hyphenate any and every multi-syllable word at the end of a line.

You really almost never want that.

In my particular case, I’m looking at a very specific situation. Specific, but I am guessing probably the most common situation where a web developer wants a browser to hyphenate words: words in large headings that are too long to fit on a line. What I mean here is individual words that are by themselves too long to fit on a line, typically in a mobile browser, in headings with large or extra-wide fonts.

There are proposals to improve this, but there is currently nothing with broad browser support. So I invented my own.

This is a crafty little combination of CSS and JavaScript. (OK, technically it’s jQuery, but you could reasonably adapt this to vanilla JavaScript if that’s your thing. Since I’m deeply immersed in the jQuery world of WordPress, I just went with jQuery because it’s simpler for me that way.)

The first thing you need is a special CSS class for hyphenation. Since I only want it to apply on mobile devices, I gave it a logical name, and defined it in my CSS media query for the mobile breakpoint:

@media screen and (max-width: 782px) {
    .hyphenate-on-mobile {
        -webkit-hyphens: auto;
        hyphens: auto;
    }
}

OK, with that set up, then we just need a little jQuery function to determine where it’s going to be applied. I want it to get added automatically to any h1, h2, h3 or h4 tag. (I’m skipping h5 and h6 because they’re small enough text that we shouldn’t need it.) I also made the somewhat arbitrary decision to set the minimum word length at 15 letters. This is something you may need to adjust based on your font size. Here’s the jQuery:

jQuery('h1, h2, h3, h4').each(function() {
    var words = jQuery(this).text().split(' ');
    var i = 0;
    var hyphenate = false;
    while (i < words.length) {
        if (words[i].length >= 15) { hyphenate = true; break; }
        i++;
    }
    if (hyphenate) {
        jQuery(this).addClass('hyphenate-on-mobile');
    }
});

And then you just want to make sure that jQuery gets fired off when the page loads. It works!