Last week I wrote an article about misconceptions around Mastodon and the Fediverse. I got a lot of great feedback from that article, but I also got one question a lot: what is Mastodon, exactly?

I didn’t want to address this in that article, as it’s worthy of a full post of its own. I realize that this would be more introductory to the point that it should be read before that article if you just want to create an account and get started using it.

Table of Contents

An Overview of What Mastodon Is

Mastodon is a decentralized, federated social network. It is decentralized in the sense that there is no one company running Mastodon, and there are instead multiple websites that exist, allowing for flexibility, durability, and freedom for the network overall, as opposed to one organizational voice and set of servers. Mastodon is federated in that those separate servers (called instances) can converse with one another. This allows for networks of scale to exist as they do on centralized social networks. An individual instance may have a few dozen or hundred members (or even just one!) and still be able to connect to hundreds of thousands of other accounts with ease.

The aesthetic of the web and mobile apps to access Mastodon are similar to Twitter and Tweetdeck. If you’re comfortable with Twitter already, you’ll be able to mostly navigate Mastodon with little help.

The idea of Mastodon is to create small communities with their own spaces, as opposed to one large forum like Twitter, Instagram, or Facebook. Think of it more like how Reddit has separate communities in subreddits, or how Facebook has groups that require membership to access.

Unlike Reddit and Facebook however, Mastodon is not hosted monolithically by one large company that contains all communities. Instead, different system administrators maintain their own Mastodon groups (instances), and each instance functions separately of one another on different domains. I run a Mastodon instance of my own at the domain tech.lgbt.

Within an instance, the admin has complete control. This is seen as a positive or negative, depending on the community and the user (see my section on “What is True Federation?” in my misconceptions article). They can set the tone of the conversation in the space, and police as they see fit.

How Does Mastodon Compare to Twitter and other Social Networks?

On Twitter, you have to follow the Twitter Code of Conduct, for better or worse. Twitter can choose to block your account for a limited time or ban you permanently if they think that it is required. Considering the scale of Twitter and the number of messages posted daily, it’s no surprise that moderation is mainly handled algorithmically, which leads to a very opaque process. This can lead to gaffes including the temporary ban of Twitter’s own CEO, Jack Dorsey.

Mastodon, on the other hand, has all moderation handled by individual people, often one person for an instance, or maybe a small handful of admins and moderators. This doesn’t mean that the system is necessarily better, but it does allow for a human touch that is so desperately needed where human speech is concerned.

If you do want to keep your Twitter account and use both, as I do, you can use a cross-poster to let you use both services together. I use moa.party, which allows you to link your Mastodon account to both Twitter and Instagram and cross-post between them. These services aren’t perfect, in part because the platforms work different, and because of limitations in the APIs of the closed networks.

How do I Create an Account?

There is no one place to create a Mastodon account. Instead, you choose a community that you want to be part of and create an account there. As an example, my instance, tech.lgbt is for LGBTQIA+ folks and allies with an interest in technology. One of the faster growing instances for furries that I’ve seen is snouts.online. Some users who got banned from Tumblr in late 2018 after their adult content ban have gathered at humblr.social (no longer online). A community for artists exists at mastodon.art, board gamers at boardgames.social, and even a private instance for video game slimes at slime.global.

The last instance is an example of a private instance. This means that the administrators set it up so that new users are either barred from creating accounts, or need to have one created for them by an admin. This is another one of the ways where Mastodon separates itself from Twitter and other networks. Users and admins are welcome to create their own spaces, manage them as they see fit, and interact in ways that are comfortable to them.

The account that you create will be findable via your username and instance name. For instance, I use the rather clever username of david, and am on the instance tech.lgbt. Therefore, my full username to send messages to is @david@tech.lgbt. Think of it like a hybrid of Twitter and email addresses.

Do I Need Accounts on Each Instance?

Long story short: no, you only need as many accounts as you want identities. You can probably interact with others that you want to from whichever instance you choose.

At this point you might be thinking about where to signup for an account and how much that matters. After all, you may be interested in both art and technology, or a specific political ideology as well as something more esoteric like fairies. Thankfully, you don’t generally need to worry about where you sign up for an account, because you can still interact with people on separate instances thanks to the most powerful feature of Mastodon: federation.

What is Federation Again?

Federation is, in simplest terms, how users at various Mastodon instances (or other, compatible websites like micro.blog, Pleroma, and Write Freely) interact with one another. If a Mastodon instance federates with (allows connection to) my instance, then users there can send a message to @david@tech.lgbt, and I’ll receive the message, get notified, and be able to respond just as if I was using Twitter.

The reason that federation is such a powerful tool is because it provides options. I have a defined Code of Conduct on my instance that I enforce, and I take all moderation requests seriously. You may not agree with my moderation standards, but may still want to interact with me or other users on my instance. You can then join another instance and still be able to hold those conversations.

By default Mastodon installs fully federated, with the ability for users on any instance to interact with any other. I’ve blocked a few instances based on the needs of my community and my own views. For instance, I’ve blocked instances that are created solely for spam, or instances that are more toxic in general for either harassers or migrations from Gab. Many instances also block others for spamming, or for hosting content that may be illegal in other countries, like the instances run by Pixiv in Japan.

How do I Find People to Follow?

Since Mastodon is a bit decentralized, it can be hard to find people to follow at the start. There’s no suggestion tool like Twitter has, and no tailoring based on who else you follow and where you live. Part of the allure of Mastodon is that it does so little algorithmically, and instead you are in control of your feed. There are also no trackers to help give the insight that other social networks have.

There used to be a search tool at joinmastodon.org to connect your Twitter and Mastodon accounts together then find who you follow on Twitter also has a Mastodon account. That tool is sadly down, and I don’t know if it is making a return.

A lot of users do ’s, similar to what used to be more commonplace on Twitter. There is also a nice opt-in directory called Trunk that has users on various instances, sorted by topic that they like to talk about.

I reached out on Mastodon to ask how people find others to follow. One response reminded me of a feature that I didn’t highlight before: instance directories. This response from patter gave a few suggestions covered above, and the following advice:

there are profile directories on some instances, you can browse those & add your own profile to them, and your profile isn’t in this public directory by default.

@patterfloof@meow.social
profile directory of tech.lgbt Mastodon instance
Users can opt-in to the profile directory to be easier to find

Additionally, I got a suggestion from one of my favorite mutuals, Winterfang, about using who you already follow to find new people to follow. This is how I found most of the people that I follow now on Mastodon, which is a good alternative to only finding people that I already know IRL.

I just look at the local timeline and follow people who look interesting. I never use the federated timeline at all, personally. Then the local people I’m following boosted some really great people, so I followed them too.

@icewolf@meow.social

What are the Cultural Norms Around Mastodon?

Most instances have policies around what is acceptable behavior and what is not. A good instance will have some form of Code of Conduct for users to abide by. Having some rules in place makes a safer and more enjoyable space, and having the rules written out publicly makes moderation more transparent.

We’re not a free speech absolutist, and there are instances available for that. We’re not interested in Nazis, TERFS, or hate speech of any sort, which we will define at our sole discretion as moderators.

This instance is meant to be a friendly, welcoming space to all who are willing to reciprocate in helping to create that environment.

Short Version excerpt from the tech.lgbt Code of Conduct

Users are generally encouraged to create introductory posts that they can then pin to their profiles. Use the hashtag, as well as hashtags for things that you’re focusing on in your account. Let people know who you are so they have reason to follow you!

Content Warnings are also encouraged on most instances. These are notices that you can place over the content of your messages, which will the require viewers to acknowledge and click through before reading the content. These are used for things like nudity, charged topics like politics and mental health posts, or even more benign content that all users may not want to see. Using CWs where appropriate is being a good neighbor to other users, as is adding descriptive text to images that you post.

Examples of Mastodon content warnings
Content Warnings can be included to hide toot content. Images can also be marked as sensitive.

How Do Locked Accounts Work?

Accounts on Mastodon can be locked, not unlike Twitter. What sets them apart though is that locked accounts can still make public toots. Instead of having to have an all or nothing approach to privacy, you can set it on your own terms. You can even post toots that are unlisted, visible only on your profile page.

screenshot of Mastodon posting interface with post visibility setting toggled visible
By default Matsodon allows Public, Unlisted, Followers-only, and Direct Message posts

Many people on Mastodon lock their accounts to control who is allowed to follow them or not, and you may have to have a follow request accepted. Best behavior is to have your profile filled out with a name and profile photo, as well as a pinned post with the hashtag to make it easy for people to learn about you and decide whether they want to allow you to follow them. We’re here to make friends, not broadcast announcements!

*hat tip to @dysphoricunicorn@cybre.space for this tip, in their post on using the fediverse

How Exactly Do I Get Started?

First, you sign up for an instance. This is easier to do from the web, since most mobile apps only allow you to login to existing accounts. Usually you can go to the homepage of whatever instance that you want to sign up for to create an account, provided that it’s not a private or closed instance.

When you’re signed up, you can use a mobile app to interact with Mastodon. I recommend Amaroq if you are on iOS, and Tusky if you are on Android. You’ll notice that these and most Mastodon apps have very mixed reviews, often lots of five-star reviews pulled down by one-star reviews. Read some of the reviews and you’ll often notice that low ratings are based around coordinated campaigns from users on instances that are unhappy with built-in blacklists. When Gab abandoned their own codebase and moved to Mastodon they brought all of their existing community issues with them.

If you are looking to find an instance to join, instances.social is a database that lists some information about various instances, including the main languages of the instance, how many users there are, what kind of content is allowed or prohibited, and what the focus of the instance is. The website is a good guide to find some instances to start with, but some of the data isn’t always correct. As an example, my instance currently shows as down, closed to registrations, and with poor uptime. All of which I’d question considering I use it daily πŸ˜‚

With all of that out of the way, get started on the fediverse! You’ll learn a lot more by jumping in and joining the conversation. If you want more technical details, documentation, or getting started guides, check out https://joinmastodon.org/. See you there, and if you want to say hi, I’m @david@tech.lgbt

Also, I’ve rebooted my weekly newsletter which focuses on things that I’ve found interesting around the web. Subscribe and I promise I’ll only spam you in the best way!

Subscribe to the 🐺🐾 Newsletter


Terminology

Toot: An individual status update. Analogous to a Tweet on Twitter.

Boost: Sharing a Toot to other users who follow you, dependent upon the visibility of the original Toot and your account. Analogous to a Retweet on Twitter.

Content Warning: An optional field while composing a Toot that allows you to hide the content of your Toot behind a button with some notice text. Often used as a warning for content such as nudity, mental health, politics, and other subjects that some users would prefer to control visibility of. Some instances police Content Warning (shortened CW) notices more than others.

Instance: A specific server running Mastodon. Generally denoted from one another by the domain name that accounts are registered at. An instance can be made for only one user, or can be open to hundreds or thousands of users.

Federation: The ability for Mastodon instances to interact with one another. Open by default, can be modified or closed down entirely by admins.

Fediverse: An informal name for the network of sites that federate with one another, This includes Mastodon, as well as other ActivityPub or oStatus based services like micro.blog, PixelFed, Pleroma, and others.

birdsite: An often derogatory term used to describe Twitter.

Resources

One of the things that I handle for clients at FixUpFox is site speed optimization. I also help with performance optimization, which I almost lumped into this post, but I think that it deserves its own overview at a later date.

I also began blogging more regularly on this personal site, thanks to the support from the Blogging Accountability Group that I formed with a few members of the WordPress Orlando Meetup. One of the things that I want to do is to improve the theme that I use on the site, and one of the ways that I want to do that is to improve site speed.

There are quite a few reasons to want to improve the speed of a site. Most concerning to me are based around resource usage and visitor experience. Loading a smaller page does a lot of good, including:

  • Less bandwidth and resource usage for visitors, improving loading speed and battery life
  • Lighter energy usage footprint, reducing ecological impact slightly

Here’s a quick overview of what I did for my personal site, which can be what I do for a client site, depending on their needs. I have to note that I don’t do much in terms of tracking on my site, and I don’t run ads. Those are often the two biggest blockers that I have to increase page performance for clients.

A baseline of performance

The first thing that I do is establish a baseline of the site. That lets me get an idea of what improvement that I end up with, but also places to start looking at making changes.

The following data was from my WordCamp Atlanta Review post tested with tools.pingdom.com. I also use Google PageSpeed Insights, Lighthouse, and GTMetrix depending on what I’m looking for.

Performance grade: C β€” 77
Page size: 1.1 MB
Load time: 1.37 s
Requests: 56

The above indicates that I loaded 1.1MB worth of data on this page, taking an average of 1.37 seconds over their tests, and that 56 separate files were requested to load this page.

This isn’t terrible, but I had a feeling that I could do better with a few simple changes.

Removing Unused Scripts, Styles, and Fonts

First, I started by reviewing external requests. That includes any JavaScript files, CSS stylesheets, and fonts that load along with the rest of the page. I had 56 requests being made to load that page, which is far from unusual, but a bit high for a personal post about a trip on my non-monetized site.

Boilerplate Scripts

A plugin that I use to manage things like my Speaking custom post type was made with the WordPress Plugin Boilerplate. That helped save time in setting the plugin up, but it also added a bit of code that I didn’t need, including display script and style files which I wasn’t making use of. Eliminating the code that called those files eliminated two requests that did literally nothing at all.

jQuery Migrate

Next, I looked at jQuery Migrate. This is a script that WordPress loads to help manage old code. It acts as a bridge between the latest versions of jQuery and code that is written for very old versions of jQuery. Since my site is running up to date code in the theme and plugins, I could remove this script. I can’t always say that it is possible to remove it, but you can try and see if anything breaks on your site. Most current themes and plugins have no need for it, so I removed it with the following code taken from this Dotlayer article.

//Remove JQuery migrate
function remove_jquery_migrate($scripts)
{
    if (!is_admin() && isset($scripts->registered['jquery'])) {
        $script = $scripts->registered['jquery'];
        
        if ($script->deps) { // Check whether the script has any dependencies
            $script->deps = array_diff($script->deps, array(
                'jquery-migrate'
            ));
        }
    }
}

add_action('wp_default_scripts', 'remove_jquery_migrate');

Code language: PHP (php)

FontAwesome

Next, I looked at FontAwesome. loading the script to enable that on my site was the largest file, accounting for around 25% of the page load size.

I really like FontAwesome. It’s made it a great way to get social icons and other useful site iconography without having to find and load new pictures for each. Plus, it flows smoothly between code, the content editor, and stylesheets.

It turns out that I was only using three icons from FontAwesome across the entirety of my site: the hamburger mobile menu icon, the X close icon when the mobile menu was open, and the moon icon for the basic night-mode that I have a feeling no one even realizes is for that purpose (more on that in the future).

Since I didn’t have a lot of icons to replace, I decided to rebuild those in CSS only. There are a variety of places to find tutorials on drawing in CSS, something that I hope to do in the future as well. For now, I redid those icons in CSS and removed reference to FontAwesome from the theme, saving a lot of the page size in the process.

WP Emoji

WordPress has its own emoji loading, which is useful for the amount of times that I like inserting a 🐺or a 🐾 or a 😝into what I’m writing. But you can see from the previous sentence and my bio at the end of posts that I still have them displaying with system defaults of pretty much every device that would view my site without having to load them.

I’ve used the following code to blanket remove the WordPress emoji from my site load, though you might have reasons for keeping some of these on.

/**
 * Disable the emoji
 */
function disable_emoji() {
	remove_action( 'wp_head', 'print_emoji_detection_script', 7 );
	remove_action( 'admin_print_scripts', 'print_emoji_detection_script' );
	remove_action( 'wp_print_styles', 'print_emoji_styles' );
	remove_action( 'admin_print_styles', 'print_emoji_styles' );
	remove_filter( 'the_content_feed', 'wp_staticize_emoji' );
	remove_filter( 'comment_text_rss', 'wp_staticize_emoji' );
	remove_filter( 'wp_mail', 'wp_staticize_emoji_for_email' );

	// Remove from TinyMCE
	add_filter( 'tiny_mce_plugins', 'disable_emoji_tinymce' );
}
add_action( 'init', 'disable_emoji' );

/**
 * Filter out the tinymce emoji plugin.
 */
function disable_emoji_tinymce( $plugins ) {
	if ( is_array( $plugins ) ) {
		return array_diff( $plugins, array( 'wpemoji' ) );
	} else {
		return array();
	}
}

Code language: PHP (php)

Handling Images

I realized that a lot of images were returning too large on my site. This means that I had a space where an image would load, say an 80px square for a profile icon, yet a larger 512px square was loading for it.

In this case the issue was Webmentions, which I was handling via an IndieWeb plugin. I was showcasing people who liked or retweeted my post on Twitter, as well as those who commented on it.

A whole discussion should be had about the display of metrics, the privacy of individual interaction, and a need to prove popularity through that interaction. For now, my focus was on speed, and I’ve turned off profile image loading. I’m going to be reviewing my usage of this type of interaction demonstration, while still showcasing some cool features that IndieWeb proponents have given us.

Resizing default media sizes

The large image size on my site was set to the default of constraining to a box of 1024px by 1024px. This is a good default for some sites, but for me I had nowhere that images were displaying that large generally, even on wide screens. There were images loading that had to be resized by the browser and ended up loading larger files than needed.

If you are on your site dashboard, you can go to the Settings panel on the left sidebar and select the Media page. There you can change the default media settings to sizes that make sense for you. In my case, I made thumbnails a different size to fit my design. They ended up being larger than the default, but allowed me to avoid having to crop to fit featured images manually, and are smaller than the medium size that I would have otherwise loaded. I also made large images constrained to an 800px by 800px box, which is around 61% of the size of the original image size. This is still large enough for my theme, but saved some space in what is often the largest portion of page load.

If you change your image size on an existing website, you’ll also want to regenerate the cropped and resized image files that WordPress makes. The plugin Regenerate Thumbnails is my go-to for this task. You can even set it to only resize featured images, if those are the only ones that need to change.

Performance improvement after making changes

Now that I’ve made a handful of changes, it’s time to test the site again to see how we’ve done. I’ve gone back to tools.pingdom.com and ran the test again, being sure to select the same server location to get comparable results.

Performance grade: C β€” 80
Page size: 563.2 KB
Load time: 442 ms
Requests: 36

The performance grade has barely gone up, but that’s more of an overall estimation based on what they think is important, which doesn’t always apply to your site. What has improved is the page size, which is about half of what it was before optimization. That’s already a huge savings! It’s also loading in about a third the time, and I was able to remove 20 requests from the page load.

At this point we could probably be done and move on, but I figured I’d try a few other small things to improve page speed. I wasn’t doing any concatenation of files, and that seemed like the next best place to reduce the number of requests, increasing load speed.

What about performance optimization plugins?

I have used a few plugins for minification and concatenation in WordPress. Minification means stripping out unnecessary spaces and comments in files that make them much easier to read for humans, but aren’t needed by the computer. Concatenation is taking files and combining them together into one larger file. While it takes up more space it is one fewer request to make, which again can be a big driver in performance and speed.

Fast Velocity Minify and Autoptimize are two free plugins with a variety of free and paid extensions that you can take advantage of. I’ve never used the paid extensions to offer any insights, but the free versions work very well.

In this case I chose Fast Velocity Minify, which I installed on my site and activated with default settings only, no modification. Running the speed test again gave me the following results:

Performance grade: A β€” 91
Page size: 607.3 KB
Load time: 443 ms
Requests: 19

There’s a few things to note here. The performance grade greatly improved, and the number of requests was cut nearly in half, which is a big contributor to that score.

But we also see that load time is basically unchanged, and the page size actually increased, despite the fact that we tried shrinking the number of files that loaded.

These optimization plugins can do great things for your site, though they can also add headaches with another layer of caching and the possibility that concatenation breaks the order that scripts need to load to function. I still use them on a lot of sites, but I think it’s important to note that they aren’t a magic fix and are a bit more complex in how they handle your site content.

tl;dr β€” A recap of what I did to improve performance

I’m going to let the following screenshot (that I optimized, of course) from Google PageSpeed Insights speak for itself in terms of what a few minor changes that took me about an hour worth of work did for my site.

And here are the results that I got for the site at various testing times:

Before OptimizationAfter OptimizationAfter Optimization Plugin
Performance gradeC β€” 77C β€” 80A β€” 91
Page Size1.1 MB563.2 KB607.3 KB
Load Speed1.37 s442 ms443 ms
Requests563619

I’ll encourage you to consider deeply what optimization steps apply to your website and which don’t, but here’s a short list of things that I did that you could try.

As a reminder, I am basing this case study on a personal site that does not run ads (though it has a Patreon to support my writing and tutorials!), and uses a single Google Analytics tracking script. When it comes to sites that do extensive tracking or use advertising networks, there are a host of other things to consider.

I hope that the above gives you a place to start when you begin looking at increasing performance and speed on your site. Now go make the web faster and better!

PHP normally only displays fatal errors in the browser, or doesn’t load any page content and gives you a “White Screen of Death (WSOD)” if it has a fatal error before the page can load. A fatal error is one in which something is so wrong in the PHP code that it cannot make sense of it to gracefully fail in the background. If I forget to add chocolate chips when making cookies, I still have a perfectly tasty dough. If I forget to add baking soda though, I end up with a flat, gooey mess.

WordPress has a few features built in to make it easier to see PHP errors while you are testing. You’d want to activate these while developing a new site, theme, or plugin to ensure that you are seeing any PHP errors that come up.

As mentioned in the last post on PHP Illegal Strings, there are a few failure types in PHP including warnings, notices, and errors. Turning on WP_DEBUG will allow you to see those failure types so that you can fix them in your code.

Activating WP_DEBUG

If you have access to all of the files of your WordPress install, you’ll want to edit the wp-config.php file, which is located in the root directory, meaning the same folder that has the wp-admin, wp-content, and wp-includes folders. You’re going to go into that file and add the following line of code near the bottom of the file, but before the stop editing notice:

define( 'WP_DEBUG', true );

/* That's all, stop editing! Happy blogging. */Code language: PHP (php)

If that line already exists but says false, change that to true. There can be other lines of code above or below this, but as long as it’s above the comment to stop editing, it’s in the right spot.

What did we do?

We’ve now told WordPress that rather than hide PHP errors, we want them to display while viewing the site. WP_DEBUG is a PHP constant, which by convention are written in all caps. We’ve used the PHP define() function to set the value of that constant to a boolean true. Note that we didn’t surround the word true in quotes, otherwise PHP would read it as a string.

Using WP_DEBUG also allows us to see any deprecated functions that are running on our site. Deprecated functions exist in WordPress but are no longer the standard way to perform a particular tas. As an example, long ago in WordPress history you would get the ID of a category in WordPress with the function the_category_ID(), but now the function to do the same in a better way is get_the_category().

Using WP_DEBUG_LOG and WP_DEBUG_DISPLAY

There are some companions to WP_DEBUG that can be used to make it even more helpful. You may not always be able to easily see errors if they are loading behind content, or you may want to keep track of them over time to review later. Two other constants that are built into WordPress that can help are WP_DEBUG_LOG and WP_DEBUG_DISPLAY.

Using WP_DEBUG_LOG

Setting up WP_DEBUG_LOG allows you to save all of the debug errors that are getting displayed to a file in your WordPress install. That file gets saved to wp-content/debug.log by default. Whenever an error occurs that WP_DEBUG would display, it will also get saved to that file with a timestamp of when the error occured.

To turn on WP_DEBUG_LOG you’ll want to define the following constant:

define('WP_DEBUG_LOG', true);Code language: PHP (php)

You don’t have to worry about creating the debug.log file if it doesn’t already exist. WordPress will do this for you automatically as soon as it has an error to log. So hopefully not right away!

Changing WP_DEBUG_DISPLAY

By default, setting WP_DEBUG to true will display all errors on the screen in your browser, on both the visitor-facing frontend, and the admin-facing backend of your site. This is ok while you’re editing a site that isn’t live with other people using it, but you don’t really want those errors displaying to other site visitors. It will make the site look more broken than it is, and can even be a security concern.

If you want to use WP_DEBUG but don’t want to display errors to the screen, set the following constant:

define('WP_DEBUG_DISPLAY', false);Code language: PHP (php)

Again, if you don’t set that as false, it will default to true when debug is turned on. If you are setting it to false, you’re probably also setting WP_DEBUG_LOG to true, since otherwise you won’t see the errors on the screen or in a debug log.

If you want to passively log errors for review later on a live site, just in case any come up, you can combine the three definitions above to turn on debug mode, log errors, and stop them from displaying on the site. I recommend doing this if you don’t have anything else handling these error logs for you, which you’d probably know if you did.

// Enable WP_DEBUG mode
define('WP_DEBUG', true);
 
// Enable Debug logging to the /wp-content/debug.log file
define('WP_DEBUG_LOG', true);
 
// Disable display of errors and warnings 
define('WP_DEBUG_DISPLAY', false);Code language: PHP (php)

Continuing to Debug Your Site

The settings above display PHP errors, but they don’t actually do anything to fix them. You’ll need to handle that yourself. Still, they provide an invaluable source of information to determine why something is broken on your site. This won’t show all types of errors that could occur, since not all broken page or feature problems are PHP related.

What it does do is give you a good footing to begin the fun part of debugging: digging into code and squashing bugs as you find them. In this case the old proverb is true: Knowledge is Power.

An update to Yoast SEO v11.1 came out yesterday, causing a few site errors relating to illegal strings in PHP. It made me dust off this post to provide some detail on what that PHP warning is, why it is happening, and how it can be fixed.


Last year I updated all existing client sites that I could to PHP version 7.2, to replace versions 5.6 and 7.0, both of which reached their end of security update lifespans in December of 2018. The current plan for WordPress v5.2 is to drop support for versions of PHP below 5.6, which is targeted to be released on 7 May. If this goes well, the minimum PHP version will be bumped to 7.0 later this year.

We’re only a few weeks away from this change, and a lot of hosts have been informing users that their version will change, or that they should opt-in to update when they can. One issue is that there are some things that work in earlier versions of PHP that will now throw warnings, notices, and errors in newer versions. One of the ones that I had to contend with on a few sites recently was the “Illegal string offset” warning.

Warning: Illegal String Offset

Here’s a few warnings that appeared on a development version of a site that I was upgrading (file path removed for readability):

__Warning:__ Illegal string offset 'menu' in [file location] on line 13
__Warning:__ Illegal string offset 'post_types' in [file location] on line 25
__Warning:__ Illegal string offset 'post_formats' in [file location] on line 36
Code language: PHP (php)

I’m noting that it’s a development environment, because I had WP_DEBUG set to true in my wp-config.php file, which I don’t do on live, production environments. Basically, I ensure that on a live version of a site I don’t have PHP errors/warnings/notices displayed, even if there are some that would otherwise display.

I took a look at that file, which was a configuration file for the theme being used. The relevant lines from that file are below:

/*
 * Theme menu
 */
$theme['menu'] = array(
    THEMENAME,
    'Slideshow',
    'Sidebars',
    'Style',
    'Upload your fonts',
    //'Help'
);

/*
 * Post types
 */
$theme['post_types'] = array(
    'Posts',
    'Pages',
    'Works',
    'Testimonials',
);

/*
 * Post formats
 * aside, gallery, link, image, quote, status, video, audio, chat
 */
$theme['post_formats'] = array( 'gallery' );
Code language: PHP (php)

Can you spot the issue? I didn’t immediately see it myself, as I saw things like $theme['menu'] and thought “how can that be read as a string? The braces clearly indicate that we’re setting an array key.

Explicitly Declaring an Array in PHP

What I didn’t realize was that we were missing something that’s necessary as of PHP v7.1.0: an explicit declaration of the variable $theme as an array. If you take a look at the PHP.net manual entry on PHP Array Syntax Modifying, you’ll see the following note:

Note: As of PHP 7.1.0, applying the empty index operator on a string throws a fatal error. Formerly, the string was silently converted to an array.

So there’s our issue, and with it, a lead on a solution: the theme never explicitly declared the variable $theme to be an array, and so it was assumed to be a string. Since it is no longer being silently converted, we have a warning being thrown.

Fixing the Illegal String Offset Warning

The solution in this case is to add a line to the start of that block of code where we explicitly declare our variable as an array. What that looks like is this:

$theme = array();

/*
 * Theme menu
 */
$theme['menu'] = array(
    THEMENAME,
    'Slideshow',
    'Sidebars',
    'Style',
    'Upload your fonts',
    //'Help'
);
Code language: PHP (php)

By adding $theme = array();, we’re telling PHP, “yes, this is an array, please treat it as such.” It doesn’t have to try to guess what we mean, which newer versions of PHP no longer do anyway.

PHP v7.0+ also introduces strict typing, which is great for being even more explicit in your PHP coding. This makes the code more secure (people can’t put different data types in than you intend), and less liable to break (you will always know what type of data to expect). If you want to learn a bit more, Eric Mann wrote a short introductory post on the topic early last year.

PHP is getting better and better all the time, but this progress sometimes causes old code to break. While this is frustrating, it can also give you the opportunity to review old code with fresh eyes. It’s not always convenient to do this, but it can overall improve your site!

If you’re like me, you don’t do much for SEO on your site. If you’re a better marketer than me and also have tools that you use for SEO, you probably don’t use the built-in SEO tools with the Genesis Theme Framework.

The tools do their job and are already there if you want to use them, but they can be limiting, as well as duplicate work being done with any other SEO plugin that you may be using. You can choose not to use them, but they still take up some valuable space in your dashboard and while editing pages, and they can be a bit confusing if you’re handing the site off to someone else to manage.

WordPress Gutenberg post editor with Genesis SEO enabled
Look at all of that space devoted to an unused settings section!

Removing the Genesis SEO Settings

One of the many great things about Genesis is that it allows you to easily modify or remove various portions of it without having to directly edit the core files of the theme. This allows you to modify your child theme only, so that if you ever switch child themes or Genesis updates, your changes won’t break.

Place the following code in your functions.php file, or another file that loads on the dashboard.

// Remove Genesis SEO settings from post/page editor
remove_action( 'admin_menu', 'genesis_add_inpost_seo_box' );

// Remove Genesis SEO settings option page
remove_theme_support( 'genesis-seo-settings-menu' );

// Remove Genesis SEO settings from taxonomy editor
remove_action( 'admin_init', 'genesis_add_taxonomy_seo_options' );Code language: PHP (php)

The first line of code removes the SEO metabox in posts/pages/custom post types. The post editor is already looking cleaner!

WordPress block post editor without Genesis SEO settings section
Now there’s less distraction while writing a post!

The second line of code removes the SEO settings menu from the left sidebar in the dashboard. If we’re not using it at all, no reason to have the settings page!

Finally, the last line of code removes the SEO settings from taxonomies. That means that you won’t be able to access them on categories, tags, or any other custom taxonomies on the site.

And with that, we’re done! Three lines of code (plus a bit of spacing and comments to make it easier to read and remember what we did that for later), and we’ve removed access to the Genesis SEO settings. Again, this isn’t a knock on Genesis, but simply a way to clean up your site a bit if you’ve already invested in another SEO tool for WordPress.