Styling Your Confirmation Messages and Broadcast Emails

The latest update to RSVPMaker focuses on more design freedom and better consistency for confirmation messages, reminder messages, and email broadcasts.

This push was inspired in part by a recent post on the SendGrid blog, How to Send On-Brand Confirmation Emails (+ Examples). Having noticed some shortcomings in the formatting of RSVPMaker email messages (which were annoying me as much as anyone), this project had been on my todo list anyway. The examples in SendGrid’s article nudged me to put it at the top of the list.

Here’s an example of a confirmation message for a wedding, created using these new capabilities, with the correct formatting for a section laid out using the Gutenberg columns block and a centered image below the spot where the registration details are included:

A styled confirmation email
Continue reading “Styling Your Confirmation Messages and Broadcast Emails”

How I Learned to Create a Gutenberg Sidebar for Editing Post Metadata (Tips for WordPress Plugin Developers)

More than a year after releasing the first version of RSVPMaker with support for Gutenberg (the WordPress “block editor” introduced with 5.0), I now have an editor sidebar implementation I’m pretty happy with.

In the process, I learned more than I ever wanted to know about the WordPress Data API for JavaScript — and frankly more than I needed to know for the relatively simple thing I wanted to accomplish. I just wanted to update my old PHP-based UI for getting and setting post metadata to work in Gutenberg. The problem is not just insufficient documentation, but overwhelming documentation that can lead you in a wrong direction.

What you see below is a composite image of 2 screenshots.

What you see on the left are the most basic RSVPMaker settings (when does the event start and end? and are we collecting RSVPs?) as they’ve been added to the Document tab of the standard Gutenberg sidebar. I do that to make these basic elements of editing an event date as accessible as possible.

The insert on the right shows an additional sidebar, specific to RSVPMaker, that I can get to by clicking the calendar icon at the top of the screen. This additional sidebar provides access to a longer list of RSVPMaker settings: not just date and time, but also the email address to send registration notifications to, whether there is a maximum number of registrations to be accepted, and so on.

There are still a few more complex settings, such as those for event pricing online payments, where I direct users to a separate RSVP / Event Options screen. But I want them to be able to accomplish most tasks without delivering the editor.

The designers and developers behind the Gutenberg UI recommend providing a “distraction free” editing environment that minimizes the use of the old “metaboxes” at the bottom of the content editing window, which used to be a standard for WordPress plugin design. I also found that the JavaScript functions in my old metabox code seemed to clash with Gutenberg, so I got rid of metaboxes some time ago. But making those same capabilities available in a Gutenberg sidebar, rather than a metabox has proven challenging.

Gutenberg represents a steep learning curve for those developers who learned plugin programming in PHP and are now asked to master at least the basics of the React JavaScript framework and the Gutenberg component library. I hope that we will eventually be provided with some easier ways of handling common needs like setting the metadata of a post from within the Gutenberg UI.

Meanwhile, here are my tips on how to cope with the current state of things.

Continue reading “How I Learned to Create a Gutenberg Sidebar for Editing Post Metadata (Tips for WordPress Plugin Developers)”

Background Loading RSVPMaker Event Listings From Any Site To Any Site

Using the new widget and/or the new Gutenberg block that have been added to RSVPMaker 6.4.2, you can display a listing of events that will be dynamically loaded from your own site or any other site that implements RSVPMaker. This feature uses JavaScript and RSVPMaker API endpoints to fetch a listing of events in the background and display it in a widget or in the body of a page.

Widget loading an event listing in the background (GIF runs in a loop)

A separate RSVPMaker Widget plugin (see below) is available for sites that want to fetch listings from a remote sites without having the full RSVPMaker plugin installed locally. Or you can embed an HTML/JavaScript code snippet in a non-WordPress site to achieve the same effect.

Advantage of Dynamic Loading

One advantage of using this technique, even for displaying events from the local website, is it may work better with websites that have implemented caching. The client can be served a cached HTML version of the page but will still see a current listing of events because it is loaded in the background via a JavaScript call to the API endpoint.

Site visitors may briefly see a “Loading …” message while event posts are being retrieved.

API urls are in the format:
(all future events)

or wp-json/rsvpmaker/v1/type/featured
(events tagged with the event type “featured”)

RSVPMaker Widget plugin

A separate RSVPMaker Widget plugin is available for download as a zip file (and pending as a submission to the plugin repository). I have been using it on websites where the full RSVPMaker is not active or needed.

Example: a WordPress multisite implementation for a Toastmasters district, where divisions within the district have their own blogs but RSVPMaker is not active on those subordinate sites. Instead, RSVPMaker is active on the main domain, and division-specific events are designated with an RSVPMaker Type tag.

The RSVPMaker Widgets plugin allows me to display a listing of each division’s events on the division site homepages, while still maintaining a single calendar of events from across the district.

HTML/JavaScript Snippet

You can also embed events listing into any website, including static HTML sites and those that run a different content management system, using the HTML / JavaScript code snippet shown below. Change the div ID and the parameters for the creation of the widget object to match your needs and modify to taste.

On a WordPress site, you can use the Custom HTML widget or the Custom HTML editor block to add this code (assuming it’s allowed by your site security) as an alternative to installing the RSVPMaker Widget plugin.

PayPal Integration (REST API)

RSVPMaker now integrates with PayPal via its REST application programming interface (API).

If you previously set up integration with the older Express Checkout / NVP API method, RSVPMaker still supports it. PayPal also still supports it but is not adding new features to that version. You probably want to switch to the new method anyway because the user experience is better and more tightly integrated with your website.

The pay by PayPal / pay by credit card buttons will appear as part of the confirmation message when someone registers for one of your events.

PayPal payment buttons

Attendees who click on the PayPal button will get a pop up prompt inviting them to log in and pay.

PayPal login prompt

Those who prefer to pay by credit card can click one of the credit card icons (or the button on the screen above that says Pay with Debit of Credit Card) and be prompted for credit card information.

To obtain the required credentials for the REST API, go to and log in with your PayPal password. The developer’s dashboard allows you to register multiple sandbox accounts for testing and create an app for your integration. Creating an app just means you are generating the API access keys required for the integration with RSVPMaker. Just give your app a name, associate it with a sandbox account for testing, and click the Create App button.

Creating an App

Then copy the keys (the client id and client secret) for both the Sandbox (test) and Live versions of the app.

Copying the client id and client secret.

Once you have copied and pasted all the credentials, into the Payments Tab of the RSVPMaker settings, it’s a good idea to toggle the Operating Mode setting from Production to Sandbox. Create a sample event with sample pricing and test the integration. For testing, you can make payments using one of the sandbox accounts associated with your developer account on PayPal, which is funded by imaginary money.

Once you are satisfied that everything is working properly, go to the Payments tab in RSVPMaker settings and toggle the integration from Sandbox to Production to accept live payments.

Here is a quick video demo:

Recommended wp-config.php Debug Logging Setup

When people contact me with reports that RSVPMaker is misbehaving in some way on their websites, figuring out whether the problem is due to a flaw in my code and/or interaction with some other plugin is tricky business. This can be made more complicated by WordPress features that hide error and warning messages from being publicly displayed — a good practice, but one that can frustrate access to debugging information.

Here’s the debug logging setup I recommend adding to wp-config.php – so you can track down errors when necessary without them being publicly displayed:

@ini_set( 'display_errors', 0 );
// Enable WP_DEBUG mode
define( 'WP_DEBUG', true );
// Disable display of errors and warnings 
define( 'WP_DEBUG_DISPLAY', false );
// Enable debug logging to file, ideally outside of public_html
define( 'WP_DEBUG_LOG', '/home/mysite/debug.log' );
@ini_set( 'display_errors', 0 );

The debug file location will vary based on your server setup, but for example on my sites /home/mysite/public_html/ is where publicly visible files go, so /home/mysite/ is a more secure location for a debug log that you don’t want someone attacking your site to be able to access (bugs are sometimes opportunities for hacks).

Should come before the line that says:

/* That’s all, stop editing! Happy blogging. */

Note: these debug log files can grow large after a while, so you might have to periodically delete the file and then let it regenerate as new error and warning messages are generated. Then go try to perform whatever action wasn’t working for you.

On systems that include the Cpanel utility (or something similar), I typically use that to view and delete log files.

RSVPMaker Concepts and Terminology

The basic idea behind RSVPMaker is that every event is a post — an event post, rather than a blog post — meaning you use all the same authoring and editing tools, but event posts have a date and time associated with them.

When you add a new event post, you will be prompted to enter the date and time up front, along some basic details like whether you want to collect RSVPs (registrations). You can also use RSVPMaker to announce events for which no registration is required.

Once an event post is loaded into the editor, you can change the date and time using a calendar widget that appears in the sidebar (assuming you’re using the Gutenberg editor introduced with WordPress 5.0). To change other parameters, including pricing for an events you charge for, navigate to the RSVP / Event Options screen associated with each post.

Link to the RSVP Event Options screen

You will see several submenu options under RSVP / Event Options, which will take you to the screens for customizing confirmation and reminder messages and for customizing the registration form.

In RSVPMaker, your confirmation message is also modeled at as a WordPress post that you can edit as you would any other content. Reminder messages work much the same way, except that they have a specific interval relative to your event date / time associated with them. The reminder message headline becomes the subject line of the email message, and the body copy becomes the content of the email message.

The RSVPMaker form is modeled as a series of custom content blocks that specify the data you want to gather from each person who registers (details).

The RSVP Form editor

When you are editing a form, a confirmation message, or a reminder message, you will see a navigation option in the black admin menu at the top of the screen that allows you to navigate back to editing or viewing the parent event post. First, make sure you save your work.

Multi-Date Events and Event Templates

RSVPMaker allows you to create a single event that stretches across multiple dates — so one registration (if you’re taking registrations) for an event that lasts all weekend.

The more common requirement is to support events that recur on a weekly or monthly schedule, with many of the details repeated each time. For example, the local Chamber of Commerce holds a breakfast meeting on the first Wednesday of the month at a standard location, and the phone number to call with questions is always the same. We need to be able to account for occasions when the schedule or meeting place changes, and we want to be able to add details about a specific month’s event.

For that, use an Event Template. The template defines the standard meeting schedule and the details that should be included in every event listing by default. From an Event Template, you can create a series of events along the projected schedule (all those first Wednesdays in my example). Each of these events will include the content and the settings specified in the template, including details like event pricing.

Each individual event can then be edited individually, for example to add the names of a guest speaker. If the Event Template changes, perhaps because your standard meeting place has changed, you can update any previously published future events with the new details. (More about Events and Event Templates).

Many event parameters can also be changed on the RSVPMaker Settings screen on the WordPress dashboard. For example, you can specify whether the feature for collecting RSVPs should be on or off by default. A link from the settings screen allows you to create a standard RSVP form to be used if a custom one has not been defined.

The settings screen is also where you would enter the required credentials for the PayPal or Stripe payment services or the MailChimp email broadcast service.

Video: RSVPMaker Events and Event Templates

One of the keys to using RSVPMaker effectively is taking advantage of event templates. Like the rest of RSVPMaker, the templates feature has been updated for the new Gutenberg editor.

Templates allow you to create one or many events that follow a regular schedule and that share some basic details like meeting location and who to contact with questions.

Like a cookie cutter, a template lets you create many events that will start out the same — until you decorate them.

Think of it like the relationship between the cookie and the cookie cutter, where you can stamp out one or many cookies that start out the same, but you still have the option of decorating them all differently, with details specific to a particular event date.

On the other hand, if you’ve created many placeholder events based on your template and you change the template (say, because your meeting location has changed) — you can update those related events. You can update them all, or update them selectively (if you don’t want to overwrite information you’ve added for a specific event date).

Navigating RSVPMaker: Event Posts, Options, Messages and Forms

The whole idea behind RSVPMaker is to allow you to take advantage of the familiar WordPress user interface for content creation and editing, while adding the event dates and registration form options that allow you to display even posts on a calendar and/or chronological listing of events, collect RSVPs (or registrations) and charge for events when appropriate.

New Event

The latest versions of the software have gotten away from trying to cram all the options onto one screen — which I hope is an improvement — but it means you need to understand the relationships between the different screens available to you.

These include:

  • The Settings screen for RSVPMaker, which is where you can set defaults for most event options, plus settings related to email notifications, email broadcasts (Mailchimp integration) and payment processing (integration with PayPal and Stripe).
  • The Event Setup screen, displayed whenever you choose Add New for RSVP Events — prompts you to specify the date and time, plus some other key settings (RSVPs on or off?) before filling in the event description details. The Event Setup screen is shown above.
  • The event template variation of that same screen, used to define events that occur on some regular schedule (such as every Friday or first and second Monday) along with the defaults for events in that series (RSVPs on? etc.).
  • The WordPress editor — works the same as for any other post, but with a few RSVPMaker-specific controls in the sidebar and more available through the “admin bar” (the black bar that appears at the top of the screen when you are logged in as an author or editor).
  • The confirmation and reminder messages, which you also work with in the WordPress editor. Look for the admin bar menu items that allow you to navigate back to the parent event post.
  • The RSVP Form, where each registration field is modeled as a special block in Gutenberg. You can add or modify fields, including text entry, textarea, select, and radio button fields, and the optional guest data block.

Some of these options may not appear if you are not using Gutenberg, the new editor introduced with WordPress 5.

Here’s a visual tour:

Draft event

When you save your options on the Event Setup screen, RSVPMaker creates a draft post with the headline, event date, and other basic options set. You can now add whatever body copy you want your event post to have.

RSVP / Event Options link (and submenu)

More event options are presented on a separate RSVP / Event Options screen. When you are viewing a post in the editor or on the website (when logged in), you will see RSVP / Event Options as a link on the admin bar with several submenu items.

Edit Event link (and submenu)

When you are on the options screen, you will see Edit Event as a link on the admin bar with several submenu items related to customizing confirmation / reminder messages or customizing the form.

Default documents show link to RSVPMaker Settings.

You can set the default documents for Confirmation Message and RSVP Form from the RSVPMaker Settings screen. New events you post will use these default documents unless you create custom ones for your event.

You can also create templates for specific types of events, with a Confirmation Message and RSVP Form that may be different from your overall default but will be copied to all events based on the template. (More about event templates below).

Recommendations: Customize the confirmation message to include details people will need to know to attend your event, such as directions to the venue and a number to call with questions.

Change the RSVP Form if the default options don’t make sense for your event (for example, when registering attendees at a webinar, the guest fields probably aren’t necessary) and to gather additional information, such as the name of the person who referred the attendee to your organization.

Custom documents show a link back to the Parent Event.

When you create a custom Confirmation Message or custom RSVP Form for a specific event (or template), you will see options to allow you to navigate back to the parent event (in either viewing or editing mode) on the admin bar.

Customizing registration form fields.

When you edit the form, each form field is represented as a content block with properties including Label, Required, and Include on Guest Form displayed in the sidebar on the right hand side of the editor. (More about the form editor).

Link to create a template rather than an individual event.

To create a template instead of an individual event, look for the New Template link on the Event Setup screen. You can also go to the Event Templates screen and click Add New at the top of that page.

Setting a schedule, rather than individual dates, for a template

On the template version of the screen, you set a schedule rather than specifying a specific date. Unless you merely choose to say that the schedule “Varies” (meaning you’ll specify the date each time), the schedule will be something like “Every Friday” or “First Monday” or “Second and Fourth Tuesday.”

Create / update link displayed after saving a template.

After you enter your template content and save it, you will be prompted to “create / update events” based on the template. The template itself isn’t meant to appear publicly on your website and won’t be included on the calendar.

Think of the cookie versus the cookie cutter. The template is a cookie cutter, which you can use to stamp out many cookies and then decorate them individually. But you don’t eat the cookie cutter.

Templates typically include “boilerplate” details that are the same for all your events, or almost all of them.

Checkboxes to add multiple events based on a template.

The create / update routine allows you to create one or more events based on your template. Both the body copy for the event and the associated settings (RSVPs on/off, confirmation message, etc.) will be copied.

You can create many events according to your schedule and then add details to them as each event date draws closer. For example, you may publish a whole series of events for a club or professional organization, then add the names of speakers when you want to promote a specific event.

Updating previously created events, based on a template.

When you update your template, you have the option of updating all the events based on the template. An example would be if your standard meeting location changes, or you now want people to call a different number if they have questions.

RSVPMaker tries to warn you if any of those events have been modified independently. For example, perhaps we’ve added speaker or activity details to the April 12 event shown above. We might want to uncheck that one and make any modifications to it manually.

Viewing your events on the calendar.

If all goes well, the result is an interactive calendar that allows you to promote and organize your events more effectively.

New RSVPMaker Form Builder Based on Gutenberg

If you install RSVPMaker version 6.0+ and are running WordPress 5.0 or later, you will have the option of activating a new RSVP registration form that you can customize using Gutenberg, the new WordPress visual editor. One of the reasons I like Gutenberg is that it makes it easier to define visual components for content creation that happen to lend themselves well to many of my projects.

The new form builder makes it much easier to customize what fields are included, what the labels on those fields are, and the order in which they are presented, both for the person filling out the form and any guests included in their party.

As before, the default form asks for:

  • First Name, Last Name, and Email
  • A single phone number, with a drop down list for specifying whether it is a mobile, home, or work number
  • A section for adding the names of guests
  • A note field where the person registering can add a comment

You can delete any of these fields and add others. You can determine which fields are required and which ones should also show up in the guest section (if you’ve included the guest section).

Here’s an example of the default form for Online Presenters Toastmasters, a public speaking and professional development club that meets online and focuses on the skills you need to present online. There’s no guest section (that’s more appropriate for offline events like luncheons) but we gather some other information about our guests.

Online Presenters RSVP form

The only field that is absolutely required is email. You can change the label on that one, but a validated email address is required or the form submission will not be processed. Previously, first and last name were also mandatory — and they are still required by default — but you can now specify that they are not required, or not include one or both of those fields on your form. I’ve had people ask for the option of creating simpler forms where they may ask for just the first name or just a nickname, or just an email address and nothing else. Again, that might be appropriate for certain informal online events or for attracting a privacy-conscious crowd.

To see the available form components, type rsvpfield in the block chooser popup or enter /rsvpfield as a slash command on a blank line.

RSVPMaker form builder blocks

Like all content blocks, these form builder blocks have options specific to their content type. Typically, those options will be displayed in the sidebar on the right hand side of the page (if you don’t see it, click the gear symbol and select the Block tab).

Text field options:

  • Label
  • Required (yes/no)
  • Include on guest form (yes/no)

Textarea options:

  • Label
  • Required (yes/no)
  • Include on guest form (yes/no)

Radio Buttons / Select (Drop-Down Field)

  • Label
  • Include on guest form (yes/no)
  • Choices, separated by a comma

Mailchimp Checkbox

  • Label (defaults to “Add me to your email list”)
  • Checked by default (yes/no)


  • Limit (if any) to the number of guests per party
  • You can embed other form fields in this section if there is information to be gathered about the guests only. Example: An event for parents and children, where “Grade Level” is an additional field for the children on the guest list.
The Guests widget, with an additional field embedded for a question to be asked about guests, which will not appear on the main form.

By themselves, these blocks are not functional if included outside of one of the special documents created specifically define a form. They are not intended for use within the body of an event post or any other document. I have some ideas about providing a wrapper that would allow you to embed them in other contexts, but for now if you are looking at a document with a headline other than “RSVP Form” you don’t want to be including these blocks.

If you run into glitches with the form blocks not working as promised, let me know in the support forum on

Overall, I think this is a huge improvement over the system of shortcodes and the primitive form builder provided in earlier versions.

Form upgrade prompt (excuse the typo)

The new form will be used by default on new installs of RSVPMaker on WordPress 5 or greater. Existing RSVPMaker users will see a prompt to upgrade your form on the dashboard. Clicking the Upgrade link will install a new default RSVP Form:Default document, which you can then customize. This default will also be applied to any future events you have on your calendar. Sorry, any customizations you made previously will not be preserved, but I think you’ll find you can re-create them fairly quickly.

A Note on Navigation

Your RSVP form, confirmation message, and any reminder messages you’ve defined are stored as special RSVPMaker documents that aren’t meant to show up on the website. The default RSVP Form and confirmation message can be accessed from the Settings page for RSVPMaker. When you’re viewing one of these default documents, you will see a link at the top of the page to help you navigate back to RSVPMaker Settings.

The default form.

You can use the same default form for all your events, or you can customize the form for specific events. If you create a custom form (or confirmation message), you will see navigation at the top of the screen to allow you to get back to editing the “Parent Event” or visiting the associated screens for setting options and confirmation messages.

A custom form for an event (post ID 117528)

Updating Plugins for Gutenberg, WordCamp Miami 2019 – Video, Notes and Code

This presentation is built around the frustrations and payoffs of updating RSVPMaker and the WordPress for Toastmasters extension to RSVPMaker, as well as starting to create new functionality around Gutenberg, such as the My Marginalia plugin I created to help a client with the “show notes” she posts with recorded videos. Download PPT.

Whether you’re creating a plugin for the repository of a hack for your own website, Gutenberg may be able to help you make it better.

(For anyone not grokking the terminology, Gutenberg refers to the new editor that comes standard with WordPress 5+ and the more JavaScript-centric programming model that comes with it).


Gutenberg Handbook


Gutenberg Hub

Create Guten Block
Tutorials: CSS Tricks and Tuts+

HTML in My JavaScript

Here’s something I found confusing at first. Does this look like legal JavaScript to you?

JSX example from Create Guten Block

In fact, this is NOT legal JavaScript in the sense of being code that your browser would understand. This is the JSX template language, which originated as part of the React JavaScript framework created by Facebook. The idea is to allow you to specify a user interface in an HTML-like syntax that can also include functional components such as <RichText> to specify that an editable rich text field should be displayed at that spot within your application. For example, this is equivalent to instantiating a JavaScript class that will render the RichText component:

 setAttributes({ content })}

As part of the development process, we run this source code through a “compilation” step. You don’t compile your JavaScript down to a binary executable, but you feed it through a series of preprocessing steps that translate it into code that is intended to be understandable by all modern browsers and also optimizes / minifies it to download and run faster.

In the process, code like <div>my content here</div> turns into something like:

wp.element.createElement("div","my content here")

Using the Create Guten Block utility, you can create the skeleton of an application and then begin customizing it to meet your needs. You define your editor user interface within the block of code for the “edit” function and the code to be saved to the post in the “save” function.

You can use JSX in both the edit and save functions. Specifically, you use it within the return clause, after you have applied whatever processing might be required to decide what should be output in the editor.

The saved content that will be recorded to the WordPress database looks like this:

Source code for an image, as saved by the Gutenberg editor.

In most cases, what you are saving is legal HTML code wrapped in comments that define instructions to the editor for how this content should be displayed the next time it is edited. Within the opening HTML content, you will often see variables expressed in JSON format within the {curly brackets}.

Gutenberg blocks can also be used like shortcodes, in which case those JSON-encoded attributes will be passed to a PHP function that uses server-side logic to determine what should be output to the user. On the other hand, one reason for adopting Gutenberg is that it allows less server side processing, particularly when your goal is simply to format content in a custom way. You can do that with your save function and regular HTML/CSS.

Demo Code

Here’s simple example showing Gutenberg edit and save functions, plus an “inspector” component for the sidebar.

All this does is create a block in the editor and a save mechanism on the front end, with a custom headline and a line of text you can change using the sidebar component.


import './style.scss';
import './editor.scss';
const { __ } = wp.i18n; 
const { registerBlockType } = wp.blocks; 
const { Component } = wp.element;
const { InspectorControls } = wp.editor;
const { PanelBody, TextControl } = wp.components;

class DemoInspector extends Component {
render() {
	const { attributes, setAttributes, className } = this.props;
	return (
		 setAttributes( { message } ) }
}//end render


registerBlockType( 'wcmia/demo', {
	title: __( 'WordCamp Demo' ), 
	icon: 'shield', 
	category: 'common', 
	keywords: [__( 'Demo' )],
	attributes: {
	message: {
		type: 'string',
		default: '',
	edit: function( props ) { // UI for editor
	const { attributes, setAttributes, className } = props;
		return (

My custom block (editor)


); }, save: function( props ) { // format for storage / retrieval const { attributes, setAttributes, className } = props; return (

My custom block (editor)


); }, } );

We can give it formatting that will be applied both in the editor and on the front end with a style.scss file like this:

.wp-block-wcmia-demo  {
border: medium solid red;
padding: 5px;

Practical examples:

  • A custom format you define for product descriptions, executive bios, recipes or other content employed frequently in the context of your specific uses for WordPress. For example, I created a Floating Callout plugin for a callout / sidebar format used as an accent within a post or page. I had essentially been doing the same thing for years with snippets of custom HTML / CSS — but the plugin makes it easier.
  • A block of content that will exhibit custom behavior when viewed on your site, in combination with either front end JavaScript or server-side processing in PHP (more on that below).

Fussy Code

One important thing to understand is that the “save” function doesn’t merely save content to the HTML content of the post, as it will be stored in the WordPress database. When you retrieve the content, Gutenberg expects it to be organized the same way. If not, you will see an error.

Here’s an example that popped up while I was writing this post.

The unexpected or invalid code warning.

This apparently happened because I was having trouble with the display of my JavaScript code examples, which I recorded here using the Gutenberg component for displaying code. Ironically, Gutenberg seemed to be confused by the JSX examples. All the < symbols in HTML or component tags were being displayed as entity codes (<).

To get the code to display properly, I had to do a search-and-replace in Windows Notepad. That worked in terms of front-end display, except that Gutenberg would no longer allow me to edit those blocks as blocks in the editor.

Wrapping a Block Around Other Blocks

When you define Edit and Save functions using the InnerBlocks component, you can define a block that wraps around other content blocks (paragraphs, images, etc.). The code below is from My Marginalia, which applies special fomatting to the wrapped content. The Floating Callout plugin I mentioned does the same thing.

There’s also a “Limited Time” block in RSVPMaker that uses an InnerBlocks component in combination with server-side rendering to suppress the display of content that is past its expiration date.

    edit: function( props ) {	
	const { attributes, className, setAttributes, isSelected } = props;
	const marginstyle = {width: attributes.width + 'em'};
	const innerstyle = {marginLeft: (attributes.width + 2) + 'em'};

	return (
Nested inside another Marginalia block
setAttributes({ content })} />
); }, save: function( { attributes, className } ) { const marginstyle = {}; const innerstyle = {}; if(attributes.position == 'left') { marginstyle['float'] = 'left;' marginstyle['width'] = attributes.width + 'em'; innerstyle['marginLeft'] = (attributes.width + 2) + 'em'; } else { marginstyle['float'] = 'right;' marginstyle['width'] = attributes.width + 'em'; innerstyle['marginRight'] = (attributes.width + 2) + 'em'; } return
; } });

Displaying a Notification

Displaying a notification in the WordPress admin following an event like a post being saved used to be fairly easy in PHP.

add_action('admin_notices', 'rsvpmaker_template_notice');

function rsvpmaker_template_notice () {
	global $post;
	if(isset($_POST['rsvpmaker_template_data'])) //detect some trigger
	echo '

'.__('After updating this template, click','rsvpmaker').' '.__('create / update events','rsvpmaker').'

'; }

It took me months of research to figure out how to do essentially the same thing in Gutenberg because those PHP-generated notifications aren’t shown on the editor screen when Gutenberg is active. The following code is based on a tip from a collaborator on Github and my own study of internal WordPress code to figure out how it detects such events (the example I found was related to saving the content of metaboxes on post save).

Blocks versus Shortcodes

Here are some shortcode examples, one where the output is based on the attributes added to the shortcode and another that wraps around a piece of content (the [caption] shortcode used in the Classic Editor to format image captions and allow them to be treated as a unit with the accompanying image).

The PHP code to process your shortcode can then be something like this:


function my_shortcode_function($atts = array()) {
	$title = $atts['title'];
	$size = $atts['size'];
	$content = sprintf('


',$size,$content); return $content; } function my_shortcode_wrapper($atts = array(), $content = '') { //apply some extra formatting or logic to $content return $content; }

You can register a Gutenberg block to get run through a server-side routine in much the same way:

function wpt_server_block_render(){
	register_block_type('wp4toastmasters/role', ['render_callback' => 'toastmaster_short']);


function toastmasters_short($atts) {
	global $post;
	$role = $atts['role'];
	$count = (int) $atts['count'];
	$content = '';
	for($i =1; $i <= $count; $i++) {
		$slug = $role+$i;
		$assigned = get_post_meta($post->ID,$slug,true);
			$content .= get_agenda_content($slug,$assigned);
			$content .= get_signup_button($slug,$assigned);
	return $content;

Escape from Gutenberg

Although I like many aspects of Gutenberg, I wasn’t prepared to refactor every bit of PHP into JavaScript. In particularly, I had a lot of functionality built into metaboxes displayed beneath the classic editor, and metaboxes are discouraged in the Gutenberg framework. Mine included some JQuery interactivity that seemed to clash with the Gutenberg code.

The coping mechanism I devised for RSVPMaker was to make a few basic options like setting the date and turning RSVP registrations on or off available within the sidebar to the editor. The more elaborate functionality like setting event pricing and customizing the registration form moved to a separate screen.

Here’s how you can do that, in pseudocode simplified from the actual code used in RSVPMaker.

add_action( 'admin_bar_menu', 'my_rsvpmaker', 99 );

function my_toolbar($wp_admin_bar) {
	global $post;
	if(isset($post->post_type) && ($post->post_type == 'rsvpmaker') )
	//a new menu
	$args = array(
		'id'    => 'rsvpmaker_options',
		'title' => 'RSVP / Event Options',
		'href'  => admin_url('edit.php?post_type=rsvpmaker&page=rsvpmaker_details&post_id='.$post->ID),
		'meta'  => array( 'class' => 'edit-rsvpmaker-options')
	$wp_admin_bar->add_node( $args );
	//a subnew menu, parent set to id of item above
	$args = array(
		'parent'    => 'rsvpmaker_options',
		'id' => 'my_form',
		'title' => 'My Form Page',
		'href'  => admin_url('edit.php?post_type=rsvpmaker&page=my_form_page&post_id='.$post->ID),
		'meta'  => array( 'class' => 'my_form')
	$wp_admin_bar->add_node( $args );

add_action('admin_menu', 'rsvpmaker_admin_menu');

function rsvpmaker_admin_menu() {
//submenu menu under post type
add_submenu_page('edit.php?post_type=rsvpmaker', __("Event Options",'rsvpmaker'), __("Event Options",'rsvpmaker'), 'edit_rsvpmakers', "my_form_page", "my_form_page" );
//standalone menu
add_menu_page(__("Event Options",'rsvpmaker'), __("Event Options",'rsvpmaker'), 'edit_rsvpmakers', "my_form_page", "my_form_page" );

function my_form_page() {
	$post_id = (isset($_REQUEST['post_id'])) ? (int) $_REQUEST['post_id'] : false;
		echo '

Updated my variable

'; } printf('
',admin_url('edit.php?post_type=rsvpmaker&page=rsvpmaker_details&post_id='.$post_id)); printf('',get_post_meta($post_id,'my_variable',true)); submit_button(); echo '
'; } else { $o = ''; $future = get_future_events(); foreach($future as $event) { $o .= sprintf('',$event->ID,$event->post_title,$event->date); } printf('
',admin_url('edit.php'),$o); } }

This shows hooking into the action for display of the admin bar, getting access to the $wp_admin_bar object, and calling add_node methods that add our custom menu and submenu.

We register a custom admin page and define a function for displaying it. If the user clicks through from the admin bar (while viewing a post on the website or in the editor), that link will have the post id added to the URL query.

If the post ID is set, we display a form with options specific to that post (an RSVPMaker event in this case). Otherwise, we retrieve a list of posts and give the user a form they can fill out to display the options for the post they are interested in.

Check back on Sunday or Monday for updates to this post.