Nothing has foregrounded the fundamental bargain of open source like the past couple months of WordPress drama. I’m not here to talk about that in particular, but it has really gotten people thinking about what’s legal, what’s ethical, what you can charge for, what you can give away, and how a business will or won’t work within the ecosystem based on how you answer these questions.
Matt Mullenweg recently took over the WordPress.org repository copy of Advanced Custom Fields, for which he received a great deal of criticism. Just a couple of days ago, he included advanced features (the one’s you’d ordinarily have paid for) as part of this free (renamed) version of the plugin.
GPL is a free pass
As nearly as I can tell, this is completely within the letter of the GPL (General Public License, a baseline agreement created by GNU). If you use GPL’d software to make your thing, the anyone else can use your thing for whatever they like.
But this business ecosystem is in some respects built on faulty assumptions, and Matt’s release of “premium features” from Advanced Custom Fields is solid proof of this, barring some significant turn of events in a legal action that hasn’t happened yet (ACF’s parent company WP Engine is suing Matt and others but not over this particular matter).
New models
I am convinced that there needs to be a model for code that is examinable and extendible, but that requires a low-cost license to use (or to use in a business resale context, but I prefer the simpler idea of just charging a small amount for any use). I think a blockchain model of project governance is the way to accomplish this, but that’s a post for another day.
Meanwhile, though, those of us trying to run businesses in the WordPress space are pretty concerned by the idea that their features can be distributed for free on the primary distribution site for the ecosystem at WordPress.org.
SaaS, API or Bust
My take is that you have to offer your business as a SaaS, or a SaaS with a connector plugin, if you want to operate in a way that you can legally protect. If I sell you a service, all you see and use is the service. To date, anyway, what I build the service with is my choice and the code I did it with isn’t necessarily anyone else’s concern.
So if what I’m selling you is essentially access to a WordPress site, you’re using the site, not running the code, and you aren’t necessarily entitled to see the code. I’m probably obligated to make the code available to you if I build it within a GPL context, but this seems effectively unenforceable.
For one thing, anything that I want to keep outside of GPL provisions I can implement as a separate service that’s used via REST calls. The code that processes the REST requests isn’t GPL and you’re not entitled to take it and resell it.
I can even make the source code available to you, but not under a GPL license. I can let you see it but not use it yourself, let you see it but only use it if licensed for a fee, and so on.
Business behind the curtain
In the current environment, what I suspect will happen is that developers will cordon off some portion of what they do behind a REST API and not let you see the inner workings. That’s not really the way I want PeakZebra to do business, but I want there to be a revenue stream that Matt can’t gut at a whim.
The good thing about this sort of workaround, where it is feasible, is that it makes it possible to continue to do business in the WordPress space without undue risk to the business owner. And there are all sorts of great reasons to keep WordPress (and it’s ecosystem) thriving and moving forward.
With the WordPress block editor, you get a reasonably good editor for managing the pieces that make up a typical web page. And that can include things like forms and interactive charts and so on.
For that reason, PeakZebra uses the block editor as the interface for any clients that want to build or customize their own pages. They are otherwise shielded from the potential confusions of the WordPress back end.
But while the block editor is good for making a page that looks like part of an application, you have to ask the question: what happens when something is supposed to happen.
Enter logic
For “normal” form processing, PeakZebra justs handles putting any updated values from forms on the page into their appropriate database records. For use cases where you’re just tracking data (what’s this client’s mailing address?) that’s surprisingly powerful all by itself. If you use address fields in a form that gathers client information, for example, simply submitting that form ensures that the data winds up stored in the right table.
But what’s needed beyond that is a (relatively) easy way to make more complex interactions happen. I think what you need is some kind of logic block that’s configurable in the editor–you give it a set of instructions through some kind of GUI–and presumably not visible (though present and ready to do its work) in the front end.
Alternatively, you could simply make it possible to attach actions or code to each element of a form or other block and tie them to specific actions (onclick, for example), in pretty much the same matter that HTML lets you attach JavaScript to element events.
The lotsa-pulldowns approach
While Bubble and other no-code platforms use a sort of “assemble instructions by clicking options” approach to attaching procedures to elements, I’m resistant to this, even with a client base that doesn’t really want to code.
That’s because it quickly becomes nearly impossible to keep track of what’s going on (or what’s going wrong) because you have to go back through all the options you selected in that visual interface, plus you can’t get any coherent overview of your whole application’s logic flow. (Actually, maybe one or another of the no-code options handles this well–I’d love to get a heads up on that.)
So it’s tempting just to make it easy to insert plain old code snippets into a logic block that essentially just exists as a container to put that code in. This, of course, means people have to code at least a little in order to take advantage of this.
One ecosystem divided by two languages
In the WordPress world, this approach gets more complex right out of the gate because, of course, WordPress uses two separate languages: PHP on the server and JavaScript on the client side. So should the logic block handle one or the other, or both. And does this increase the complexity sufficiently that this just can’t be termed “low code” anymore.
I’m tempted by the idea of creating a highly-simplified language for describing what should be done, like:
see if zipcode begins with “19”
if yes, set timezone to “EST”
And then this would parse back into _either_ JavaScript or PHP, as appropriate. Sounds so easy, right? What’s a programming language but a huge nested if statement, amirite?
Let’s be real, or else let’s use AI. It’s magic.
Sure. However. Given that this is almost certainly way harder than it sounds and would be a constant source of annoyance while the kinks were ironed out, I then begin to wonder whether AI is the answer. It’s the answer for everything else, after all.
And this actually does seem plausible, given how good copilot style programming assistance AI has gotten. You’d just need to train the AI on the specific codebase, something that Cursor does already, though I haven’t tried it yet to see if it actually “gets” a WordPress code base.
But I don’t think, for the moment at least, that AI is really the answer. And that’s because experienced developers bring some important horse sense into the game.
Horse sense to the rescue
It’s pretty easy to design a system that does something that is error prone and non-scalable from the get-go. If you talk to a developer who really understands the code base and what you might be trying to do with it, they can help you see if you’re really tackling the problem in the right way, with the right approach.
In other words: maybe you could get the count of the number of tasks associated with a project by counting the tasks associated with that project in the task table, but maybe it’s better to keep a running total that the system updates whenever tasks are added or subtracted from the project.
You want someone at least looking at this from a perspective that has the whole picture in view.
For the foreseeable future, this is how PeakZebra handles these things: by request. Your request to do X or Y is handled by a real, human programmer who is familiar with the PeakZebra code base as well as the WordPress platform (from a technical perspective).
It occurred to me that I’m so bad at thinking up witty little bits to post on Bluesky that I’d probably do better writing a five-hundred-word piece literally every day and then “skeeting” (as they say on Bluesky, though I have no idea why) the address and topic. I’d have something to say, sort of.
And writing at a steady pace (something I haven’t done in quite a while) means I can do something that’s more my style in terms of building in public. That is, I can get into the weeds on code and WordPress particulars and also talk about some startup decisions more or less as they happen.
The good
I’ve been working away on one version or another of PeakZebra for something on the order of three years now (depending on how you count). This is a terrible way to launch a solo bootstrap business, just in case you were wondering. I think people get problematically cultish about shipping as fast as possible sometimes, but for the most part I do believe it’s a good idea to come up with a business idea that’s relatively small and self contained, at least as far as creating it. Didn’t manage it myself, though.
But the good thing of late is that the vision is considerably clearer and, as I’m putting the pieces together, I’m pleased that some of the pieces that go back fairly far in that three-year period work just fine as I’m integrating them with new pieces. This wasn’t necessarily going to be the case because the framework I was developing for–WordPress Gutenberg blocks–was a moving target the entire time.
It’s funny, when fixing bugs in that older code (because, um, there were a few) to be reminded that, to take one small example, you used to have to enqueue any JS files you were going to use on the client side of your block. Nowadays you can just use a render.js file that you list in your block.json file. All sorts of other minor details have been streamlined in the interim.
And pieces are coming together. I have a test platform that, I guess because I think of it as a blueprint site, I call mrblue. I give my local sites dorky names. The offline version of this PeakZebra.com site is currently totally.local.
The less good
I spend a lot of time wondering whether I’ve gone down the wrong track with the idea of enabling companies to build internal tools on a WordPress platform. That’s in part because I more or less arrived at this goal within an almost entirely WordPress context and I didn’t really dig into all the options that are out there.
I was aware of most or perhaps even all of the no-code application builders that are used by people trying to build no-code startups, but I didn’t really take the time to see what kinds of services were specifically targeting the internal business market.
Setting aside the various things that you can do with customization in Salesforce, there are also quite a few companies that specifically target enterprise internal tools.
Checking these various products out has been kind of depressing, because some of them are very polished and very capable. At least one of them, Budibase, is open source.
So far, though, they are all really most suitable for enterprise use, and I’m more interested in the tiers below that. They are also, accordingly, a lot more expensive. I’m not trying to be the low-cost purveyor, but what I really think is the case is that these other products are really playing in a different product category. I genuinely don’t see PeakZebra tackling the enterprise world anytime soon.
The storm clouds overhead
Meanwhile, Matt Mullenweg seems to be trying his dead-level best to seriously undermine the WordPress economy. I’m not going to make this a forum for my read on the #wpdrama, but what I can say is that I’ve shifted my strategy for going to market with PeakZebra so that I can get closer or farther away from WordPress. More on that another time.
While your first encounter with PeakZebra may catch you a little off guard, especially if you’re coming from a WordPress background, the ideas behind it are actually very straightforward. Which is what makes them powerful, of course.
Halfway with Forms
Particularly in the WordPress world, there’s this notion of an add-on called a “forms package.”
A forms package lets you create forms, needless to say. These forms are presented to users on the front end of your site and when they fill them out and press the submit button…
Actually, that’s where the capabilities of a forms package begin to peter out. In the simplest instance, the data from the form will be plopped into an email in text format and sent to a pre-configured email address (your address, roughly speaking). What happens to the data at that point is your problem.
If all you want to do is toss the name and email into an email mailing service, then that’s likely to work just fine. Most of the larger such services are integrated enough with the dominant forms packages that they can pick up new entries without manual intervention.
There are also forms packages that offer the capability to dump all your form responses into a database table. While that’s a start–and it might even be ok if you only have one form active on your site–but since it literally dumps the data from every form into the same data table, what you typically wind up with is a jumble that you have to sort out by hand. It’s a feature that I don’t really believe anyone with more than one form actually uses.
Enter the Table
Out in the world beyond WordPress, there are several options for ad-hoc applications that start with a table. The original example of this is arguably Google Sheets, even though it’s a spreadsheet, not a database table, strictly speaking. A lot of people use it strictly for columns and rows of data, though. Plus it’s easy and automatic to connect a form (one form, and you can’t control what it looks like) to a table. A more purpose-built version of the same thing is Airtable, which gets an enormous amount of mileage out of good looks (though you can’t change them much) and support for a whole lot of bells and whistles (scripts, automations, widgets that aggregate data and chart it).
The Initial Insight: Known Tables
PeakZebra combines the forms package and better-structured, more “Airtable-like” tables. In a departure from other tools out there, PeakZebra starts with a set of pre-defined tables. This has a couple of advantages. First, it’s faster to get going (it’s also just plain faster) because you don’t have to create fields for obvious things like “city” or “email”.
Second, it makes it easy to tie form fields to the tables. So in PeakZebra, if you add a text field to a form, you can pick which table and which table column you’re connecting to that instance of the text field input. If you want “city”, you just select it over in the right-hand-side column with the various configuration options for that field.
A third, huge differentiator for PeakZebra is that using known tables means we can supply various templates for different kinds of applications and they will–because they are tied to the same underlying tables–be inherently interconnected.
Second Insight: Fields are Blocks
The pages you visit as part of a PeakZebra application are built with the WordPress block editor, using blocks.
Of particular instance, when (and if) you build custom forms as part of your application, each field and each button is a block. So you have enormous control over what your form looks like and how it performs.
Third Insight: It’s Not that It’s WordPress
It runs on WordPress, but what matters is that it runs on a WordPress that provides you with your own SaaS service. So you don’t have to “run” or “administer” WordPress. You just use your customized service. It’s SaaS, but ultimately it belongs to you.
There are plenty of long-time WordPress professionals who will tell you that WordPress is too complex for its own good. I don’t agree, but I’ll readily concede that it’s very confusing to get started with, even if it does offer a lot of power and flexibility.
Thus, while a PeakZebra instance is running on WordPress, the idea is that you’ll be largely unaware of this. You never log into the “admin” side of WordPress (unless you know your way around and want to do something unusual). If you opt to edit the pages of your applications, you’ll be doing so in the WordPress block editor, but in a cleaned-up version that prevents some of the confusions that have made some people less than thrilled about the interface.
In short, even if you’re the admin for your instance of PeakZebra, you don’t have to be the admin on the WordPress instance running behind the scenes. You show up to the website as a user. If you’re the admin, you show up as a user with access to PeakZebra admin functions (adding a new team member, for instance).
Thus
The core ideas that power PeakZebra are pretty simple at the end of the day: tie forms and tables together from the get-go, build the forms from standard block components, and use the strengths of the WordPress platform without forcing people to learn WordPress just to take advantage of the good stuff.
I’m banging away on what I guess you could call the second sprint of PeakZebra blocks (except that it’s just me, so it’s a pretty thin scrum), but it’s hard to work on applications like CRM (built from blocks) without thinking about onboarding.
Onboarding is an enormous opportunity for WordPress, just because so many (including the core team) do it poorly or, more often, not at all.
If you are brand new to it and load a fresh install of WordPress on that hosting account you just signed up for, you’re almost certainly about to be royally confused. There have been a couple of slight improvements in the 6.3 release that just came out, but basically you end up looking at the admin back end, perhaps without even knowing that there is such a thing, and if you find your way to a view of the front end, you’ll be wondering how you accidentally loaded a “blog about philosophy” when you were trying to load a blank WordPress site.
If you survive this onboarding (designed to weed out the folks with no grit), dealing with new plugins can be rough, too. Most of them just load and then wait around for you to find the configuration page and do something. Some of them are clever enough to go ahead and jump to that page, but you may have very little idea what you’re supposed to do at that point and what effect different settings will have on your site.
Yes, there’s lots of documentation, but the prevalent experience in the computer and internet world these days includes at least a little in situ onboarding. There are surprisingly few tools for this in the WordPress space.
Now, I’m as big an offender as any, at least so far. But I want to work on making it easy to get rolling with the fairly large set of blocks I’m putting out into the world.
And it occurred to me, maybe each of the primary blocks should be capable of creating a popup that can be customized to provide an onboarding experience. There are a few key variables in the PZ block system that are essentially persistent (for a session) global variables, so why not have one that tells the block to do the onboarding thing.
I haven’t built this into blocks or given it a test to see if it really provides anything useful, but I think I’m going to try to sneak at least a small test of the concept into the current, um, sprint. I’m letting all the scrum members know about it right now.
Here are the slides from my presentation at WCPHX, Using Blocks to Build Applications. Note that most of the presentation was a live demo. I’ve included the backup slides I made in case the demo went south– a series of screen shots that captures much of what I showed.
A lot of the third-party activity around blocks these days is centered on putting together sets of blocks, and one of the more widely used sets out there is Kadence blocks, which has a free and a pro option. For a recent project I spent quite a bit of time working with the Kadence Pro Blocks set. So I have some views on the Kadence block set itself, but it also brought me to some realizations about the state of WordPress blocks in general.
The takeaway is that Kadence blocks are mostly good at what they do, though a couple of the fancier blocks have some rough edges that gave me fits trying to bend them to a particular design I’d been given. I’m going to tackle my discussion of the world of Kadence this in three parts. (Previous looks at other block sets are here and here.)
In this post, I’m going to talk as much about why you want to move beyond the core blocks that WordPress installs with and why block sets like Kadence’s include “copies” that seem to do roughly the same chores, like adding headers and images. In the second, I’ll drill down on some of the blocks in the set that are common in the world of “fancy” blocks, like testimonial sliders and masonry displays of blog post titles. In the third, I’ll look at some of the blocks that, while they may not be unique to Kadence Blocks, are nevertheless not as common (and we’ll look into whether they’re worth the trouble or not).
Replacing the core blocks with Kadence blocks
One great thing about Kadence blocks is that the free version has all the same blocks as the pro version, as far as I can tell. If you bump yourself up to Pro, some of the blocks do more complex things. For example, the Advanced Text block will give you the ability to add text from dynamic sources.
As with other collections of blocks, Kadence has a group of blocks that are improved versions of things that come stock with WordPress, but it also has a group of blocks that are more the sort of thing you get with pre-block-editor page builders. In the first group are things like Advanced Text and Advanced Image. In the second group is a Testimonial block, some options for displaying blog posts in masonry format, and other odds and ends like a Timeline block.
In the project I mentioned above, I needed to match an agency created design fairly closely, so exact font sizes and content widths and so on became issues. While I have in the past been somewhat suspicious of block sets that seem to duplicate much of what the native WordPress blocks provide, the need for better blocks was something that the project hammered home for me.
Group and Section and Full-Width Designs
Let’s talk just about organizing basic layout issues. If you’re trying to do something even remotely better than just dumping blog posts down the middle of the page, you are almost immediately pushed out of the supposedly no-code WordPress block editor. So here’s a Canva website template:
It’s an image with some text and a button laid over it. If you swing a dead firefox on the internet, you’ll hit a page that has this.
Now, that’s a full-width image. To get a full-width image in native WordPress blocks, the simplest approach is to insert an image block and use the menu to set the block to full width.
That’s easy peasy, though the block editor doesn’t really show you the full-width result (there’s a way to make it look more like the finished widescreen result, but I’ll save that for another post):
Now, you probably already realize that we’re stuck here. You can’t overlay text blocks on Image blocks. So you want to do something like put this image inside a Group block as the background of the Group. Alas, you can set the color of the background, but you can’t use an image.
Cover Block, anyone?
You’re already thinking to yourself: There is a native block designed for this sort of thing: the Cover block. With the Cover block we can put the picture in the background and put items such as columns and text as an overlay to the picture. The block throws in a couple of extras as well. You can, for instance, have a color that overlays the picture. In this example, I’ve got a black color overlay at around 40% opacity:
This isn’t quite right, compared to the original, though it’s close-ish. The button in particular is wrong compared to the original. And the original button, to my eye, is way better looking.
There’s also the matter of the fonts not matching the design. In this particular example, the main text is a fairly generic sans font, so the default sans font in the WP theme I’m using is a reasonable substitute. The company name in the upper left doesn’t grate too much, either, but it’s wrong if you look at all closely.
In a situation like this, the solution lies in setting the right default fonts for the theme, which has nothing to do with either native or Kadence blocks. But there are certainly times when you need to throw in a one-off font – maybe a special landing page that uses entirely different fonts, or you need a crazy display font for the heading of an article. You can set a specific font for a specific block instance using either the native or the Kadence Advanced Text block, but the Kadence block makes it vastly simpler, largely because it gives you a dropdown of all the Google fonts, which is fine for an awful lot of use cases.
There’s another important thing wrong here that you can’t fix with native blocks, at least not in a no-code way, and that’s the spacing of the columns across the image. Note that in the original, the company name text slightly overlaps the main text below. My block version has the main text considerably further to the right. (It occurred to me as I was writing this that there’s a more accurate way to do this with native blocks where you use only two columns and align the company text left, but center the main text, both in the left-hand column. But that works more because it just happens to in this case, not because you actually have fine control over it.)
My point is that it would be nice to have some ability to drag the column widths. Thus: enter the Kadence Row Layout block. It does what the Column block does, but with considerably more finesse. We can go full-width with it and we can adjust the width of the columns on the fly.
But before we really get into it, here’s a nice example of things that are going to frustrate the crap out of people just plunging into the block editor, particularly if they used to use third-party page builders…
Let’s say that I want to keep some organization in place for the different parts of the page. To do this, I might decide to throw this piece of the page inside a Group block. So I insert a Group block and use the toolbar that appears atop the block to pick the full-width option.
Maybe I want a background picture for this area. Well, all the Group block does, really, is put a <DIV> wrapper around everything nested within the Group. That’s handy if you’re going manipulate the area using CSS classes. But we don’t want to do that, because we’re after a no-code editing experience.
Well, I can get a background image if I nest a Section block within the Group block, because the Section block supports it. The thing is, Section doesn’t inherit the full-width setting. Instead, it uses the inner content width for the theme. To my way of thinking, that’s not what you’d intuitively expect and you can’t set the Section block to full-width the way you can with other blocks.
Ultimately, this isn’t a problem, because we don’t actually need the Section block to get our background image in place, but it’s the sort of “one block does it but another doesn’t” aspect of blocks that can be pretty aggravating at times.
I said you didn’t need the Section block. You can instead use the Kadence Row Layout block, which you can set to full width and set up with a background image. Row Layout works like the native Column block, but has some bells and whistles. One really great addition is that you can drag the columns wider and narrower in five percent increments.
But ach, here’s another inconsistency: that dragging and resizing thing only works up through three columns. Bump it up to four columns and you’re locked into the default split. The Kadence documentation doesn’t spell this out, though there’s a new feature request that explains it. I was mystified as to when I could drag column widths and when I couldn’t.
For the sample page we’ve been working on, it actually made more sense to just have two columns, but I did drag the “person” part of the image wider so the text sat a little further to the left.
Space control in Kadence blocks (and elsewhere)
What separates the native blocks from sets like the Kadence blocks is some frilly blocks that do countdowns and the like, sure, but the thing that you really need better blocks for is margin and padding controls, plain and simple.
Consider a situation like this:
Some clever designer has placed a logo such that it overlaps the three-column block just below it. On the plus side, you can use the Advanced Image block Kadence provides and adjust the margin values so that the left margin is pushed far over to the right and the top margin so that it’s negative and pushes the image down into the next block’s space. In fact, the screen shot above is what it looked like in the editor after I had done that.
There are situations where this works just fine, but actually this isn’t one of them. That’s because Kadence wraps the <IMG> tag inside a <DIV> where it sets some of the classes it uses to set up default behavior in CSS. Without belaboring the details, it looks like this when published:
I thought, hey, no problem, I can just set the Advanced Image to align right. But that results in an image the size of a pinhead. There are ways to handle this sort of thing using the CSS translate/transform combo, but again, I’m trying to avoid having to muck around in the CSS.
Or, honestly, what I’m doing is manipulating the CSS directly whenever something tricky needs to get done. And that’s how it’s going to be for the near term and, who knows, maybe forever. CSS is the tool that’s built for these sorts of tasks.
Consistency needed
Right now, though, I think the issue is consistency across blocks. Is it Kadence’s fault if one of their blocks doesn’t handle stuff like negative margins? Well, yes and no. Probably there are things they could do to make the experience more seamless. But at the end of the day, there’s always (well, almost always—not in the advanced button control) an “advanced” section of controls that lets you type in a custom CSS class name, letting you tweak the block from CSS. Kadence makes it very easy to add custom CSS for a page or the site, in fact.
Specifically for relocating blocks relative to each other, though, I’d prefer if Kadence gave me direct control over the CSS transform property from within the GUI. Divi, quirky and old-school though it is in many ways, does this cleanly and even fairly intuitively.
But despite my first example being one that doesn’t actually work, having finer grained control over things like margins and space between lines in text and image overlays and so forth—all this is powerful stuff and once you find a block that does it the way you want, you’ll have trouble using many of the core blocks again. That’s the main point here: you can’t really do design work unless you control margins and padding on a block-by-block basis.
I have quibbles, but Kadence gives you that control, whether in pixels, ems, rems, or percentages. It also gives you a number of useful specialty blocks—a testimonial carousel, for instance—but we’ll tackle the good and the bad in these fancier blocks next time.
Let’s check out some more WordPress blocks. Third-party blocks.
On our last outing we looked at blocks that work together for a specialized purpose—JetFormBuilder, which is a forms package that builds forms using a block for each field.
The people that make the widely used Astra theme have built (and continue to expand) a set of blocks that help you build fancier, prettier pages than you can if you restrict yourself solely to the blocks that are native to WordPress. Initially, this set of blocks was called Ultimate Addons for Gutenberg (or UAG), but now it’s been renamed as Spectra.
By my count, there are presently 30 blocks in the package. Some of them are blocks that duplicate blocks in other third party collections (not surprisingly), but there are quite a few that are pretty interesting and that I haven’t yet seen elsewhere.
The time of your life
One block that lets you get a something pretty onto a page that would otherwise take a lot of work is the timeline block. I found it a tiny bit quirky, but it works just fine on the page. You add each date over in the context sidebar and then directly type your descriptive text within the block. You wind up with a series of stacked blocks connected by a vertical rule that fills with color as you scroll down through the timeline. It’s nice, and all the colors and backgrounds are configurable.
The Spectra timeline. The green line shows that we’re mid-scroll. Not sure it really adds any information, but it’s kind of cool.
There’s a “search” block that inserts exactly what you think it would, except that it’s a somewhat different design than the native block – it seems clear that an important aspect of many third-party blocks is going to be that they duplicate the basic function of a native block, but with some desirable design differences.
Heads up
Another block that I like a lot and that shows, I think, how blocks will add “behind the scenes” functionality without a lot of fuss and bother is the “Inline Notice” block. At one level, it’s just a design element that let’s you visually identify things like warnings and notices. And just for that it’s pretty useful and highly configurable. But an additional touch is that you can allow users to dismiss the notice by clicking on an X icon, plus you can cause this action to set a cookie to track how many days have passed since the notice was dismissed. If you set it for, say, three days, then the notice will reappear after three days. So you can let a user effectively say, sure, I got that, but when they come back six months later, you may think it’s prudent to show them the notice again as a reminder.
A table of contents block generates a box that contains links to all the header tags on the page (though you can set it to pay attention only to higher-level headers, H1 through H3, for example). You can configure the table to initial display collapsed, which is how I’d be inclined to use it. I’ve had to implement this sort of thing with plugins in the past and this certainly seems easier to drop where I want it without a fuss.
Schema
A final thing I want to mention is that there are three blocks that facilitate the addition of structured data to your pages. There’s a FAQ block that lets you build an accordion of the sort one sees everywhere, but it also adds structured data to the page meta as you build. I’m still going to charge extra for that, of course.
Another block lets you build a “How To” page that adds the structured data Google will be looking for—this is really a nice thing for those creating content that can take advantage of it. A similar block for product reviews makes sure you’ve added all the necessary schema components like SKU and brand and that you’ve included a product picture. If you’re bothering to do reviews, you should bother to do this. Which suddenly makes me think that these walkthroughs are, frankly, reviews. So I should use this block.
Mix and match
One thing I’d forgotten and been reminded of as I’ve started my world tour of the block-a-verse is that one of the big points of Gutenberg was to create a standard way for third-parties to create interoperable blocks. And I mention this to say that in this new era, it will be totally normal for website creators to decide to use a few blocks from this set, plus another block over here, and so on. And a nice feature that a couple of the blocksets out there have added (including this one) is the ability to turn off the blocks you don’t want to use. Love it.
Final point: this group of blocks is put together by the people who make the Astra theme. They’ve sort of built on this by creating a direct interface to drop in fully designed page templates from the block editor. The world up there in the top bar of the editor may well become hopelessly cluttered over time, but I still kind of like that you can grab a page so effortlessly, then make all the changes you want to make it yours. That’s one of the things that I’ve liked about the Divi page builder—I like it here too.
Pressing the Templates button gives you the below interface for importing page designs and block patterns…
I’ve headed out on a world tour of Gutenberg blocks. Third-party blocks. There are starting to be quite a few of them out there, sometimes singly, sometimes in groups of layout and design-related blocks. Especially for the groups of them, you’ve typically got to pony up a few bucks to license them.
But one I ran across—JetformBuilder—is both free (though there’s a pro version for $39 (unlimited sites for $79) per year) and a nice example of how blocks let you go about some kinds of page creation in rather different ways. Experimentation ensued.
The product is made by Crocoblock, which I only recently learned is a Ukrainian company. They have continued to run the company (even make product updates) from the basements where they are taking shelter. I don’t want to shill the product, but on the other hand I can imagine you could do a lot worse in supporting these Ukrainians directly by purchasing a license or two (and I think you’ll get your money’s worth, too, but Sláva Ukrayíni!).
Forms with blocks
The easiest way to explain JetFormBuilder, I think, is to just call it a block-native version of more traditional third-party WordPress forms packages like WPForms. You create a form and then you can embed it in your posts by way of a JetFormBuilder block with a dropdown that lets you select the form you want to appear.
What’s different is that you create the form within the block editor as well. There’s a custom post type for forms, the difference being that when you publish a form post, it’s just saved. Each field is a block. When you want to embed the form in a page, you use a block to place one of your previously created CPT forms.
What makes JetFormBuilder especially interesting is that it gives you a bunch of options you don’t generally get with the free versions of other forms packages. For one thing, you can store your form entries on the site (WPForms makes you upgrade if you want more than an email of the filled form). You can add multiple actions on form submission without upgrading.
You can create multiple-page forms. You can create fields that display calculated values. Indeed, that last bit means that you can create calculator-style tools for site users that aren’t possible in a typical WordPress forms package.
Let’s base a little calculator project on a block that allows you to hide or display fields on a form based on previously entered values.
Before we do that, let me just say that I’m not going to use this article to dig into what extras you get if you pay for the license. It’s a fairly long list of things and, if there’s interest, we can dig into that on another occasion.
Dog years
All right, project time. I want to create a calculator that allows people to determine their dog’s age in human years.
As you know, no one can ever quite remember how many years you’re supposed to multiply the dog’s age by. Is it 3 years? Is it 7 years?
If it were, say, 3 years, then you could have a form field for the dog’s age, then a calculated field that multiplied the age field by 3. That’s trivially easy to do in JetFormBuilder.
Alas, I think the reason no one can ever remember what to multiply by is that, well, that’s not actually how it works, at least according to the American Kennel Club, which uses this chart:
Table that shows human-year equivalent for a dog’s age.
Yeah, so people years are harder to come up with than simply multiplying by a number. We have to take the size of the dog into account. Of course it’s easy enough to ask what that is, but the real problem is that this chart doesn’t move in predictable increments. Giant dogs age slower in human years the first couple of years, then age faster than other dogs. The other three sizes age 15 years in year one, then 9 in year 2, then 4 years for each of the next 3 years.
If this is unclear, spend a couple minutes with the chart trying to derive a rule for how to convert years to human years–you’ll see what I mean.
Since the human age varies on a cell-by-cell basis, you need a table-driven way to retrieve and spit out the answer. You can imagine loading an array and then using two form fields to determine the right indexes into the array.
But there are no arrays in block forms. You can’t do this the easy way.
Thing is, even if it’s not straightforward, it’s at least possible. Color me impressed. Not one line of code gets written, and you wind up with a calculator that follows some wonky, non-mathematical rules.
Now you see it
My approach hinged on the conditional container block that JetFormBuilder includes, the one I mentioned above, which is visible (or not) depending on some other field’s value. I include several such containers, each containing a single field: a radio button selection of the dog’s size.
Which version of the size selection radio button you see is determined by which age you input. There are a bunch of different ones, but you only see the one corresponding to the age you entered and all the rest of them are hidden.
For the radio button you do see, there’s a value associated with each of the options. In other words, there’s the label or text you see, like “Giant,” but there’s also a value attribute, and I set the value for each option for a given age at the appropriate number for the size of dog.
In other words, if you say your dog is two years old, you see the two-year-old version of the radio button field. In that version, the value for the Giant dog selection is set to 22 and the other sizes are set to 24 (these come from the American Kennel Club’s chart).
Elsewhere in the form, I have a calculated form that simply takes the value associated with the selected radio button. So if you said your dog was 2 years old and then selected Giant, the number 22 is displayed in the calculated field. (In other words, in this case it isn’t really calculating anything, it’s just pulling in a value from another field and leaving it be.)
Effectively, each different version of the radio button field functions as one row of an array of year equivalents. It’s a little clunky, but when you work with it on the page, it’s shockingly clean because you aren’t aware of any of the multiple versions of the radio buttons that you don’t see.
I suspect you can do this sort of tomfoolery and come up with all sorts of ways to get real-world worksheets and calculators to work, which I find very intriguing. So, just by way of showing that it does in fact work, here’s a rudimentary version of the form that only handles years 1-4 (I got tired of duplicating the conditional radio-button blocks–indeed, it’s a bit of a kludgy hack as far as making a calculator goes, but it does work and, to be sure, something that was actually calculated rather than looked up in a table would be a fair bit more straightforward).
My initial thought was that the conditional field capability could be used to perform another bit of magic: progressive form fills.
A progressive form fill is a process whereby you only bother a site user for a piece or two of new information per visit, but you ask different questions each time around and eventually you have a fully filled form.
The first time a user shows up, for instance, you might ask for nothing more than a first name and email. If you were implementing this from scratch, you’d probably tie the process to a cookie on the user’s system, but in this case let’s assume the return user logs in (or, perhaps, stays logged in because of a cookie).
Let’s say there’s a private page each user is redirected to as they log in. There’s a form embedded in that page and what the user sees is something like “Welcome back – can we just ask two quick questions?” and then the two next questions.
I was wrong about Jetformbuilder being able to do this, though, and I mention it because the underlying reason is worth thinking about. Like other form packages, here we have form definitions (which happen to be made out of blocks) and then, as a user submits a form, the data is written to a row in a table of entries.
This is what you’d expect, but it means that, in the normal course of things, each time the form is filled, it’s a brand-new entry. As a nice extra, it actually is possible to prefill some limited information from the user account (like the user’s name) into a form, just to speed up the form filling process for users. But each entry is still filled de novo.
This is what you’d expect—I’m not knocking the plugin for being set up this way—but it’s interesting to contrast this to the way that data attributes in blocks are natively handled.
Let’s say I create a custom block that has an HTML form embedded in it (by way of React createElement calls). When you add that block to a page within the back-end editor, you’ll see a form. If you’ve set up the block to save the attributes you’ve associated with your form fields, then when you update the page, the data in the fields will be stored. Next time you come back, the data will be there. Additionally, you can use this saved data as part of what’s displayed on the public-facing page.
To take an obvious example, you could create a company address block that the page creator could fill in with an address when they added it to a page. When people viewed the page with the block in it, they’d see the address.
I’m spelling this all out because I want to point out that, should you happen to use this address block on some other page you’ve created, the address you entered before will not be there. The address data within your custom address block is stored with the instance of the block that’s within the individual post you’ve created.
Block data, unless you do something to make it work differently, works like custom fields within posts. Each post has different data. Indeed, you can build applications by treating each individual post as a record within a database table. (And of course that’s what the core of a post actually is: a row in a SQL database table.)
I think that blocks that do things and that store things are going to be where the really interesting developments in WordPress will be found in the next couple of years. JetformBuilder is interesting because it lets you build forms, and you get a lot of value even within the free version. But it’s probably just the tip of the iceberg as we move forward.
Just to be clear right up front, this is not an article about customizing the back-end dashboard that WordPress provides to system administrators. This is an article that captures my journey in creating a WordPress client dashboard to show various kinds of statistical progress to PeakZebra clients. These folks don’t care how many page views the PeakZebra.com site is getting. They care about monitoring how things are going in their consulting engagement with me.
When someone becomes a PeakZebra client, typically they are working on a content marketing project. As often as not, they’ve been browbeaten about how important SEO could be to them and they feel a little guilty about not having done much of anything about it.
So the first useful thing PeakZebra can provide them is a specific plan for content and for whatever SEO benefits we think might be realistically achieved in the coming year (the world is filled with people who wildly overpromise what can typically be achieved with SEO, but that’s an article for another day).
That plan is stored on PZ, accessible only to them through their client login. Additionally, I want clients to be able to see how things are going month over month. And my experience has been that almost all the details I care about in SEO program execution are things they simply do not have time or energy to be bothered with. So I need to show how things are going and do it sticking only to the most useful metrics, showing them in a visual format that makes them very quick to digest.
What I need, in other words, is a WordPress client dashboard. You know, green light if things are good and let’s hope the light is never any other color than green.
This turns out to be relatively simple to achieve, but maybe not quite as simple as you’d think. Today’s article brings you the gory details of the first pass I took at this, working within the context of the Divi page builder for WordPress. In a follow up coming in the next few days, I’ll walk through the path I took after I decided I needed better graphic and table tools, which then meant I didn’t really want to use Divi because I was happy with the look without it.
Easy-does-it WordPress Client Dashboard
To make things easy, at least initially, I decided that the dashboard wouldn’t directly query data in realtime. Rather, there would be tables on the site that were periodically updated, and it’s the data from the tables that winds up displayed in the dashboard.
Second, I absolutely needed to prevent a client’s dashboard from being visible to anyone but the client and myself (and authorized contributing team members). I wanted to keep that simple as well, about which more toward the end.
One final thing for simplicity’s sake the first time around: I’m just going to make each client’s dashboard a regular WordPress page. That way the dashboard pages are just ordinary pages, meaning I can throw in whatever page components I like (assuming we’re using Gutenberg or a page builder like Divi).
This isn’t really how I think this should be done. Rather, the “real” way to do this is to create a custom post type, probably called “dashboard,” with each client having a post of that type. That’s by no means complicated, but we’ll hold off for now.
Data
In order to show the data, we need a plugin that, ahem, turns data into pretty charts. And I want to stress here: if you’re bothering with charts, pretty is almost certainly a hugely important part of the deal. We want pretty.
There are a bunch of plugins out there that will take data and spit out charts. The popular page builders that web designers often use with WordPress these days also have at least some elements that lend themselves to showing data, which is what sent me down this initial route to have a look at what the Divi builder (the one I have the most experience with) could do.
Mixed results, honestly. To be sure, I can build a Divi dashboard that looks pretty darned good. But I did have to hunt down a couple of extra tools to get it done.
All by itself, you can’t do much that looks “dashboard-y” in Divi. It will let you show numbers as a single bar, as you see here:
You get as much satisfaction out as you put effort in.
And you can throw in animated circles with numbers in the middle of them, of the sort that you’ve seen on a million landing pages:
It’s almost the answer to the universe.
Honestly, I think they both look nicely professional, but we’re going to need some more stuff, goodles like bar charts and spider graphs and maybe color-coded maps.
Send in the Charts
In fact, you can get these in Divi by investing less than ten bucks (assuming you already have a Divi license, which is a larger expense) in an add on available through the Divi Marketplace. In the interest of responsible journalism, I picked this up and gave it a whirl:
Peace is the thing with feathers.
In addition to this line chart, there are six other chart types—all basic stuff like pie charts—and each of the chart types has some degree of animation and interactiveness, such as popups that show the values on the line as you hover over them. You can flip the chart into several different predefined palettes, or override the CSS to set your own colors, or go with monochrome.
It’s actually not bad, except for one thing… Putting the data in is a bit clunky, in that you bring up the properties box for the graph and then input comma separated values for each data plot. It’s not terrible for something with a dozen data points, but you’re not going to want to do anything big or fancy with this.
The only way to update the data is to go back into the properties and hand edit (or paste over) the data. This seems like a deal killer for many sorts of projects, where you’d like to suck up a spreadsheet in one go, or maybe query a REST API for the latest data.
If you need something that’s very top-level and that you can just edit now and then as the need arises, you could build a pretty professional-looking dashboard with this.
This won’t help you if you need to place tabular data somewhere in your dashboard, of course. For that, the simple answer (with or without Divi being involved) is the TablePress plugin.
I like TablePress. It’s a robust, simple tool. You can get the data you want from a .csv or Excel file (and from a couple other source types as well), suck it up to your WordPress site, where it’s assigned a shortcode, then embed the shortcode in the page where you’d like it to appear. The results look pretty decent as long as you don’t have too many columns. Too many columns makes for a complete mess.
You can embed a shortcode directly into a Divi page, no problem, and that includes TablePress charts.
If the table you get from TablePress by itself, though, isn’t dressy enough to suit you, it’s possible to add in an additional plugin called TablePress Styler, sold at Divi creator’s ElegantThemes.com website for $35. I haven’t really dug into it, but I suspect that most of the things that TablePress Styler does are done simply by manipulating the CSS associated with classes that are set up in TablePress itself. Meaning you could do lots of the styling yourself for free.
But TablePress Styler makes short work of making a table look quite fancy, no question. If you’re going this route, I’d recommend it.
Except…you might want to handle your tables with the Visualizer plugin, which will give you both charts and basic table capabilities. The free version gives you six chart types; popping for a $99 “personal” license gets you an additional nine chart types, email support, and periodic synchronization with either .csv files or JSON endpoints (full pricing information is here).
This last part—the data sync-ups—strikes me as the thing that might make it worth a hundred bucks. If you set it up using this feature, you can update your underlying spreadsheets and not worry about the dashboard keeping up, because it will do that on its own.
By this point, though, the bulk of the dashboard is being supplied by plugins that have nothing to do with Divi. So whether you bother with Divi (or Elementor, or any other page building tool) really comes down to how much control you want over the design of whatever else is on the page, whether you want fly-in graphics or accordions with icons that rotate as the sections are revealed and all that other “fancy professional design” stuff.
By the time you get the charting and table plugins involved, it’s kind of an incidental detail that the page was made in Divi. Indeed, the argument could be made that Divi isn’t really doing all that much here. If you get the sense that I’m about to abandon the Divi approach, you’re probably right.
So, yes, to be clear: I by no means want to imply that Divi is the way to do a dashboard. Truth be told, Divi can be pretty quirky (though it can also produce beautiful WordPress results) and there’s some question about which of the WordPress builders will survive the introduction of blocks as the essential design element of WordPress running natively (which, roughly speaking, makes WordPress itself a page builder).
To get the same sorts of graphs I discussed up above, you can use any of a number of WordPress plugins, some of which provide block support. A walkthrough of this approach is coming in a week or so.
And, yes, I did say I’d talk about gating access to the dashboards so that only the client can see that client’s dashboard. The short answer is that you can do it using the PublishPress Permissions plugin. There’s also another approach with fewer moving parts—next time…