<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>WP Smith</title>
	<atom:link href="https://wpsmith.net/feed/?cat=-255" rel="self" type="application/rss+xml" />
	<link>https://wpsmith.net</link>
	<description>Creating WordPress &#38; Genesis Websites Since 2010</description>
	<lastBuildDate>Thu, 24 Sep 2020 12:24:17 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=5.7.15</generator>

<image>
	<url>https://wpsmith.net/wp-content/uploads/2015/08/wpsmith-logo-rgb-150x150.jpg</url>
	<title>WP Smith</title>
	<link>https://wpsmith.net</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Solving WordPress 5XX Server Errors on SiteGround</title>
		<link>https://wpsmith.net/2020/solving-wordpress-500-502-503-504-5xx-errors-on-siteground-and-other-hosts/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=solving-wordpress-500-502-503-504-5xx-errors-on-siteground-and-other-hosts</link>
					<comments>https://wpsmith.net/2020/solving-wordpress-500-502-503-504-5xx-errors-on-siteground-and-other-hosts/#respond</comments>
		
		<dc:creator><![CDATA[Travis Smith]]></dc:creator>
		<pubDate>Wed, 16 Sep 2020 17:52:12 +0000</pubDate>
				<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">https://wpsmith.net/?p=70074</guid>

					<description><![CDATA[<p>Understanding 499, 500, 502, 503, 504 errors on SiteGround and 15 ways to solve those 5XX errors.</p>
<p>The post <a rel="nofollow" href="https://wpsmith.net/2020/solving-wordpress-500-502-503-504-5xx-errors-on-siteground-and-other-hosts/">Solving WordPress 5XX Server Errors on SiteGround</a> appeared first on <a rel="nofollow" href="https://wpsmith.net">WP Smith</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-large"><img loading="lazy" width="1024" height="481" src="https://wpsmith.net/wp-content/uploads/2020/08/siteground-500-1024x481.png" alt="500s on SiteGround" class="wp-image-70089" srcset="https://wpsmith.net/wp-content/uploads/2020/08/siteground-500-1024x481.png 1024w, https://wpsmith.net/wp-content/uploads/2020/08/siteground-500-300x141.png 300w, https://wpsmith.net/wp-content/uploads/2020/08/siteground-500-768x361.png 768w, https://wpsmith.net/wp-content/uploads/2020/08/siteground-500-1536x722.png 1536w, https://wpsmith.net/wp-content/uploads/2020/08/siteground-500-2048x962.png 2048w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>Lately, I have helped a lot of clients who have 5XX errors on SiteGround, especially eCommerce sites. If you are experiencing any 499, 500, 502, 503, and 504 errors on SiteGround, please know that they are very common. I know there is <em>nothing more frustrating than having one's site down</em>, especially if you do not know why! If your site is down, you are truly suffering: </p>



<ol><li>You lose those precious leads</li><li>You lose revenue and real money whether via clients, ads, or purchases from your store</li><li>You lose trust from your potential customers</li><li>Your SEO rankings will drop because a site with poor uptime will less likely be available when the search needs it from a search results page</li></ol>



<p>Look no further! In this article, I will explain what the error codes mean, some of the terms and relevant architecture, and outline my 15 steps of what I do to address these issues. </p>



<ol><li><a href="#understanding-500-errors">Understanding 500 Errors</a></li><li><a href="#solving-500-errors">Solving 500 Errors</a></li><li><a href="#understanding-499-502-503-504-errors">Understanding 499, 502, 503, &amp; 504 Errors</a></li><li><a href="#web-architecture">Understanding the Web Hosting Architecture</a></li><li><a href="#support-expectations-for-5xx-errors">What to Expect from Managed Hosting Support</a></li><li><a href="#solving-499-502-503-504-errors">15 Ways of Solving 499, 502, 503, &amp; 504 Errors</a></li><li><a href="#summary">Summary</a></li></ol>



<div class="wp-block-buttons aligncenter">
<div class="wp-block-button"><a class="wp-block-button__link" href="/contact/"><strong>Hire Me!</strong></a></div>



<div class="wp-block-button is-style-outline"><a class="wp-block-button__link" href="https://wpsmith.net/hire-a-wordpress-developer/" target="_blank" rel="noopener noreferrer">Hire Me on Codeable</a></div>
</div>



<h4><strong>Why is it so difficult to fix the 5xx errors on SiteGround?</strong></h4>



<p>On SiteGround, the problems with even identifying the 5XXs are:&nbsp;</p>



<ol><li>No visibility provided by SiteGround on the number of 5XXs.</li><li>Inability to access the logs in real time via SSH, which are 15-30min behind.</li><li>No alerts to you or from the system of any 5XXs.</li></ol>



<p>Essentially, you have absolutely zero ability to identify the 5XXs without SiteGround support which they have consistently answered, "Scale the hosting plan" (which obviously benefits them). SiteGround is not really motivated to suggest anything else, so besides suggesting external experts and recommending you scale your site, I doubt you will ever get anything else from their Support team.</p>



<p>As a side note, SiteGround is not 100% designed and optimized for WordPress like <a aria-label="undefined (opens in a new tab)" href="https://wpsmith.net/go/wpengine" target="_blank" rel="noreferrer noopener nofollow">WP Engine</a> (which solely and only hosts WordPress). Many managed hosts that may have originally been designed for WordPress have expanded to support other types of applications like Drupal and Joomla, which also uses the same technological stack. While it makes sense to do this, fine tuning for WordPress v. Drupal v. Joomla is still different albeit very small (but these nuances matter at scale). Only when a hosting company scales their hosting do these nuances begin to show themselves. Those managed hosting companies like Flywheel that use containers (probably Kubernetes) can still claim they maintain optimization for WordPress though they've expanded into other platforms.</p>



<h3><strong>Can You Just Solve This For Me!</strong>?</h3>



<p>If you do not care about how to solve this, and just want someone to do this, you are looking at between $500–$3,000. With others, it may even cost you more as they may not have a strategic approach as I do. This sort of work is considered a troubleshooting task where you are paying based on the number of projected hours worked (and must pay hourly until solved with no guarantees). The strategy laid out below is a strategic plan that can be done as a service that will give you a level of satisfaction. If you are still interested, you can hire me immediately by <a aria-label="undefined (opens in a new tab)" href="/contact/" target="_blank" rel="noreferrer noopener">contacting me</a> directly or via <a aria-label="undefined (opens in a new tab)" href="https://wpsmith.net/hire-a-wordpress-developer/" target="_blank" rel="noreferrer noopener nofollow">Codeable</a>. </p>



<h4>Disclaimer</h4>



<p>Please feel free to read this article and attempt to fix your site yourself <em>at your own risk!</em> Please note that I cannot be held liable for what you attempt to do on your own. If you attempt to do what is outlined here and mess up your site even further, it will most likely cost you even more monies to rectify and help you. So please, please create backups of everything before moving forward with attempting to fix things yourself or with hired help.</p>



<div class="wp-block-buttons aligncenter">
<div class="wp-block-button"><a class="wp-block-button__link" href="/contact/"><strong>Hire Me!</strong></a></div>



<div class="wp-block-button is-style-outline"><a class="wp-block-button__link" href="https://wpsmith.net/hire-a-wordpress-developer/" target="_blank" rel="noopener noreferrer">Hire Me on Codeable</a></div>
</div>



<h3 id="understanding-500-errors"><strong>Understanding 500 Errors</strong></h3>



<p><em>A 500 is an Internal Server Error</em>. The server has encountered a situation that it doesn't know how to handle, and usually a 500 error is more persistent. </p>



<p>All hosts handle this the same way and this issue is not really germane to just SiteGround. This is also known as the WordPress White Screen of Death (though that also occurred for other reasons too). The reason for these 500 errors can be limitless, but generally the primary cause is a plugin, a missing plugin/files, or some bad code somewhere.</p>



<p>Now what is problematic is that SiteGround calls all their errors 500 to the end user. You only see the actual error code though the access logs. All users get the error page pictured above that says <strong>500 - Internal Error</strong>. So the actual error code could be any one of these: 499, 500, 502, 503, or 504; all of which mean something different to a developer.</p>



<h4 id="solving-500-errors"><strong>So what do you do to solve your 500 issue(s)? </strong></h4>



<p>If you are on a managed host (e.g., SiteGround's Cloud Hosting, WP Engine, etc.), then simply revert to a previous installation/backup. This will be the easiest by far and will not require you to hire a developer. If you are more technical or daring...then you can try some of the recommendations below. Alternatively, you can <a aria-label="undefined (opens in a new tab)" href="https://wpsmith.net/hire-a-wordpress-developer/" target="_blank" rel="noreferrer noopener nofollow">hire me or another expert</a> or <a href="/contact/">contact me directly</a>.</p>



<p>If this happened right after upgrading or activating a <strong><em>plugin</em></strong>, then you simply want to deactivate the plugin either via WordPress admin or WP CLI. To do this:</p>



<ul><li>via SFTP/FTP, simply go to the <code>wp-content/plugins</code> folder and rename the plugin folder (e.g., from <code>my-plugin</code> to <code>my-plugin.bak</code>) and log into the WordPress admin plugins page (<code>wp-admin/plugins.php</code>). Going to the plugins page will automatically deactivate the plugin (because it will be considered missing).</li><li>via WP CLI, at the root of the site (same place where wp-config.php is located), run <code>wp plugin deactivate my-plugin-slug</code>. For more information, see <a href="https://developer.wordpress.org/cli/commands/plugin/">WP CLI plugin command</a>.</li></ul>



<p>If this happened right after upgrading your <strong><em>theme</em></strong>, then you want to do something similar. To do this:</p>



<ul><li>via SFTP/FTP, simply go to the <code>wp-content/themes</code> folder and rename the plugin folder (e.g., from <code>my-theme</code> to <code>my-theme.bak</code>) and log into the WordPress admin plugins page (<code>wp-admin/themes.php</code>). Going to the themes page will automatically activate the default theme giving you a notice that the active theme is broken.</li><li>via WP CLI, at the root of the site (same place where wp-config.php is located), run <code>wp theme install my-theme-slug --activate</code>. For more information, see <a href="https://developer.wordpress.org/cli/commands/theme/">WP CLI theme command</a>.</li></ul>



<p>If you have <strong><em>access to the WordPress admin</em></strong> (meaning you can log into the site, access the plugins (<code>wp-admin/plugins.php</code>) and/or themes page (<code>wp-admin/themes.php</code>) and can install plugins.</p>



<ol><li>Go to the plugins page.</li><li>Install the <a href="https://wordpress.org/plugins/health-check/">Health Check</a> plugin.</li><li>Begin troubleshooting mode via the Advanced.</li><li>Enable your theme and check the site.</li><li>Enable plugins one by one and check the site after every activation.</li></ol>



<p>These methods will help you temporarily fix the issue and you may need to <a aria-label="undefined (opens in a new tab)" href="https://wpsmith.net/hire-a-wordpress-developer/" target="_blank" rel="noreferrer noopener nofollow">hire a developer</a> or <a href="/contact/">myself</a> to completely fix this for you.</p>



<div class="wp-block-buttons aligncenter">
<div class="wp-block-button"><a class="wp-block-button__link" href="/contact/"><strong>Hire Me!</strong></a></div>



<div class="wp-block-button is-style-outline"><a class="wp-block-button__link" href="https://wpsmith.net/hire-a-wordpress-developer/" target="_blank" rel="noopener noreferrer">Hire Me on Codeable</a></div>
</div>



<h3 id="understanding-499-502-503-504-errors"><strong>Understanding 499, 502, 503, &amp; 504 Errors</strong></h3>



<p>There are four primary 5XX error codes that your server will be giving you: 499 Client Closed Request, 502 Bad Gateway, 503 Service Unavailable, and 504 Gateway Timeout.</p>



<ul><li><em>A 499 is Client Closed Request</em>. This was originally a NGINX Error code to highlight that the client closed the request before the server could respond.</li><li><em>A 502 is Bad Gateway</em>. The server was acting as a gateway and received an invalid response from the upstream server.</li><li><em>A 503 is Service Unavailable</em>. The server is not ready to handle the request, generally as a result of being overloaded or down for maintenance.</li><li><em>A 504 is Gateway Timeout</em>. The server was acting as a gateway and did not receive a timely response from the upstream server.</li></ul>



<p>There are several reasons that this is happening.  First, you could be under a DDOS Attack of some kind. If this is the case, you need to implement Cloudflare or <a aria-label="undefined (opens in a new tab)" href="/go/sucuri/" target="_blank" rel="noreferrer noopener">Sucuri</a> ASAP. Second, you could have a surge in traffic that you were not expecting. Third, your resources (CPU/RAM) was not configured properly. Fourth and onward, too complicated to explain in this short-ish post.</p>



<div class="wp-block-buttons aligncenter">
<div class="wp-block-button is-style-outline"><a class="wp-block-button__link" href="#503-support">Skip Architecture</a></div>
</div>



<h4 id="web-architecture"><strong>Understanding Web Hosting Architecture</strong></h4>



<p>So to prevent the 5XXs, you could <span style="text-decoration: underline;">scale out</span> (or expand) your resources (which costs money <em>always</em>) or <span style="text-decoration: underline;">remove load off</span> your server by offloading traffic. To understand what I mean by offloading traffic, you need to understand the general architecture of WordPress on managed hosting platforms. On SiteGround (and many other installations), you are generally dealing with these layers:</p>



<ol><li>Web <em>Server</em> layer (e.g., Apache) with an ingress (e.g., NGINX)</li><li>(Optional) Caching layer</li><li>Web <em>Application</em> layer (e.g., WordPress)</li><li>Object Cache layer (e.g., memcached and/or in-memory)</li><li>MySQL Database layer</li><li>Filesystem layer (see also <a aria-label="undefined (opens in a new tab)" href="https://helpdeskgeek.com/linux-tips/what-are-inodes-in-linux-and-how-are-they-used/" target="_blank" rel="noreferrer noopener">Help Desk Geek's article on Inodes in Linux</a>)</li></ol>



<p>While I don't know SiteGround's architecture explicitly, I am fairly certain that SiteGround is using NGINX, Apache, memcached, and a database (MySQL or PostgreSQL) <em>all</em> on the <span style="text-decoration: underline;"><em>same set</em></span> of resources. There is no resource separation or isolation for preventing interference with one another (though I could be convinced that NGINX is separate from the resources as it appears to be a global thing). At scale, you would have each of these items isolated (and at super-scale a sharded MySQL, but you can ignore this as most WordPress sites don't need this level of scale). </p>



<div class="wp-block-columns">
<div class="wp-block-column">
<figure class="wp-block-image size-large"><img loading="lazy" width="798" height="1024" src="https://wpsmith.net/wp-content/uploads/2020/08/siteground-wordpress-798x1024.png" alt="" class="wp-image-70086" srcset="https://wpsmith.net/wp-content/uploads/2020/08/siteground-wordpress-798x1024.png 798w, https://wpsmith.net/wp-content/uploads/2020/08/siteground-wordpress-234x300.png 234w, https://wpsmith.net/wp-content/uploads/2020/08/siteground-wordpress-768x985.png 768w, https://wpsmith.net/wp-content/uploads/2020/08/siteground-wordpress.png 1149w" sizes="(max-width: 798px) 100vw, 798px" /></figure>



<p></p>
</div>



<div class="wp-block-column">
<figure class="wp-block-image size-large"><img loading="lazy" width="962" height="960" src="https://wpsmith.net/wp-content/uploads/2020/08/lnamp.png" alt="" class="wp-image-70087" srcset="https://wpsmith.net/wp-content/uploads/2020/08/lnamp.png 962w, https://wpsmith.net/wp-content/uploads/2020/08/lnamp-300x300.png 300w, https://wpsmith.net/wp-content/uploads/2020/08/lnamp-150x150.png 150w, https://wpsmith.net/wp-content/uploads/2020/08/lnamp-768x766.png 768w" sizes="(max-width: 962px) 100vw, 962px" /></figure>
</div>
</div>



<p>So far, I have derived the following sequence on SiteGround: </p>



<ol><li>Traffic enters the ecosystem via NGINX (called an ingress). If you have <a href="https://wordpress.org/plugins/sg-cachepress/" target="_blank" rel="noreferrer noopener">SG Optimizer</a> installed and enabled/configured via the <a aria-label="undefined (opens in a new tab)" href="https://tools.siteground.com/cacher" target="_blank" rel="noreferrer noopener nofollow">SiteTools Dashboard</a>, then NGINX will respond at that layer for all static resources (e.g., images, JS, CSS, etc.). NGINX is much, much more performant for handling these requests than Apache. </li><li>Traffic is then handed off to the site specific stack fronted by Apache as directed by <code>.htaccess</code> file. This will catch any and all static assets that missed (for whatever reason) the NGINX ingress.</li><li>If a caching plugin like <a href="https://wordpress.org/plugins/sg-cachepress/" target="_blank" rel="noreferrer noopener">SG Optimizer</a> or <a href="https://wpsmith.net/go/wp-rocket/" target="_blank" rel="noreferrer noopener">WP Rocket</a> is installed, then the cache may intercept the traffic and respond.</li><li>If there is no cache or cache is bypassed (called a cache miss), traffic is then handed off to WordPress to process.</li><li>WordPress will load all its core files, plugins and theme files depending on object cache and/or memcached (if configured properly on SiteGround either via <a href="https://wordpress.org/plugins/sg-cachepress/" target="_blank" rel="noreferrer noopener">SG Optimizer</a> or other caching plugin) fetching from the MySQL DB as needed (autoloading all [or mostly all] options).</li><li>The Filesystem returns all the files and data to be read by WordPress.</li></ol>



<div class="wp-block-image"><figure class="aligncenter size-large is-resized"><a href="https://helpdeskgeek.com/linux-tips/what-are-inodes-in-linux-and-how-are-they-used/" target="_blank" rel="noopener noreferrer"><img loading="lazy" src="https://wpsmith.net/wp-content/uploads/2020/08/filesystem-inode.jpg" alt="" class="wp-image-70085" width="340" height="244" srcset="https://wpsmith.net/wp-content/uploads/2020/08/filesystem-inode.jpg 680w, https://wpsmith.net/wp-content/uploads/2020/08/filesystem-inode-300x215.jpg 300w" sizes="(max-width: 340px) 100vw, 340px" /></a></figure></div>



<p>Here's a sequence diagram that may help...<em>hopefully</em>.</p>



<div class="wp-block-wp-mermaid-block mermaid">














sequenceDiagram
	
participant Client
participant NGINX
participant Apache
participant WordPress
participant Memcached
participant MySQL
participant Filesystem

Client->>NGINX: A Request
NGINX->>Filesystem: Checks cache
alt NGINX Miss
    note over NGINX,Apache: NGINX checks the cache.&lt;br>If not cached, continue.
    Filesystem-->>NGINX: (Empty)
    NGINX->>Apache: Cache MISS
    note over Apache, WordPress: Apache checks .htaccess
    Apache->>Filesystem: Checks cache
    alt Apache Miss 
    	Filesystem-->>Apache: (Empty)
        Apache->>WordPress: Cache Miss\nBegin Processing Request
        WordPress->>Filesystem: Load WP PHP Files
        WordPress->>Memcached: WP checks cache
        Memcached->>Filesystem: Get Data
        alt Not Cached
            note over WordPress,MySQL: If Object Cache does not have it, get from DB
            Filesystem-->>Memcached: (Empty)
            Memcached-->WordPress: (Empty)
            WordPress->MySQL: Query DB
            MySQL->Filesystem: Get data
            Filesystem->MySQL: Read data
            MySQL->WordPress: Fres Data
        else DB Cached
            Memcached->WordPress: Cached Data
        end

        WordPress->WordPress: Process query
        opt Populate DB Cache
            WordPress->Memcached: Populate Cache
            Memcached->Filesystem: Write Data
        end
        opt Plugin Populates File Cache
            WordPress->Filesystem: Cache HTML, Write Data
        end
        WordPress->Apache: Response
    else Apache Cached
        note over Apache, WordPress: Apache gets cached file
        Filesystem->Apache: Cached Response
    end
else NGINX Cache
    note over NGINX, Apache: If cached, get the cached file.
    Filesystem->NGINX: Cached Response
end


NGINX->Client: The Response














</div>



<p>By default, SiteGround configures <code>http2_idle_timeout</code> and <code>http2_recv_timeout</code> to <code>600</code> seconds, and these are not changeable. Also by default, the <code>max_execution_time</code> of PHP is 120s, which is configurable via <code>user.ini</code> at the root of your site (same location as <code>wp-config.php</code>). So if you increase the <code>max_execution_time</code> to <code>600</code> or greater then you will eventually see 499s as opposed to 5XXs since NGINX will timeout before the PHP times out.</p>



<p>Next, you need to understand the most vulnerable parts of WordPress. Outside the known issues with <code>load-scripts</code> and <code>load-styles</code>, the most vulnerable parts of WordPress are:</p>



<ul><li>XMLRPC</li><li>Login Page</li><li>Admin Area</li><li>Any theme/plugin <code>index.php</code> files</li></ul>



<p>If you look at your access logs, you will find that bots, people, crawlers, scrapers, etc. will be hitting those URLs trying to gain access to your site...just because they can. So you want to mitigate those as soon as you are able.</p>



<h4 id="support-expectations-for-5xx-errors"><strong>What to Expect from Managed Hosting Technical Support</strong></h4>



<p>If you engage the SiteGround technical support, more than likely you will be referred to external WordPress experts, like myself. At best, they will tell you to scale your site with more RAM or CPU, which obviously helps them (and really doesn't solve the problem). Running a WooCommerce WordPress site on SiteGround should be able to run well with 3-4 CPUs and 6-8GB RAMs assuming you have the appropriate plugins, architecture and caching established.</p>



<p>Alternatively, technical support may tell you something like the site has high IOPS (input/output operations). Simply, IOPS are read/writes of the hard disk. IOPS is the reading of the various PHP files (plugins/themes and template files) as well as the writing of cache files and MySQL transactions in order to render the site. Higher IOPS also increases memory usage and in some occasions increases CPUs (but rarely with WordPress sites). In my experience, high IOPS is characteristic of many eCommerce sites and that’s one of the few problems and is a symptom of many other potential root causes. This data and debug information is useful <strong><em>if</em></strong> you have access to monitor these processes, which on a managed host like SiteGround, you do not have.</p>



<h4 id="solving-499-502-503-504-errors"><strong>So what do you do to solve your 499, 502, &amp; 503 issues?</strong></h4>



<p>Depending on your setup, the plan I would create may differ, but generally speaking you would need to take the following actions. I attempted to organize these actions in a somewhat logical order, but depending on the situation, I would do some tasks before other tasks. Also, while these items will work almost on any host, all examples will focus almost solely on SiteGround. These actions are:</p>



<ol><li><a href="#analyze-logs">Analyze the Logs for 499s, 500s, 502s, 503s, &amp; 504s</a></li><li><a href="#check-php-version">Check PHP Version</a></li><li><a href="#wp-doctor">Run WP CLI’s Doctor Command</a></li><li><a href="#cdn">Properly Configure a CDN</a></li><li><a href="#xmlrpc">Disable XMLRPC</a></li><li><a href="#bots">Control Bots</a></li><li><a href="#ram-cpu">Check Memory &amp; Compute Utilization</a></li><li><a href="#cron-jobs">Configure Proper Cron Jobs</a></li><li><a href="#plugins">Use Optimized Plugins</a></li><li><a href="#optimize-db">Optimize the Database</a></li><li><a href="#offload-emails">Offload All Emails</a></li><li><a href="#limit-ajax">Limit AJAX Usage</a></li><li><a href="#offload-images">Offload Images/Assets</a></li><li><a href="#analyze-wp-actions">Analyze WP Actions &amp; Filters</a></li><li><a href="#cache-strategy">Determine Cache Strategy</a></li></ol>



<h5 id="analyze-logs"><strong>1. Analyze the Logs</strong> for 499s, 500s, 502s, 503s, &amp; 504s</h5>



<p>First and foremost, you want to check all the logs to see what is impeding or bogging down the server.  This exercise is entirely exploratory and will only reveal further issues that need to be addressed. Based on work I have done so far, most of the time these will reveal issues that will be addressed in subsequent items (e.g., XML-RPC, bots, etc.). Sometimes, however, they reveal gems.</p>



<p><strong>Access logs</strong> are in a gzipped file, so you need to inspect them using <code>zcat</code>. SSH into the site and check the logs. You can find them at <code>www/domain.com/logs/</code>. You can find all the errors by using one of these commands:</p>


<a href="https://gist.github.com/8535c049e6c732252d2ebf4a8de45b30" target="_blank"><em>View this code snippet on GitHub.</em></a>



<p>As you work through the access logs, you will find a variety of pages that are the targets of various crawlers/bots and users. More than likely, the bots are causing most of the damage. If you have a WooCommerce site, you want to check the various Woo pages as well as their AJAX calls (via <code>wc-ajax</code>). Also, check your archive pages, your <code>/feed/</code> pages, and the WP API (<code>/wp-json/</code>) URLs.</p>



<p>The format of a log entry at SiteGround is a bit different. SiteGround uses a Custom Log Format combining logs from Apache and NGINX. So, in the techy world it looks like this (if you're not techy, just skip this):</p>



<p>In human words, it is this:</p>


<a href="https://gist.github.com/e5c98c170bc9a644b6eb455c7efde39c" target="_blank"><em>View this code snippet on GitHub.</em></a>


<a href="https://gist.github.com/e5c98c170bc9a644b6eb455c7efde39c" target="_blank"><em>View this code snippet on GitHub.</em></a>



<p>For an explanation of the latter third see <a href="http://nginx.org/en/docs/http/ngx_http_upstream_module.html#variables" target="_blank" aria-label="undefined (opens in a new tab)" rel="noreferrer noopener nofollow">NGINX's Embedded Variables</a>.</p>



<p>Here's a real example (with IP and domain obfuscated):</p>


<a href="https://gist.github.com/e5c98c170bc9a644b6eb455c7efde39c" target="_blank"><em>View this code snippet on GitHub.</em></a>



<p><strong><em>Error Logs</em></strong> are currently <strong><em>only</em></strong> available via the SiteGround dashboard. According to the SiteGround Dashboard:</p>



<figure class="wp-block-pullquote"><blockquote><p>The error log displays the <strong><em>300 most recent errors</em></strong> that have occurred when accessing your website over HTTP or HTTPS. Reviewing the error log can be useful for troubleshooting broken links, files and other errors.</p></blockquote></figure>



<p>However, this is not true at all. At the time of writing this post, they only show the <strong>50 most recent errors</strong>. I did file a ticket with SiteGround and they have escalated the issue to their DevOps team but no timeline has been given as to when it will be fixed.</p>



<p><strong><em>PHP Error Logs &amp; WP Logs</em></strong> are only available via SSH or FTP. For PHP Error Logs, you will find a file like <code>php_errorlog</code> and potentially <code>error_log</code> in the folder where the PHP error occurred, which is somewhat annoying. So you want to find this via <code>find . -name "php_errorlog"</code> on the SSH command line or use the find function in your favorite FTP client.</p>



<p>For WP Logs, check <code>wp-content/debug.log</code>. If the file does not exist (and really should not on a production site), you want to temporarily enable <code>WP_DEBUG</code> in <code>wp-config.php</code>. This can even be done dynamically via:</p>


<a href="https://gist.github.com/22ec50c29488da78b12f45ad0572c59a" target="_blank"><em>View this code snippet on GitHub.</em></a>



<p>The way this work is probably self-evident but it is a method that I use on the majority of the sites I do any development. It's a great and secure method to never have to edit <code>wp-config.php</code> continually.</p>



<p>If you are thinking, "Ok, I realize this is too much for me," you can <a aria-label="undefined (opens in a new tab)" href="https://wpsmith.net/hire-a-wordpress-developer/" target="_blank" rel="noreferrer noopener nofollow">hire a developer</a> or <a href="/contact/">myself</a> to help you through this.</p>



<div class="wp-block-buttons aligncenter">
<div class="wp-block-button"><a class="wp-block-button__link" href="/contact/"><strong>Hire Me!</strong></a></div>



<div class="wp-block-button is-style-outline"><a class="wp-block-button__link" href="https://wpsmith.net/hire-a-wordpress-developer/" target="_blank" rel="noopener noreferrer">Hire Me on Codeable</a></div>
</div>



<h5 id="check-php-version"><strong>2. Check PHP Version</strong></h5>



<p>If you are on SiteGround, more than likely you are on the Managed PHP version and are on the latest version of PHP, but it's worth a check. PHP 7.x provides more performance and security than PHP 5.x. You can check your PHP version in SiteTools &gt; Devs &gt; <a aria-label="undefined (opens in a new tab)" href="https://tools.siteground.com/php-settings" target="_blank" rel="noreferrer noopener nofollow">PHP Manager</a> (<a aria-label="undefined (opens in a new tab)" href="https://tools.siteground.com/php-settings" target="_blank" rel="noreferrer noopener nofollow">https://tools.siteground.com/php-settings</a>).</p>



<h5 id="wp-doctor"><strong>3. Run WP CLI's Doctor</strong> Command</h5>



<p>By default, WP CLI is installed on the server, but the doctor command is not. So first you will need to install the WP CLI doctor command via <code>wp package install git@github.com:wp-cli/doctor-command.git</code> and then run <code>wp doctor check --all</code> at the root of the WordPress site (same location as <code>wp-config.php</code>) and examine those issues to fix. I use a custom yaml configuration for my magic fixes and to automate some of the items listed in this longer-than-expected blog post.</p>


<a href="https://gist.github.com/f89b2157d41295125bca0ca9fe7d203c" target="_blank"><em>View this code snippet on GitHub.</em></a>



<h5 id="cdn"><strong>4. Properly Configure a CDN</strong></h5>



<p>In order to prevent load from reaching your server, you must establish a solid caching strategy including browser cache and an edge cache via configuring a CDN. It is the easiest and fastest way to prevent useless load on your server which reduces 499, 503 and 504 errors. I always recommend that clients either use <a aria-label="undefined (opens in a new tab)" href="https://cloudflare.com/" target="_blank" rel="noreferrer noopener nofollow">Cloudflare</a> or <a aria-label="undefined (opens in a new tab)" href="https://fastly.com" target="_blank" rel="noreferrer noopener nofollow">Fastly</a> (if you're OpenSource software, <a href="https://fastly.com/" target="_blank" rel="noreferrer noopener">Fastly</a> will front your site for free).</p>



<p>Implement the free version of <a href="https://cloudflare.com" target="_blank" aria-label="undefined (opens in a new tab)" rel="noreferrer noopener nofollow">Cloudflare</a> (personally, I would do this at <a href="https://cloudflare.com/" target="_blank" aria-label="undefined (opens in a new tab)" rel="noreferrer noopener nofollow">Cloudflare</a> and not via SiteGround). Within <a href="https://cloudflare.com/" target="_blank" aria-label="undefined (opens in a new tab)" rel="noreferrer noopener nofollow">Cloudflare</a>, enhance security around <code>/wp-login.php*</code> and <code>/wp-admin/*</code>, geofence <code>/wp-admin</code>, and set the browser cache of general assets to a few months or even a year and the edge cache to a month or two.</p>



<p>I always recommend paying for <a aria-label="undefined (opens in a new tab)" href="http://cloudflare.com/pricing" target="_blank" rel="noreferrer noopener nofollow">Cloudflare Pro</a> minimally. This gives you image optimization out-of-the-box, plus more rules. Alternatively, you can use something like <a href="https://wpsmith.net/go/optimole/" target="_blank" aria-label="undefined (opens in a new tab)" rel="noreferrer noopener nofollow">Optimole</a>.</p>



<h5 id="xmlrpc"><strong>5. Disable <a href="https://codex.wordpress.org/XML-RPC_Support" target="_blank" rel="noreferrer noopener">XML-RPC</a></strong></h5>



<p>What is <a href="https://codex.wordpress.org/XML-RPC_Support" target="_blank" rel="noreferrer noopener">XML-RPC</a>? </p>



<p><a aria-label="undefined (opens in a new tab)" href="https://codex.wordpress.org/XML-RPC_Support" target="_blank" rel="noreferrer noopener nofollow">XML-RPC</a>&nbsp;on WordPress is an interface that allows apps and other services the ability to talk to your WordPress site to do any of the following:</p>



<ul><li>Publish, Edit, or Delete a Post</li><li>Upload a new file (e.g. an image for a post)</li><li>List or Edit Comments</li></ul>



<p>Because of these capabilities, it is a potential security vulnerability and open for an attack. Most websites today do not use the capabilities offered via <a href="https://codex.wordpress.org/XML-RPC_Support" target="_blank" rel="noreferrer noopener">XML-RPC</a> especially since the WP API has been released.</p>



<p>I always recommend simply disabling <a href="https://codex.wordpress.org/XML-RPC_Support" target="_blank" rel="noreferrer noopener">XML-RPC</a> and block access to <code>xmlrpc.php</code> via <code>.htaccess</code> and/or <a rel="noreferrer noopener" href="https://cloudflare.com/" target="_blank">Cloudflare</a>. Blocking at Cloudflare will reduce load on the server altogether and blocking at <code>.htaccess</code> will reduce load on the processing of the web application (i.e., WordPress).</p>


<a href="https://gist.github.com/46db0964ad0468b1617fe34f662fe457" target="_blank"><em>View this code snippet on GitHub.</em></a>



<h5 id="bots"><strong>6. Control the Bots</strong></h5>



<p>While resistance may be futile when it comes to bots, you do want to attempt to control them in some way that benefits your site and your audience. If the bots are hitting your site/server so hard that you cannot even serve your true customers, what benefit is for you to have these bots index your site? None because they will penalize you for being down. So preventing bots from hitting your sites primarily addresses 499s and some of the 500s errors as some of these errors are not appropriately identified on SiteGround.</p>



<p><em>Good Bots</em>: If you are running an eCommerce site, you most likely will want to redirect all bots away from adding items to their cart as identified by <code>?add-to-cart</code> in the access logs; even good bots like <code>bingbot</code>, <code>googlebot</code>, <code>ahrefs</code>, <code>semrush</code>, and others do this. On SiteGround, to find out what these are simply go to the logs and execute:</p>



<pre class="wp-block-preformatted">zcat domain.com-YYYY-MM-DD.gz | grep "bot" | grep "?add-to-cart"</pre>



<p>Please note, that these good bots may also cause a server load on your site. Generally, I would recommend delaying the bots that are not important to you. If googlebot is causing you issues, you can set its delay in the <a aria-label="undefined (opens in a new tab)" href="https://support.google.com/webmasters/answer/48620" target="_blank" rel="noreferrer noopener nofollow">Google Search Console</a>.</p>


<a href="https://gist.github.com/c440ef4fa1667924967ad6ba83eec94c" target="_blank"><em>View this code snippet on GitHub.</em></a>



<p><em>Bad Bots</em>: Block all bad bots via <code>.htaccess</code> or via <a href="https://cloudflare.com/pricing" target="_blank" aria-label="undefined (opens in a new tab)" rel="noreferrer noopener nofollow">Cloudflare Pro</a>. You can access this <a aria-label="undefined (opens in a new tab)" href="http://www.botreports.com/badbots/index.shtml" target="_blank" rel="noreferrer noopener nofollow">Bad Bots list</a> to see all the bad bot user agents.</p>



<h5 id="ram-cpu"><strong>7. Check the Memory (RAM) and Compute (CPU) Utilization</strong></h5>



<p>There are two things you want to enable with your memory and CPU: one via WordPress and the other via SiteGround Dashboard.</p>



<ol><li><em>Increase WordPress PHP Memory Limit</em> via a define statement in <code>wp-config.php</code>.<br><code>define( 'WP_MEMORY_LIMIT', '1024M' );</code></li><li><em>Enable CPU and RAM Autoscaling</em> on SiteGround ($$). You can do this in your site's account (URL will be something like https://my.siteground.com/services/hosting/{SOME-CRAZY-ID}/autoscale). In order to prevent all 5XX errors, this <strong><em>must be enabled</em></strong>. Any hosting company that offers auto-scaling, no matter how good or bad it is, a site owner should <em>always</em> elect to use it.</li></ol>



<h5 id="cron-jobs"><strong>8. Configure Proper Cron Jobs</strong></h5>



<p>By default the&nbsp;WordPress cron&nbsp;is&nbsp;run&nbsp;by the <code>wp_cron()</code> function, which is hooked to&nbsp;run&nbsp;on the init hook, which&nbsp;runs on every page load.&nbsp;Disable WP Cron via a define statement in <code>wp-config.php</code>:<br><code>define( 'DISABLE_WP_CRON', true );</code><br>Then, setup a "true" cron job via the <a aria-label="undefined (opens in a new tab)" href="https://tools.siteground.com/cron" target="_blank" rel="noreferrer noopener nofollow">SiteGround SiteTools Dashboard</a>, Pingdom, or Uptime Robot.</p>



<h5 id="plugins"><strong>9. Use Optimized Plugins</strong></h5>



<p>Plugins are great, after all, "There's a plugin for that!" However, plugins can cause massive problems if they are not designed well or use too much compute from the server. So let's take a look at a few plugin categories: Caching Plugins, Security Plugins, BackupPlugins, and Related PostsPlugins.</p>



<p><em>Caching Plugins</em>: Properly configure either <a rel="noreferrer noopener" href="https://wordpress.org/plugins/sg-cachepress/" target="_blank">SG Optimizer</a>. If you want something with more control and settings, install and configure <a rel="noreferrer noopener" href="https://wpsmith.net/go/wp-rocket/" target="_blank">WP Rocket</a>. Using <a rel="noreferrer noopener" href="https://wpsmith.net/go/wp-rocket/" target="_blank">WP Rocket</a> renders <a rel="noreferrer noopener" href="https://wordpress.org/plugins/sg-cachepress/" target="_blank">SG Optimizer</a> useless (because <a rel="noreferrer noopener" href="https://wpsmith.net/go/wp-rocket/" target="_blank">WP Rocket</a> has logic inside the plugin to mitigate SG Optimizer), so you will need to implement memcached yourself, and you will need to be sure to install the <a href="https://docs.wp-rocket.me/article/919-disable-cache-for-logged-in-administrators" target="_blank" aria-label="undefined (opens in a new tab)" rel="noreferrer noopener nofollow">No Cache for Administrators Add-on</a>.</p>



<p><em>Security Plugins</em>: Some security plugins are resource hogs and Wordfence is one of those. If you are using Wordfence, uninstall it, install <a aria-label="undefined (opens in a new tab)" rel="noreferrer noopener nofollow" href="https://wordpress.org/plugins/limit-login-attempts-reloaded/" target="_blank">Limited Login Attempts Reloaded</a>, and use <a href="https://cloudflare.com/pricing/" target="_blank" aria-label="undefined (opens in a new tab)" rel="noreferrer noopener nofollow">Cloudflare Pro</a> and/or <a aria-label="undefined (opens in a new tab)" rel="noreferrer noopener" href="/go/sucuri/" target="_blank">Sucuri</a> as a web application firewall (WAF); both <a href="https://cloudflare.com/pricing/" target="_blank" aria-label="undefined (opens in a new tab)" rel="noreferrer noopener nofollow">Cloudflare</a> and <a rel="noreferrer noopener" href="https://wpsmith.net/go/sucuri/" target="_blank">Sucuri</a> are $20/mo.</p>



<p><em>Backup Plugins</em>: SiteGround backs-up your files and DB daily which appear to run around 8am UTC time. To verify, go to your Backups in the SiteGround Dashboard via SiteTools &gt; Security &gt; <a aria-label="undefined (opens in a new tab)" href="https://tools.siteground.com/backup-restore" target="_blank" rel="noreferrer noopener nofollow">Backups</a> (<a href="https://tools.siteground.com/backup-restore">https://tools.siteground.com/backup-restore</a>) and note the time, which will be in your timezone. So, you really do not need a backup plugin.</p>



<p><em>Server Plugins</em>: <a aria-label="undefined (opens in a new tab)" rel="noreferrer noopener" href="https://wordpress.org/plugins/broken-link-checker/" target="_blank">Broken Link Checker</a> is a notoriously awful plugin to run on your server. So I always recommend only using it when you <em>have to use it</em> and then uninstall it. Also for emails, use a plugin like <a aria-label="undefined (opens in a new tab)" rel="noreferrer noopener" href="/go/wp-mail-smtp/" target="_blank">WP SMTP</a> where you can offload your server emails to another service. Not only does this remove server load, it removes server responsibility and ensures your IP doesn't get blacklisted by Google's servers (which are also connected with Gmail analyzing bad email actors).</p>



<p><em>Related Posts Plugins</em>: Most of these plugins are horrible and hog resources. Simply, <em>do not use</em> and uninstall <a aria-label="undefined (opens in a new tab)" href="https://wordpress.org/plugins/seo-alrp/" target="_blank" rel="noreferrer noopener">SEO Auto Links &amp; Related Posts</a>, <a aria-label="undefined (opens in a new tab)" href="https://wordpress.org/plugins/yet-another-related-posts-plugin/" target="_blank" rel="noreferrer noopener">Yet Another Related Posts Plugin</a>, <a aria-label="undefined (opens in a new tab)" href="https://wordpress.org/plugins/similar-posts/" target="_blank" rel="noreferrer noopener">Similar Posts</a>, &amp; <a aria-label="undefined (opens in a new tab)" href="https://wordpress.org/plugins/contextual-related-posts/" target="_blank" rel="noreferrer noopener">Contextual Related Posts</a>. Instead you want to use a related posts plugin that does all its compute offsite (e.g., <a aria-label="undefined (opens in a new tab)" href="https://www.bibblio.org/wordpress" target="_blank" rel="noreferrer noopener nofollow">Bibblio Related Posts</a>, <a aria-label="undefined (opens in a new tab)" href="http://jetpack.me/support/related-posts/" target="_blank" rel="noreferrer noopener nofollow">Jetpack Related Posts</a>, <a aria-label="undefined (opens in a new tab)" href="https://www.relatedpostsforwp.com/" target="_blank" rel="noreferrer noopener nofollow">Related Posts for WordPress</a>, <a aria-label="undefined (opens in a new tab)" href="http://www.outbrain.com/" target="_blank" rel="noreferrer noopener nofollow">Outbrain</a>, <a aria-label="undefined (opens in a new tab)" href="http://contextly.com/" target="_blank" rel="noreferrer noopener nofollow">Contextly</a>).</p>



<p>For a list of plugins, you should never use, see <a aria-label="undefined (opens in a new tab)" href="https://wpengine.com/support/disallowed-plugins/" target="_blank" rel="noreferrer noopener nofollow">WP Engine's Disallowed Plugin List</a>. If you are not hosted on WP Engine, then you can ignore Duplicate Behavior Plugins section. </p>



<p>Finally, always remove plugins that you are not using, even if you use them periodically.</p>



<h5 id="optimize-db"><strong>10. Optimize the Database</strong></h5>



<p class="has-text-align-center"><strong><em>Before you do anything with the database, </em><span style="text-decoration: underline;">always</span><em> create a backup! Always! </em></strong></p>



<p><code>wp doctor</code> will check your database (DB) for the size of your auto-loaded options and recommends that it be below 900kb (by default). You can also use <code>wp db optimize</code> to further optimize the DB. To reduce the database, I use <a aria-label="undefined (opens in a new tab)" rel="noreferrer noopener nofollow" href="https://wpsmith.net/go/advanced-database-cleaner/" target="_blank">WordPress Advanced Database Cleaner</a> to do find orphaned options, etc.</p>



<p>Generally speaking, if the DB is good according to the doctor, then I do nothing. If it is not, then I will take action. However, the WordPress DB can almost always be optimized further. If this is interesting to you, I'd advise you to hire a MySQL DB administrator to help you think this through.</p>



<h5 id="offload-emails"><strong>11. Offload All Emails</strong></h5>



<p>Many hosting companies offer email hosting with their plans, and SiteGround is one of those companies. SiteGround's email hosting leverages RoundCube for its webmail client. This also creates load on your server resources, and IMHO, always, always offload email hosting to another third party like Google Suite, Microsoft Office 365, ZohoMail, Greatmail or even hey.com.</p>



<p>Also, WordPress sends out emails (e.g., user registration, forgot password, reset password, etc.). WordPress should be configured via <a href="https://wpsmith.net/go/wp-mail-smtp/" target="_blank" aria-label="undefined (opens in a new tab)" rel="noreferrer noopener nofollow">WP Mail SMTP</a> to send emails using a third party service like SendGrid, Google Suite, Sendinblue, or Mailgun. </p>



<p>Offloading email from your server will free compute (because monitoring, logging, etc. on those processes are not required) and ensure that your servers are not blacklisted or blocked as a result of some sort of email hack or mass email blasts.</p>



<h5 id="limit-ajax"><strong>12. Limit AJAX Usage</strong></h5>



<p>AJAX creates an awesome user experience, and if improperly implemented can also create a detrimental user experience. When considering AJAX, the tradeoff is simple: UX v. Server Costs/Uptime. In order to determine this, you need some good marketing analytics and probably some A/B testing with server correlations (which is fairly difficult to do correctly).</p>



<h6><em>Themes/Plugins</em></h6>



<p>Many themes and plugins use AJAX to improve the user experience (UX). The problem with WordPress's AJAX is that it is not cached by default because it is accessing <code>wp-admin/admin-ajax.php</code>. Most caching plugins ignore <code>/wp-admin/</code> in its caching, <em>and</em> generally speaking AJAX functions IMHO should only be for custom, personalized functionality; for all else, use the WP REST API (which is usually cached by default).</p>



<h6 class="inline">WooCommerce</h6>



<p>WooCommerce uses AJAX a ton; or rather they can and do by default. WooCommerce has also implemented their own AJAX endpoints instead of the standard <code>admin-ajax.php</code> (good, bad or indifferent). The Add to Cart AJAX (via <code>/?wc-ajax=add_to_cart</code>) isn't so bad, but the Cart Fragments (via <code>/?wc-ajax=get_refreshed_fragments</code>) can be quite detrimental to your server (and even possibly Google PageSpeed Insights; though I am not convinced that it is blocking).</p>



<p>WooCommerce's Cart Fragments is extremely hard on the server as it was built without caching in mind. This is because they hash every cart and every cart item as well as using nonces to remove items (for security purposes most likely). It would be easier for Woo/Automattic to re-create and develop cart fragments with statelessness in mind (than doing it yourself in Woo's software pattern). But I doubt they will fix this. Additionally, most eCommerce sites have the cart on every page, including the About page of a site.</p>



<p class="inline">Here is an example after adding one item to the cart:</p>


<a href="https://gist.github.com/718a8f08a265a3228ffdf70fa2ef618f" target="_blank"><em>View this code snippet on GitHub.</em></a>



<p>Here is an example after adding a second item to the cart:</p>


<a href="https://gist.github.com/718a8f08a265a3228ffdf70fa2ef618f" target="_blank"><em>View this code snippet on GitHub.</em></a>



<p>As you can see <code>get_refreshed_fragments</code> refreshes the <em>entire</em> cart. This makes it nearly impossible to cache well. If the response was broken down to the smaller items (e.g., <code>mini_cart_item</code>) then it can be cached. Otherwise, you cannot cache this due to the hashes and well, you don't want everyone buying the same thing...unless you do (well I guess you may be able to pull this off if you only have one item with no variations, etc.). </p>



<p>So what do you do? If you are struggling with server load and want something simple and fast, just do these 4 things:</p>



<ol><li>Disable AJAX add to cart buttons on archives,</li><li>Redirect customers to the cart upon adding items,</li><li>Remove cart fragments, and</li><li>Remove all cart widgets</li></ol>



<figure class="wp-block-image size-large"><img loading="lazy" width="1024" height="359" src="https://wpsmith.net/wp-content/uploads/2020/08/woocommerce-settings-product-ajax-enabled-1024x359.png" alt="" class="wp-image-70101" srcset="https://wpsmith.net/wp-content/uploads/2020/08/woocommerce-settings-product-ajax-enabled-1024x359.png 1024w, https://wpsmith.net/wp-content/uploads/2020/08/woocommerce-settings-product-ajax-enabled-300x105.png 300w, https://wpsmith.net/wp-content/uploads/2020/08/woocommerce-settings-product-ajax-enabled-768x269.png 768w, https://wpsmith.net/wp-content/uploads/2020/08/woocommerce-settings-product-ajax-enabled.png 1140w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<h6 class="inline">To disable AJAX add to cart buttons on archives,</h6>



<p class="inline">within WooCommerce &gt; Products, beside <em>Add to cart behaviour</em> uncheck <em>Enable AJAX add to cart buttons on archives.</em></p>



<h6 class="inline">To redirect customers to the cart upon adding items,</h6>



<p class="inline">within WooCommerce &gt; Products, beside <em>Add to cart behaviour</em> check <em>Redirect to the cart page after successful addition.</em></p>



<figure class="wp-block-image size-large"><img loading="lazy" width="1024" height="359" src="https://wpsmith.net/wp-content/uploads/2020/08/woocommerce-settings-product-change-1024x359.png" alt="" class="wp-image-70102" srcset="https://wpsmith.net/wp-content/uploads/2020/08/woocommerce-settings-product-change-1024x359.png 1024w, https://wpsmith.net/wp-content/uploads/2020/08/woocommerce-settings-product-change-300x105.png 300w, https://wpsmith.net/wp-content/uploads/2020/08/woocommerce-settings-product-change-768x269.png 768w, https://wpsmith.net/wp-content/uploads/2020/08/woocommerce-settings-product-change.png 1140w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<h6 class="inline">To remove cart fragments,</h6>



<p>you can use a plugin or custom code within your theme's <code>functions.php</code> (or even better as a basic custom plugin). If you do disable cart fragments, be sure to enable <em>Add to cart behavior</em>'s <em>Redirect to the cart page after successful addition.</em></p>



<p>Within <em>functions.php</em>, you can add one of these snippets:</p>



<p><em>Disable cart fragments on the front page only:</em></p>


<a href="https://gist.github.com/38478709c06eb7aa2010be4c4ebfc905" target="_blank"><em>View this code snippet on GitHub.</em></a>



<p><em>Disable cart fragments everywhere except WooCommerce shop pages:</em></p>


<a href="https://gist.github.com/38478709c06eb7aa2010be4c4ebfc905" target="_blank"><em>View this code snippet on GitHub.</em></a>



<p>Using a <em>plugin</em>, you can disable Cart Fragments with the <a aria-label="undefined (opens in a new tab)" href="https://wordpress.org/plugins/disable-cart-fragments/" target="_blank" rel="noreferrer noopener">Disable Cart Fragments</a> plugin, with <a aria-label="undefined (opens in a new tab)" href="https://wordpress.org/plugins/trimpress/" target="_blank" rel="noreferrer noopener">TrimPress</a> (which also does many other things), or <a href="https://wpsmith.net/go/perfmatters/" target="_blank" aria-label="undefined (opens in a new tab)" rel="noreferrer noopener">Perfmatter's Premium Plugin</a>. Some have had success with using <a aria-label="undefined (opens in a new tab)" href="https://wordpress.org/plugins/wp-menu-cart/" target="_blank" rel="noreferrer noopener">WP Menu Cart</a> as an alternative to the default Woo Cart.</p>



<p>The great thing about the <a href="https://wordpress.org/plugins/disable-cart-fragments/" target="_blank" rel="noreferrer noopener">Disable Cart Fragments</a> is that you can selectively disable cart fragments.</p>


<a href="https://gist.github.com/38478709c06eb7aa2010be4c4ebfc905" target="_blank"><em>View this code snippet on GitHub.</em></a>



<h6>Cart Fragments Reimagined Plugin Sponsorship</h6>



<p>If one wants to sponsor the creation of a custom plugin with a custom cart fragments implementation in order to cacheability, improve performance and server load, I would be excited for the opportunity. The cost to do this would be the equivalent of having a custom plugin created. I would love to be funded by someone to create an extension for WooCommerce that does this properly and correctly.</p>



<h6>WooCommerce Reports</h6>



<p>One of the hidden costs of WooCommerce is the async (or on-demand) reporting computations for the WooCommerce MailChimp integration and WooCommerce reports. This can place a <strong><em>massive</em></strong> load on your server. To fix this you need to disable the amount of the user's spend and/or move <code>get_total_spend()</code> post meta data to its own custom DB table. To do both, you can use my plugin or to do just disable the amount of a user's spend:</p>


<a href="https://gist.github.com/db4f5fe63409ac66fcef02c18f970cd8" target="_blank"><em>View this code snippet on GitHub.</em></a>



<p>To limit the heartbeat, install <a aria-label="undefined (opens in a new tab)" href="https://wordpress.org/plugins/heartbeat-control/" target="_blank" rel="noreferrer noopener nofollow">WP Heartbeat Control</a>. You can then set different intervals for each page type or even disable it for some pages.</p>



<h5 id="offload-images"><strong>13. Offload Images/Assets ($$)</strong></h5>



<p>Offloading your images from your server does three things:</p>



<ol><li>Reduces load (<strong>CPU</strong>) on the server.</li><li>Reduces <strong>bandwidth</strong> from the server.</li><li>Reduces <strong>storage space</strong> used on the server.</li></ol>



<p>Space on the server is a hidden cause of 5XX errors. It prevents new cache files from being written, prevents new server processes from being started creating a bottleneck, and potentially increases IOPs and thus death for some requests.</p>



<p>Since hosting companies charge based on bandwidth, CPU/RAM, and storage space, any reductions in these items will save you money and will allow you downgrade your hosting plan (though on SiteGround to reduce SSD space, you actually have to purchase a new server, migrate and cancel the old one which is a lot of fun).</p>



<p>The cost of AWS S3 is quite minimal even beyond the free tier. For example, if you have 100GB of storage and had 1 million requests for those assets (e.g., images, CSS, JS files), it would only cost you about $5 USD/month. AWS S3 is cheaper than any hosting plan's SSD space. If you have <em>a lot</em> of images, then you may want to offload them via a script, which I am happy to do for you! </p>



<p>I highly recommend you do offload your images from your server via <a href="https://wpsmith.net/go/offloadmedia/" target="_blank" rel="noreferrer noopener">WP Offload Media</a> to <a href="https://aws.amazon.com/free/" target="_blank" rel="noreferrer noopener">AWS S3</a> (or DigitalOcean Spaces or Google Cloud Storage) connected with Cloudflare to a custom domain (e.g., assets.domain.com). It also has an add-on that will pull other site assets to be delivered via S3. </p>



<p>For sites with <strong><em>a lot</em></strong> of media assets, the pricing structure of the <a href="https://wpsmith.net/go/offloadmedia/" target="_blank" rel="noreferrer noopener">WP Offload Media</a> plugin is very, very disappointing, but there are ways around this. If you are hosted on SiteGround, more than likely you are going to need some help to properly offload those images.</p>



<h5 id="analyze-wp-actions"><strong>14. Analyze the WordPress Actions</strong> &amp; Filters</h5>



<p>When troubleshooting a WordPress site, I immediately install a set of plugins:</p>



<ul><li><a href="https://wordpress.org/plugins/debug-bar/" target="_blank" rel="noreferrer noopener">Debug Bar</a> + some add-ons.</li><li><a href="https://wordpress.org/plugins/query-monitor/" target="_blank" rel="noreferrer noopener">Query Monitor</a></li><li><a href="https://wordpress.org/plugins/wp-crontrol/" target="_blank" rel="noreferrer noopener">WP Crontrol</a></li><li><a href="https://wordpress.org/plugins/transients-manager/" target="_blank" rel="noreferrer noopener">Transients Manager</a></li></ul>



<p>You can install these plugins via the WP CLI. </p>


<a href="https://gist.github.com/10e8887cd396db5406fb657d8bf94ecf" target="_blank"><em>View this code snippet on GitHub.</em></a>



<p>These plugins will provide a vast amount information about the site. Of particular focus will be the number of queries, duplicate queries, and query times.</p>



<p class="has-small-font-size"><strong>As a side note</strong>: Generally, when I am debugging a site, I have almost all the Debug Bar plugins installed. Depending on the issue I install all of or a subset of the following plugins: <a aria-label="undefined (opens in a new tab)" href="https://wordpress.org/plugins/debug-bar/" target="_blank" rel="noreferrer noopener"><strong>Debug Bar</strong></a>, <a aria-label="undefined (opens in a new tab)" href="https://wordpress.org/plugins/debug-bar-actions-and-filters-addon/" target="_blank" rel="noreferrer noopener"><strong>Debug Bar Actions &amp; Filters Addon</strong></a>, <a aria-label="undefined (opens in a new tab)" href="https://wordpress.org/plugins/debug-bar-console/" target="_blank" rel="noreferrer noopener">Debug Bar Console</a>, <a aria-label="undefined (opens in a new tab)" href="https://wordpress.org/plugins/debug-bar-constants/" target="_blank" rel="noreferrer noopener"><strong>Debug Bar Constants</strong></a>, <a aria-label="undefined (opens in a new tab)" href="https://wordpress.org/plugins/debug-bar-cron/" target="_blank" rel="noreferrer noopener"><strong>Debug Bar Cron</strong></a>, <a aria-label="undefined (opens in a new tab)" href="https://wordpress.org/plugins/debug-bar-custom-info/" target="_blank" rel="noreferrer noopener">Debug Bar Custom Info</a>, <a aria-label="undefined (opens in a new tab)" href="https://wordpress.org/plugins/debug-bar-extender/" target="_blank" rel="noreferrer noopener">Debug Bar Extender</a>, <a aria-label="undefined (opens in a new tab)" href="https://wordpress.org/plugins/debug-bar-hook-log/" target="_blank" rel="noreferrer noopener">Debug Bar Hook Log</a>, <a aria-label="undefined (opens in a new tab)" href="https://wordpress.org/plugins/debug-bar-list-dependencies/" target="_blank" rel="noreferrer noopener"><strong>Debug Bar List Script &amp; Style Dependencies</strong></a>, <a aria-label="undefined (opens in a new tab)" href="https://wordpress.org/plugins/debug-bar-localization/" target="_blank" rel="noreferrer noopener">Debug Bar Localization</a>, <a aria-label="undefined (opens in a new tab)" href="https://wordpress.org/plugins/debug-bar-plugin-activation/" target="_blank" rel="noreferrer noopener">Debug Bar Plugin Activation</a>, <a aria-label="undefined (opens in a new tab)" href="https://wordpress.org/plugins/debug-bar-post-meta/" target="_blank" rel="noreferrer noopener">Debug Bar Post Meta</a>, <a aria-label="undefined (opens in a new tab)" href="https://wordpress.org/plugins/debug-bar-post-types/" target="_blank" rel="noreferrer noopener">Debug Bar Post Types</a>, <a aria-label="undefined (opens in a new tab)" href="https://wordpress.org/plugins/debug-bar-query-count-alert/" target="_blank" rel="noreferrer noopener">Debug Bar Query Count Alert</a>, <a aria-label="undefined (opens in a new tab)" href="https://wordpress.org/plugins/debug-bar-query-tracer/" target="_blank" rel="noreferrer noopener">Debug Bar Query Tracer</a>, <a aria-label="undefined (opens in a new tab)" href="https://wordpress.org/plugins/debug-bar-remote-requests/" target="_blank" rel="noreferrer noopener">Debug Bar Remote Requests</a>, <a aria-label="undefined (opens in a new tab)" href="https://wordpress.org/plugins/debug-bar-rewrite-rules/" target="_blank" rel="noreferrer noopener">Debug Bar Rewrite Rules</a>, <a aria-label="undefined (opens in a new tab)" href="https://wordpress.org/plugins/debug-bar-roles-and-capabilities/" target="_blank" rel="noreferrer noopener">Debug Bar Roles &amp; Capabilities</a>, <a aria-label="undefined (opens in a new tab)" href="https://wordpress.org/plugins/debug-bar-screen-info/" target="_blank" rel="noreferrer noopener">Debug Bar Screen Info</a>, <a aria-label="undefined (opens in a new tab)" href="https://wordpress.org/plugins/debug-bar-shortcodes/" target="_blank" rel="noreferrer noopener">Debug Bar Shortcodes</a>, <a aria-label="undefined (opens in a new tab)" href="https://wordpress.org/plugins/debug-bar-sidebars-widgets/" target="_blank" rel="noreferrer noopener">Debug Bar - Sidebars &amp; Widgets</a>, <a aria-label="undefined (opens in a new tab)" href="https://wordpress.org/plugins/debug-bar-slow-actions/" target="_blank" rel="noreferrer noopener"><strong>Debug Bar Slow Actions</strong></a>, <a aria-label="undefined (opens in a new tab)" href="https://wordpress.org/plugins/debug-bar-super-globals/" target="_blank" rel="noreferrer noopener"><strong>Debug Bar Super Globals</strong></a>, <a aria-label="undefined (opens in a new tab)" href="https://wordpress.org/plugins/debug-bar-taxonomies/" target="_blank" rel="noreferrer noopener">Debug Bar Taxonomies</a>, <a aria-label="undefined (opens in a new tab)" href="https://wordpress.org/plugins/debug-bar-tracer/" target="_blank" rel="noreferrer noopener">Debug Bar Tracer</a>, <a aria-label="undefined (opens in a new tab)" href="https://wordpress.org/plugins/debug-bar-transients/" target="_blank" rel="noreferrer noopener">Debug Bar Transients</a>, and <a aria-label="undefined (opens in a new tab)" href="https://wordpress.org/plugins/debug-bar-widgets/" target="_blank" rel="noreferrer noopener">Debug Bar Widgets</a>. Besides these, I also usually install <a aria-label="undefined (opens in a new tab)" href="https://wordpress.org/plugins/wp-crontrol/" target="_blank" rel="noreferrer noopener">WP Crontrol</a>, <a aria-label="undefined (opens in a new tab)" href="https://wordpress.org/plugins/transients-manager/" target="_blank" rel="noreferrer noopener">Transients Manager</a>, and <a aria-label="undefined (opens in a new tab)" href="https://wordpress.org/plugins/query-monitor/" target="_blank" rel="noreferrer noopener">Query Monitor</a>. If the issue is URL routing, I also like to use <a aria-label="undefined (opens in a new tab)" href="https://wordpress.org/plugins/rewrite-rules-inspector/" target="_blank" rel="noreferrer noopener">Rewrite Rules Inspector</a>.</p>



<h5 id="cache-strategy"><strong>15. Determine Your Caching Strategy</strong></h5>



<p>Finally and most importantly, you want to determine your caching strategy. My philosophy is simply <code>cacheAllTheThings();</code>.  To really understand this section, you should have read the <a href="#web-architecture">architecture section</a>. If you didn't please scroll back up to read it.</p>



<h6><strong>First, why cache?</strong></h6>



<p>Simply, you should always cache. Ok, but why? As we mentioned above, one primary reason is to offload work from the server. Another reason is performance. If a request is cached at the browser, that experience is super awesome and fast. If a request has to go all the way back to origin, that will always be much longer. </p>



<p>SiteGround uses Google Cloud, so your origins will be in one of these <a aria-label="undefined (opens in a new tab)" href="https://cloud.google.com/about/locations" target="_blank" rel="noreferrer noopener">locations</a>. Let's take a concrete example. Let's say your origin is in N. Virginia (Ashburn most likely), and you live in Tyler TX (location of the client). When you make a request, more than likely, it will hit the CDN POP (Point-of-Presence; basically where one of the Cloudflare servers are located) in Dallas or Houston (based on the networks and/or routing enhanced by Cloudflare's Argo) before it goes back to its origin. Getting a response is always faster from Dallas than Virginia, but in all honesty, it will be negligible. Now, let's say that you live in Liverpool UK. The request will be going to N. Virginia via the London Cloudflare POP.  So the response is a lot faster from London than it is from Virginia, and that will be noticeable.</p>



<p><em>So distributed cache via a CDN <span style="text-decoration: underline;">always</span> improves your site's speed.</em> If it doesn't, then your rules and/or strategy may not be correct.</p>



<h6>What is a cache strategy?</h6>



<p>A caching strategy has two components, relationship &amp; access:</p>



<ol><li>The <em>relationship</em> between the data, one's origin, the end user, and the caching systems, and</li><li>How your data is <em>accessed</em>.</li></ol>



<p>While we could discuss the various technical strategies (technically) like the look-aside, reading-through, writing-through, writing-around, writing-back, let's leave that for more enterprise and high-scale, high-volume sites that usually have teams or agencies building and maintaining their sites on enterprise-grade clouds (e.g., Google, AWS, Azure or IBM), and let's focus on the simple toolset that is offered via SiteGround. </p>



<p>With every request, there are three basic levels of cache (thinking linearly):</p>



<ol><li>Client Caching (AKA Browser Caching)</li><li>Intermediate Caching (AKA CDN or Edge Caching)</li><li>Origin Caching (AKA Backend Caching)</li></ol>



<p>So it looks something like this:</p>



<div class="wp-block-wp-mermaid-block mermaid">








sequenceDiagram
	
participant Client
participant Intermediate
participant Origin

Client->>Client: Check Cache
alt Client IS Cached
    note right of Client: Got Cache&lt;br>Do nothing
else No Client Cache Exists
    Client->>Intermediate: Cache Miss&lt;br>Send Request
    Intermediate->>Intermediate: Check Cache
    alt Intermediate IS Cached
        Intermediate->>Client: Cached Response
    else No Intermediate Cache Exists
        Intermediate->>Origin: Cache Miss&lt;br>To Origin
        Origin->>Origin: Check Cache
        alt Origin IS Cached
            Origin->>Intermediate: Cached Response
        else No Origin Cache Exists
            Origin->>Origin: Process Request
            Origin->>Intermediate: The Response
        end
    end
    Intermediate->>Client: Response
end














</div>



<p><em>Client Caching</em> includes browser cache, local storage, application storage, service workers, web workers, etc. If something is cached here, there is very low latency and nothing leaves the client (e.g., browser, device).</p>



<p><em>Intermediate Caching</em> includes any cache between the client and origin (think WordPress). In our case, this includes Cloudflare CDN. CDNs are generally read/write through caching that can also have look aside caches (which are usually only used at scale). The great thing about intermediate caching, especially CDNs, is that we can always override and ignore origin caching requests.</p>



<p><em>Backend/Origin Caching</em> includes any cache that the backend uses for its services. In our case, this would include memcached, in-memory cache, and MySQL DB cache.</p>



<p>In this flow, the client would be a Chrome Browser on a desktop device or Safari Browser on a mobile device. The intermediate would be Cloudflare CDN and/or Sucuri/Cloudflare WAF. The origin would be NGINX, WordPress, memcached, and MySQL. </p>



<p>With caching, there are decisions made at each point:</p>



<ol><li>Do we want to cache at this location?</li><li>What do we want to cache? </li><li>How long should it be cached?</li></ol>



<p>Caching can be dictated at every stage. At every stage, one can choose to ignore the caching recommendation or request made by the client request or origin response.</p>



<p>Consider this conceptual example: The browser could make a request saying, "Please don't send me anything cached," and the other client caches, intermediate cache, and backend cache would all decide whether to honor that request or not. Likewise, origin could respond saying, "Don't cache this," and the intermediate cache and client caches would decide whether to honor that request or not.</p>



<p>Now for a concrete example: By default, WordPress disables all cache for users who are logged into the site. In other words, every response sent out by WordPress for any user that is logged into the site, origin is saying, "Don't cache this." At Cloudflare, we can choose to ignore this and cache stuff regardless or we can do nothing and let WordPress have its way (even to its own detriment).</p>



<p>So in determining one's caching strategy, you have to determine where, what, and for how long you want to cache. </p>



<h6><strong>Where do we want to cache?</strong></h6>



<p>Where is the best place to cache stuff? Is it at origin? at the network edge (CDN)? or on the client? This somewhat depends on the what we are caching and why we are caching it. Generally speaking, we want to cache at every level. </p>



<p>You have the greatest control over your origin cache as that is your server. As you move closer to the end user, you have less control. CDNs control the shortest amount of time you are able to expire your cache based on your subscription level. Shortest Cache Times (also known as TTL - Time to Live) available by <a aria-label="undefined (opens in a new tab)" href="https://cloudflare.com/" target="_blank" rel="noreferrer noopener nofollow">Cloudflare</a> plans are:</p>



<ul><li>Free Plan: 2 hours</li><li>Pro: 1 hour</li><li>Business: 30 minutes</li><li>Enterprise: 30 seconds</li></ul>



<p>While you are able to set the browser cache, browsers have settings that allow users to ignore that cache, and users can clear their cache at any time. So the client cache is the least dependable cache there is.</p>



<h6><strong>What do we want to cache?</strong></h6>



<p>There are 2 basic types of assets: static and dynamic. Dynamic content can then be broken into three different types: general, segmented, and personalized.</p>



<ul><li><em>Static Assets</em> (e.g., images, JS, CSS, HTML, JSON; think logo, jQuery, theme styles)</li><li><em>Dynamic Assets</em> (e.g., HTML, JSON)<ul><li>General Assets (e.g., HTML, JSON; think feeds, home page)</li><li>Segmented Assets (e.g., HTML; think pages by role, WP Admin)</li><li>Personalized Assets (e.g., HTML; think store cart, checkout page, user profile)</li></ul></li></ul>



<p>Now let's say you have an eCommerce site. <em>By default</em> those users who are logged-in purchasing or even just browsing your site are <em>all</em> bypassing your cache. So if you set to cache your entire site, you are now caching personalized content (e.g., the cart, checkout, invoice, account, etc.). So you have to exempt some pages from the cache, e.g., <code>/cart/</code>, <code>/checkout/</code>, <code>/my-account/*</code>, and <code>/wp-admin/*</code> pages.</p>



<p>To cache the WordPress admin or pages when users are logged into the site or their account, we can use (a.) custom code via <code>nocache_headers</code> and <code>rest_send_nocache_headers</code>, (b.) a setting with WP Rocket (see <em>Caching Plugins</em> above), or (c.) configuration in <a rel="noreferrer noopener" href="https://cloudflare.com/" target="_blank">Cloudflare</a> to cache the admin.</p>



<h6><strong>For how long do we want to cache?</strong></h6>



<p>The length of time of  cache depends on the location of the cache and the location of the asset. In my approach of <code>cacheAllTheThings();</code>, even a short cache time (e.g., 30s or 1min) can help you out tremendously. Normally, you want to cache child items longer than parent items. For example, JS on a HTML page is cached longer than the HTML page itself as the JS asset is a child of the HTML asset. </p>



<p>Let's use a couple way-too-simple examples. As previously explained, we have three levels of cache: origin, edge, and browser. </p>



<h6 class="inline">Increasing Example:</h6>



<ol><li>Origin Cache: 20min</li><li>Edge Cache: 10min</li><li>Browser Cache: 5min</li></ol>



<p>When the browser cache expires (after 5min), it will get the same asset from the edge. When the browser cache expires again (after 10min), it will get the same asset from the origin setting the edge cache. When the browser cache expires again (after 15min), it will get the same asset from the edge, again. When the browser cache expires again (after 20min), it will get a new asset from origin.</p>



<div class="wp-block-wp-mermaid-block mermaid">








sequenceDiagram

participant Client
participant Edge
participant Origin

note over Client, Origin: Client: 5min Cache, Edge: 10min Cache, Origin: 20min Cache

# 1st Request
note over Client: 1st Request @ 7:00
#User->>Client: Request @ 7:00
note over Client: Cache MISS
Client->>Edge: Request @ 7:00
note over Edge: MISS
Edge->>Origin: Request @ 7:00
note over Origin: MISS
Origin->>Client: Origin Fresh Response @ 7:00&lt;br>Asset Cached @ Client, Edge, &amp; Origin

# 2nd Request
note over Client: 2nd Request @ 7:02
#User->>Client: Request @ 7:02
note over Client: HIT
Client->>Client: Client Cached Response @ 7:02

# 3rd Request
note over Client: 3rd Request @ 7:05
#User->>Client: Request @ 7:05
note over Client: MISS
Client->>Edge: Request @ 7:05
note over Edge: HIT
Edge->>Client: Edge Cached Response @ 7:05&lt;br>Asset Cached @ Client

# 4th Request
note over Client: 4th Request @ 7:10
#User->>Client: Request @ 7:10
note over Client: MISS
Client->>Edge: Request @ 7:10
note over Edge: MISS
Edge->>Origin: Request @ 7:10
note over Origin: HIT
Origin->>Client: Origin Cached Response @ 7:10&lt;br>Asset Cached @ Client &amp; Edge

# 6th Request
note over Client: 6th Request @ 7:15
#User->>Client: Request @ 7:15
note over Client: MISS
Client->>Edge: Request @ 7:15
note over Edge: HIT
Edge->>Client: Edge Cached Response @ 7:15&lt;br>Asset Cached @ Client

# 7th Request
note over Client: 7th Request @ 7:20
Client->>Edge: Request @ 7:20
note over Edge: MISS
Edge->>Origin: Request @ 7:20
note over Origin: MISS
Origin->>Client: Origin Fresh Response @ 7:20&lt;br>Asset Cached @ Client, Edge, &amp; Origin









</div>



<h6 class="inline">Decreasing Example:</h6>



<ol><li>Origin Cache: 5min</li><li>Edge Cache: 10min</li><li>Browser Cache: 15min</li></ol>



<p>If we have decreasing length of time as we move to the origin, when the browser cache expires (after 15min), it will get a new asset from the origin immediately bypassing edge cache the first time the edge is hit. If the edge cache is warmed (say by another client), then when the browser cache expires, it will get a new asset from the edge cache.</p>



<div class="wp-block-wp-mermaid-block mermaid">








sequenceDiagram

participant Client
participant Edge
participant Origin

note over Client, Origin: Client: 15min Cache, Edge: 10min Cache, Origin: 5min Cache

# 1st Request
note over Client: 1st Request @ 7:00
note over Client: Cache MISS
Client->>Edge: Request @ 7:00
note over Edge: MISS
Edge->>Origin: Request @ 7:00
note over Origin: MISS
Origin->>Client: Origin Fresh Response @ 7:00&lt;br>Asset Cached @ Client, Edge, &amp; Origin

# 2nd Request
note over Client: 2nd Request @ 7:10
#User->>Client: Request @ 7:10
note over Client: HIT
Client->>Client: Client Cached Response @ 7:10

# 3rd Request
note over Client: 3rd Request @ 7:15
Client->>Edge: Request @ 7:15
note over Edge: MISS
Edge->>Origin: Request @ 7:15
note over Origin: MISS
Origin->>Client: Origin Fresh Response @ 7:15&lt;br>Asset Cached @ Client, Edge, &amp; Origin









</div>



<h6>Pyramid Example</h6>



<ol><li>Origin Cache: 5min</li><li>Edge Cache: 10min</li><li>Browser Cache: 5min</li></ol>



<p>If we have a pyramid length of time, when the browser cache expires (after 5min), it will get the same, cached asset from the edge. When the browser cache expires again (after 10min), it will get a fresh asset from origin immediately.</p>



<div class="wp-block-wp-mermaid-block mermaid">








sequenceDiagram

participant Client
participant Edge
participant Origin

note over Client, Origin: Client: 5min Cache, Edge: 10min Cache, Origin: 5min Cache

# 1st Request
note over Client: 1st Request @ 7:00
note over Client: Cache MISS
Client->>Edge: Request @ 7:00
note over Edge: MISS
Edge->>Origin: Request @ 7:00
note over Origin: MISS
Origin->>Client: Origin Fresh Response @ 7:00&lt;br>Asset Cached @ Client, Edge, &amp; Origin

# 2nd Request
note over Client: 2nd Request @ 7:02
#User->>Client: Request @ 7:02
note over Client: HIT
Client->>Client: Client Cached Response @ 7:02

# 3rd Request
note over Client: 3rd Request @ 7:05
#User->>Client: Request @ 7:05
note over Client: MISS
Client->>Edge: Request @ 7:05
note over Edge: HIT
Edge->>Client: Edge Cached Response @ 7:05&lt;br>Asset Cached @ Client


# 4th Request
note over Client: 4th Request @ 7:10
#User->>Client: Request @ 7:10
note over Client: MISS
Client->>Edge: Request @ 7:10
note over Edge: MISS
Edge->>Origin: Request @ 7:10
note over Origin: MISS
Origin->>Client: Origin Fresh Response @ 7:10&lt;br>Asset Cached @ Client &amp; Edge








</div>



<h6>Help Determining Your Caching Strategy</h6>



<p>Now that was way too much information! Did I confuse you more? Hopefully not. I am more than happy to consult with you on your caching strategy.</p>



<div class="wp-block-buttons aligncenter">
<div class="wp-block-button"><a class="wp-block-button__link" href="/contact/"><strong>Hire Me!</strong></a></div>



<div class="wp-block-button is-style-outline"><a class="wp-block-button__link" href="https://wpsmith.net/hire-a-wordpress-developer/" target="_blank" rel="noopener noreferrer">Hire Me on Codeable</a></div>
</div>



<p>Finally, one key implementation is converting your site to a <a href="https://web.dev/progressive-web-apps/" target="_blank" aria-label="undefined (opens in a new tab)" rel="noreferrer noopener">Progressive Web App</a> (PWA). <a href="https://web.dev/pwa-checklist/" target="_blank" aria-label="undefined (opens in a new tab)" rel="noreferrer noopener">PWAs</a> are websites the deliver an app-like experience, so they must be fast, reliable, engaging and responsive. Why spend the time investing converting your site into a PWA?</p>



<ol><li>PWA's run in the mobile browser.</li><li>Not subject to app store reviews and approval processes.</li><li>Can be launched from the home screen of mobile devices.</li><li>Accessible across all platforms.</li><li>Work offline.</li><li>Increase your visits by 2-4x.</li><li>Increase your conversions by 80%.</li><li>Improve performance and decrease load time by 10-50%.</li><li>Reduce your bounce rate.</li></ol>



<p>All of these and more can be seen by reading the various <a aria-label="undefined (opens in a new tab)" href="https://developers.google.com/web/showcase/2017" target="_blank" rel="noreferrer noopener">Google Case Studies</a>; namely, <a href="https://developers.google.com/web/showcase/2017/bookmyshow" target="_blank" rel="noreferrer noopener">BookMyShow</a>, <a href="https://developers.google.com/web/showcase/2017/bookmyshow" target="_blank" rel="noreferrer noopener">ele.me</a>, <a aria-label="undefined (opens in a new tab)" href="https://developers.google.com/web/showcase/2017/jumia" target="_blank" rel="noreferrer noopener">Jumia</a>, <a aria-label="undefined (opens in a new tab)" href="https://developers.google.com/web/showcase/2017/mynet" target="_blank" rel="noreferrer noopener">Mynet</a>, &amp; <a href="https://developers.google.com/web/showcase/2016/wapo" target="_blank" aria-label="undefined (opens in a new tab)" rel="noreferrer noopener">Washington Post</a>.</p>



<p>The best implementations are always a custom implementation, but you can get mostly there through one of these plugins:</p>



<ul><li><a aria-label="undefined (opens in a new tab)" href="https://wordpress.org/plugins/pwa/" target="_blank" rel="noreferrer noopener">PWA</a></li><li><a aria-label="undefined (opens in a new tab)" href="https://wordpress.org/plugins/pwa-for-wp/" target="_blank" rel="noreferrer noopener">PWA for WP &amp; AMP</a></li><li><a aria-label="undefined (opens in a new tab)" href="https://wordpress.org/plugins/pwa4wp/" target="_blank" rel="noreferrer noopener">PWA4WP</a></li><li><a aria-label="undefined (opens in a new tab)" href="https://wordpress.org/plugins/progressive-wp/" target="_blank" rel="noreferrer noopener">Progressive WordPress</a></li><li><a aria-label="undefined (opens in a new tab)" href="https://wordpress.org/plugins/super-progressive-web-apps/" target="_blank" rel="noreferrer noopener">Super Progressive Web Apps</a></li><li><a aria-label="undefined (opens in a new tab)" href="https://wordpress.org/plugins/add-to-home-screen/" target="_blank" rel="noreferrer noopener">Add to Homescreen</a> + <a aria-label="undefined (opens in a new tab)" href="https://wordpress.org/plugins/offline-shell/" target="_blank" rel="noreferrer noopener">Offline Shell</a> + <a aria-label="undefined (opens in a new tab)" href="https://wordpress.org/plugins/offline-content/" target="_blank" rel="noreferrer noopener">Offline Content</a> + <a aria-label="undefined (opens in a new tab)" href="https://wordpress.org/plugins/web-push/" target="_blank" rel="noreferrer noopener">Web Push</a></li><li>From <strong><em>CodeCanyon</em></strong>:<ul><li><a aria-label="undefined (opens in a new tab)" href="https://wpsmith.net/go/instantify/" target="_blank" rel="noreferrer noopener">Instantify</a></li></ul><ul><li><a aria-label="undefined (opens in a new tab)" href="https://wpsmith.net/go/wordpress-mobile-soft/" target="_blank" rel="noreferrer noopener">WordPress Mobile Soft PWA</a></li><li><a aria-label="undefined (opens in a new tab)" href="https://wpsmith.net/go/pwacommerce/" target="_blank" rel="noreferrer noopener">PWACommerce</a></li><li><a aria-label="undefined (opens in a new tab)" href="https://wpsmith.net/go/progressive-web-app-pwa-push-notifications-for-wordpress-woocommerce/" target="_blank" rel="noreferrer noopener">Progressive Web App (PWA) &amp; Push Notifications for WordPress &amp; WooCommerce</a></li><li><a aria-label="undefined (opens in a new tab)" href="https://wpsmith.net/go/simple-pwa/" target="_blank" rel="noreferrer noopener">Simple PWA</a></li><li><a aria-label="undefined (opens in a new tab)" href="https://wpsmith.net/go/pwa-for-woocommerce/" target="_blank" rel="noreferrer noopener">PWA for WooCommerce</a></li><li><a aria-label="undefined (opens in a new tab)" href="https://wpsmith.net/go/progressive-web-apps-for-wordpress/" target="_blank" rel="noreferrer noopener">Progressive Web Apps For WordPress</a></li></ul></li></ul>



<h3 id="summary">Summary</h3>



<p>Sounds <em>like a lot</em>, but by doing all of these things, you now have a server that is truly serving your end customers. More than likely you won't want to do every little thing I recommend, but doing even a subset of these will improve your server's performance. There is no guarantee that doing only a subset of these will remove all 5XX errors from your site, but doing all of them will eradicate nearly 99% of those errors leaving only the errors that are truly a result of insufficient scale.</p>



<p>If you read this <em>entire</em> article, kudos! I really commend you as even writing this, I didn't want to read this entire article.</p>



<div class="wp-block-buttons aligncenter">
<div class="wp-block-button"><a class="wp-block-button__link" href="/contact/"><strong>Hire Me!</strong></a></div>



<div class="wp-block-button is-style-outline"><a class="wp-block-button__link" href="https://wpsmith.net/hire-a-wordpress-developer/" target="_blank" rel="noopener noreferrer">Hire Me on Codeable</a></div>
</div>



<p>For your convenience, here is the outline of the entire article:</p>



<ol><li><a href="https://wpsmith.net/wp-admin/post.php?post=70074&amp;action=edit#understanding-500-errors">Understanding 500 Errors</a></li><li><a href="https://wpsmith.net/wp-admin/post.php?post=70074&amp;action=edit#solving-500-errors">Solving 500 Errors</a></li><li><a href="https://wpsmith.net/wp-admin/post.php?post=70074&amp;action=edit#understanding-499-502-503-504-errors">Understanding 499, 502, 503, &amp; 504 Errors</a></li><li><a href="https://wpsmith.net/wp-admin/post.php?post=70074&amp;action=edit#web-architecture">Understanding the Web Hosting Architecture</a></li><li><a href="https://wpsmith.net/wp-admin/post.php?post=70074&amp;action=edit#support-expectations-for-5xx-errors">What to Expect from Managed Hosting Support</a></li><li><a href="https://wpsmith.net/wp-admin/post.php?post=70074&amp;action=edit#solving-499-502-503-504-errors">15 Ways of Solving 499, 502, 503, &amp; 504 Errors</a><ol><li><a href="https://wpsmith.net/wp-admin/post.php?post=70074&amp;action=edit#analyze-logs">Analyze the Logs for 499s, 500s, 502s, 503s, &amp; 504s</a></li><li><a href="https://wpsmith.net/wp-admin/post.php?post=70074&amp;action=edit#check-php-version">Check PHP Version</a></li><li><a href="https://wpsmith.net/wp-admin/post.php?post=70074&amp;action=edit#wp-doctor">Run WP CLI’s Doctor Command</a></li><li><a href="https://wpsmith.net/wp-admin/post.php?post=70074&amp;action=edit#cdn">Properly Configure a CDN</a></li><li><a href="https://wpsmith.net/wp-admin/post.php?post=70074&amp;action=edit#xmlrpc">Disable XMLRPC</a></li><li><a href="https://wpsmith.net/wp-admin/post.php?post=70074&amp;action=edit#bots">Control Bots</a></li><li><a href="https://wpsmith.net/wp-admin/post.php?post=70074&amp;action=edit#ram-cpu">Check Memory &amp; Compute Utilization</a></li><li><a href="https://wpsmith.net/wp-admin/post.php?post=70074&amp;action=edit#cron-jobs">Configure Proper Cron Jobs</a></li><li><a href="https://wpsmith.net/wp-admin/post.php?post=70074&amp;action=edit#plugins">Use Optimized Plugins</a></li><li><a href="https://wpsmith.net/wp-admin/post.php?post=70074&amp;action=edit#optimize-db">Optimize the Database</a></li><li><a href="https://wpsmith.net/wp-admin/post.php?post=70074&amp;action=edit#offload-emails">Offload All Emails</a></li><li><a href="https://wpsmith.net/wp-admin/post.php?post=70074&amp;action=edit#limit-ajax">Limit AJAX Usage</a></li><li><a href="https://wpsmith.net/wp-admin/post.php?post=70074&amp;action=edit#offload-images">Offload Images/Assets</a></li><li><a href="https://wpsmith.net/wp-admin/post.php?post=70074&amp;action=edit#analyze-wp-actions">Analyze WP Actions &amp; Filters</a></li><li><a href="https://wpsmith.net/wp-admin/post.php?post=70074&amp;action=edit#cache-strategy">Determine Cache Strategy</a></li></ol></li><li><a href="https://wpsmith.net/wp-admin/post.php?post=70074&amp;action=edit#summary">Summary</a></li></ol>



<p></p>
<p>The post <a rel="nofollow" href="https://wpsmith.net/2020/solving-wordpress-500-502-503-504-5xx-errors-on-siteground-and-other-hosts/">Solving WordPress 5XX Server Errors on SiteGround</a> appeared first on <a rel="nofollow" href="https://wpsmith.net">WP Smith</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://wpsmith.net/2020/solving-wordpress-500-502-503-504-5xx-errors-on-siteground-and-other-hosts/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Hiding an User in the WordPress Admin</title>
		<link>https://wpsmith.net/2019/hiding-an-user-in-the-wordpress-admin/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=hiding-an-user-in-the-wordpress-admin</link>
					<comments>https://wpsmith.net/2019/hiding-an-user-in-the-wordpress-admin/#respond</comments>
		
		<dc:creator><![CDATA[Travis Smith]]></dc:creator>
		<pubDate>Wed, 09 Jan 2019 13:00:06 +0000</pubDate>
				<category><![CDATA[Snippets]]></category>
		<guid isPermaLink="false">https://wpsmith.net/?p=70001</guid>

					<description><![CDATA[<p>Sometimes it is good to hide a user from other users so that user won't be deleted or modified accidentally by another administrator. This especially good for hiding the hosting user or any machine/automation user. Setup So let's setup a plugin main file. Within wp-content/mu-plugins, add a file, hide-user.php. Now that we are setup, we can [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://wpsmith.net/2019/hiding-an-user-in-the-wordpress-admin/">Hiding an User in the WordPress Admin</a> appeared first on <a rel="nofollow" href="https://wpsmith.net">WP Smith</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Sometimes it is good to hide a user from other users so that user won't be deleted or modified accidentally by another administrator. This especially good for hiding the hosting user or any machine/automation user.</p>
<h3>Setup</h3>
<p>So let's setup a plugin main file. Within <code>wp-content/mu-plugins</code>, add a file, <code>hide-user.php</code>.<br />
<a href="https://gist.github.com/c19b5107a4e3381b6e9e756cb5aca60f" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<p>Now that we are setup, we can hide the user one of two ways:</p>
<ol>
<li>Using Composer in a Single File</li>
<li>Putting All Code in a Single File</li>
</ol>
<h3>Mu-Plugin Using Composer</h3>
<p>Create a <code>composer.json</code> file where we can require my user package (<a href="https://packagist.org/packages/wpsmith/user" target="_blank" rel="noopener"><code>wpsmith/user</code></a>) via <a href="http://getcomposer.org" target="_blank" rel="noopener">composer</a>.<br />
<a href="https://gist.github.com/c19b5107a4e3381b6e9e756cb5aca60f" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<p>Once we have this file, we can do a <code>composer install</code> which will install our packages into a folder called <code>vendor</code> automagically.</p>
<p>In the plugin file (<code>hide-user.php</code>), we need to require the composer autoloader.<br />
<a href="https://gist.github.com/c19b5107a4e3381b6e9e756cb5aca60f" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<p>Finally, we add the simple code to hide the user(s):<br />
<a href="https://gist.github.com/c19b5107a4e3381b6e9e756cb5aca60f" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<h3>Mu-Plugin with All Code</h3>
<p>In the plugin file (<code>hide-user.php</code>), we need to add a hook into the <code>pre_user_query</code>.</p>
<p><a href="https://gist.github.com/c19b5107a4e3381b6e9e756cb5aca60f" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<p>&nbsp;</p>
<p><small>Credits: Image From <a href="https://www.flickr.com/photos/kalexanderson/7704409698" target="_blank" rel="noopener nofollow">Kristina Alexanderson</a>.</small></p>
<p>The post <a rel="nofollow" href="https://wpsmith.net/2019/hiding-an-user-in-the-wordpress-admin/">Hiding an User in the WordPress Admin</a> appeared first on <a rel="nofollow" href="https://wpsmith.net">WP Smith</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://wpsmith.net/2019/hiding-an-user-in-the-wordpress-admin/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Custom Rewrite Rules for Custom Post Types and Taxonomies</title>
		<link>https://wpsmith.net/2019/custom-rewrite-rules-custom-post-types-taxonomies/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=custom-rewrite-rules-custom-post-types-taxonomies</link>
					<comments>https://wpsmith.net/2019/custom-rewrite-rules-custom-post-types-taxonomies/#comments</comments>
		
		<dc:creator><![CDATA[Travis Smith]]></dc:creator>
		<pubDate>Sat, 05 Jan 2019 20:31:18 +0000</pubDate>
				<category><![CDATA[Tutorials]]></category>
		<guid isPermaLink="false">https://wpsmith.net/?p=69996</guid>

					<description><![CDATA[<p>Getting custom URL structures that differ from standard WordPress convention can be tough, even confusing. When you register a custom post type, you get these URLs: Singular Page: https://domain.com/cpt-slug/post-name-slug/ Paginated Singular Pages: https://domain.com/cpt-slug/post-name-slug/2/ Archive Page: https://domain.com/cpt-archive-slug/ Paginated Archive Pages: https://domain.com/cpt-slug/post-name-slug/page/2/ Trackback Page: https://domain.com/cpt-slug/post-name-slug/trackback/ Feed Pages: https://domain.com/cpt-slug/post-name-slug/feed/rss/, https://domain.com/cpt-slug/post-name-slug/rss/ Comment Page: https://domain.com/cpt-slug/post-name-slug/comment-page/ Embed Page: https://domain.com/cpt-slug/post-name-slug/embed/ Attachment: Attachment [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://wpsmith.net/2019/custom-rewrite-rules-custom-post-types-taxonomies/">Custom Rewrite Rules for Custom Post Types and Taxonomies</a> appeared first on <a rel="nofollow" href="https://wpsmith.net">WP Smith</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Getting custom URL structures that differ from standard WordPress convention can be tough, even confusing.</p>
<p>When you register a custom post type, you get these URLs:</p>
<ul>
<li>Singular Page: <code>https://domain.com/cpt-slug/post-name-slug/</code></li>
<li>Paginated Singular Pages: <code>https://domain.com/cpt-slug/post-name-slug/2/</code></li>
<li>Archive Page: <code>https://domain.com/cpt-archive-slug/</code></li>
<li>Paginated Archive Pages: <code>https://domain.com/cpt-slug/post-name-slug/page/2/</code></li>
<li>Trackback Page: <code>https://domain.com/cpt-slug/post-name-slug/trackback/</code></li>
<li>Feed Pages: <code>https://domain.com/cpt-slug/post-name-slug/feed/rss/</code>, <code>https://domain.com/cpt-slug/post-name-slug/rss/</code></li>
<li>Comment Page: <code>https://domain.com/cpt-slug/post-name-slug/comment-page/</code></li>
<li>Embed Page: <code>https://domain.com/cpt-slug/post-name-slug/embed/</code></li>
<li>Attachment:
<ul>
<li>Attachment Page: <code>https://domain.com/cpt-slug/post-name-slug/attachment/my-attachment-slug/</code></li>
<li>Attachment Trackback Page: <code>https://domain.com/cpt-slug/post-name-slug/attachment/my-attachment-slug/trackback/</code></li>
<li>Attachment Feed Pages: <code>https://domain.com/cpt-slug/post-name-slug/attachment/my-attachment-slug/feed/rss/</code> , <code>https://domain.com/cpt-slug/post-name-slug/attachment/my-attachment-slug/rss/</code></li>
<li>Attachment Comment Page: <code>https://domain.com/cpt-slug/post-name-slug/attachment/my-attachment-slug/comment-page/</code></li>
<li>Attachment Embed Page: <code>https://domain.com/cpt-slug/post-name-slug/attachment/my-attachment-slug/embed/</code></li>
</ul>
</li>
</ul>
<p>When you register a custom taxonomy, you get these URLs:</p>
<ul>
<li>Term Archive Page: <code>https://domain.com/custom-taxonomy-slug/term-slug/</code></li>
<li>Paginated Archive Pages: <code>https://domain.com/custom-taxonomy-slug/term-slug/page/2/</code></li>
<li>Embed Page: <code>https://domain.com/custom-taxonomy-slug/term-name-slug/embed/</code></li>
<li>Feed Pages: <code>https://domain.com/custom-taxonomy-slug/term-name-slug/feed/rss/</code>, <code>https://domain.com/tax-slug/term-name-slug/rss/</code></li>
</ul>
<p>So, if you want anything else, you need to do something custom. For example, if you want date archive pages with your custom post type or if you want to introduce a taxonomy term in the URL, you must add some custom code.</p>
<h3>Setup</h3>
<p>So let's setup a plugin main file. First create a folder called <code>post-type-taxonomy-rewrite</code>.<br />
<a href="https://gist.github.com/5382866b8d0ff3a19d0e05557ceb090b" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<p>Create a <code>composer.json</code> file where we can require my rewrite package (<a href="https://packagist.org/packages/wpsmith/rewrite" target="_blank" rel="noopener"><code>wpsmith/rewrite</code></a>) via <a href="http://getcomposer.org" target="_blank" rel="noopener">composer</a>.<br />
<a href="https://gist.github.com/5382866b8d0ff3a19d0e05557ceb090b" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<p>Once we have this file, we can do a <code>composer install</code> which will install our packages into a folder called <code>vendor</code>.</p>
<p>Now in the plugin file (<code>post-type-taxonomy-rewrite.php</code>), we need to require the composer autoloader.<br />
<a href="https://gist.github.com/5382866b8d0ff3a19d0e05557ceb090b" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<p>So now we should have this:</p>
<pre>post-type-taxonomy-rewrite/
|- composer.json
|- post-type-taxonomy-rewrite.php
|- vendor/</pre>
<h3>Custom Post Type / Taxonomy Example</h3>
<p>For example, let's say we want this pattern(<code>domain.com/{post-type-slug}/{term}/{postname}</code>):</p>
<ul>
<li>Single Custom Post Type Post: <code>https://domain.com/resource/tutorials/setting-up-something</code></li>
<li>Custom Taxonomy Archive: <code>https://domain.com/resource/tutorials/</code></li>
<li>Custom Post Type Archive: <code>https://domain.com/resource/</code></li>
</ul>
<p>Now, I have written a class that you can use to make this extremely easy!</p>
<h4>Setup</h4>
<p>Now, create a <code>resources.php</code> file to contain our post type and taxonomy registration code for <code>resource</code> and <code>resource-type</code>.<br />
<a href="https://gist.github.com/5382866b8d0ff3a19d0e05557ceb090b" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<p>So now we should have this:</p>
<pre>post-type-taxonomy-rewrite/
|- composer.json
|- post-type-taxonomy-rewrite.php
|- resources.php
|- vendor/
</pre>
<h4>Doing the Rewrites</h4>
<p>Then let's create a function:<br />
<a href="https://gist.github.com/5382866b8d0ff3a19d0e05557ceb090b" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<p>That's it!</p>
<h4>On Activation</h4>
<p>Because this is a plugin, we need to flush the rewrite rules when the plugin is activated. So in the plugin file (<code>post-type-taxonomy-rewrite.php</code>), let's flush the rules.<br />
<a href="https://gist.github.com/5382866b8d0ff3a19d0e05557ceb090b" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<h3>Taxonomy / Custom Post Type Example</h3>
<p>What if you have a hierarchical post type that you wanted to use with this pattern (<code>domain.com/{term}/{post-type-slug}/{postname}</code>):</p>
<ul>
<li>Single Parent Custom Post Type Post: <code>https://domain.com/email/landing-page/selling-something</code></li>
<li>Single Child Custom Post Type Post: <code>https://domain.com/email/landing-page/selling-parent/selling-something</code></li>
<li>Custom Taxonomy Archive: <code>https://domain.com/email/</code></li>
</ul>
<h4>Setup</h4>
<p>Now, create a <code>landing-pages.php</code> file to contain our post type and taxonomy registration code for <code>landing_page</code> and <code>campaign_type</code> (this replaces <code>resources.php</code>).<br />
<a href="https://gist.github.com/5382866b8d0ff3a19d0e05557ceb090b" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<p>So now we should have this:</p>
<pre>post-type-taxonomy-rewrite/
|- composer.json
|- post-type-taxonomy-rewrite.php
|- landing-pages.php
|- vendor/</pre>
<p>With Landing Pages, I added an additional class <code>SingleTermTaxonomy</code> to ensure that the taxonomy, <code>campaign_type</code> would always have only one term selected. In order to use this additional class, <code>composer.json</code> needs to be updated.</p>
<p><a href="https://gist.github.com/5382866b8d0ff3a19d0e05557ceb090b" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<p><code>SingleTermTaxonomy</code> is not required, and if you do not wish to use this class, then simply delete lines 88-89.</p>
<p><a href="https://gist.github.com/5382866b8d0ff3a19d0e05557ceb090b" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<h4>Doing the Rewrites</h4>
<p>Then let's create a function:<br />
<a href="https://gist.github.com/5382866b8d0ff3a19d0e05557ceb090b" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<p>That's it!</p>
<h4>On Activation</h4>
<p>Because this is a plugin, we need to flush the rewrite rules when the plugin is activated. So in the plugin file (<code>post-type-taxonomy-rewrite.php</code>), let's flush the rules.<br />
<a href="https://gist.github.com/5382866b8d0ff3a19d0e05557ceb090b" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<h3>Prefix / Custom Post Type Example</h3>
<p>What if you have a post type that you wanted to add a prefix slug, the date archives, and so use with this pattern (<code>domain.com/{prefix}/{post-type-slug}/{postname}</code>):</p>
<ul>
<li>Single Custom Post Type Post: <code>https://domain.com/video/some-music-video</code></li>
<li>Date Archives: <code>https://domain.com/video/2019</code>, <code>https://domain.com/video/2019/01</code>, and <code>https://domain.com/video/2019/01/05</code></li>
<li>Custom Post Type Archive: <code>https://domain.com/videos/</code></li>
</ul>
<h4>Setup</h4>
<p>Now, create a <code>videos.php</code> file to contain our post type and taxonomy registration code for <code>video</code> (this replaces <code>resources.php</code> or <code>landing-pages.php</code>).<br />
<a href="https://gist.github.com/5382866b8d0ff3a19d0e05557ceb090b" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<p>So now we should have this:</p>
<pre>post-type-taxonomy-rewrite/
|- composer.json
|- post-type-taxonomy-rewrite.php
|- videos.php
|- vendor/</pre>
<h4>Doing the Rewrites</h4>
<p>Then let's create a function:<br />
<a href="https://gist.github.com/5382866b8d0ff3a19d0e05557ceb090b" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<p>That's it!</p>
<h4>On Activation</h4>
<p>Because this is a plugin, we need to flush the rewrite rules when the plugin is activated. So in the plugin file (<code>post-type-taxonomy-rewrite.php</code>), let's flush the rules.<br />
<a href="https://gist.github.com/5382866b8d0ff3a19d0e05557ceb090b" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<h3>Wrap-Up</h3>
<p>If this was helpful, you can find all the code either in the <a href="https://gist.github.com/wpsmith/5382866b8d0ff3a19d0e05557ceb090b" target="_blank" rel="noopener">gist</a> or the <a href="https://github.com/wpsmith/post-type-taxonomy-rewrite" target="_blank" rel="noopener">Github</a> repo (https://github.com/wpsmith/post-type-taxonomy-rewrite). Please feel free to let me know if there is anything I missed!</p>
<p>The post <a rel="nofollow" href="https://wpsmith.net/2019/custom-rewrite-rules-custom-post-types-taxonomies/">Custom Rewrite Rules for Custom Post Types and Taxonomies</a> appeared first on <a rel="nofollow" href="https://wpsmith.net">WP Smith</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://wpsmith.net/2019/custom-rewrite-rules-custom-post-types-taxonomies/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>WordPress JavaScript Manager Native Functions</title>
		<link>https://wpsmith.net/2018/wordpress-javascript-manager-native-functions/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=wordpress-javascript-manager-native-functions</link>
					<comments>https://wpsmith.net/2018/wordpress-javascript-manager-native-functions/#respond</comments>
		
		<dc:creator><![CDATA[Travis Smith]]></dc:creator>
		<pubDate>Thu, 21 Jun 2018 12:00:43 +0000</pubDate>
				<category><![CDATA[Tutorials]]></category>
		<guid isPermaLink="false">https://wpsmith.net/?p=69983</guid>

					<description><![CDATA[<p>WordPress has native PHP JavaScript management functions. Using these functions are better than manually adding &#60;script&#62; tags in the &#60;head&#62; or footer of the page. In this article, we will discuss: PHP Constants for Debugging JavaScript Registering and Deregistering Scripts Enqueueing and Dequeueing Scripts Localizing Scripts Initializing Scripts Modifying Script Tags on Print PHP Constants [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://wpsmith.net/2018/wordpress-javascript-manager-native-functions/">WordPress JavaScript Manager Native Functions</a> appeared first on <a rel="nofollow" href="https://wpsmith.net">WP Smith</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>WordPress has native PHP JavaScript management functions. Using these functions are better than manually adding <code>&lt;script&gt;</code> tags in the <code>&lt;head&gt;</code> or footer of the page. In this article, we will discuss:</p>
<ol>
<li><a href="#constants">PHP Constants for Debugging JavaScript</a></li>
<li><a href="#registering">Registering and Deregistering Scripts</a></li>
<li><a href="#enqueueing">Enqueueing and Dequeueing Scripts</a></li>
<li><a href="#localizing">Localizing Scripts</a></li>
<li><a href="#initializing">Initializing Scripts</a></li>
<li><a href="#modifying">Modifying Script Tags on Print</a></li>
</ol>
<p><img loading="lazy" src="https://wpsmith.net/wp-content/uploads/2018/06/wordpress-js-1024x576.jpg" alt="JavaScript in WordPress" width="1024" height="576" class="aligncenter size-large wp-image-69984" srcset="https://wpsmith.net/wp-content/uploads/2018/06/wordpress-js-1024x576.jpg 1024w, https://wpsmith.net/wp-content/uploads/2018/06/wordpress-js-300x169.jpg 300w, https://wpsmith.net/wp-content/uploads/2018/06/wordpress-js-768x432.jpg 768w, https://wpsmith.net/wp-content/uploads/2018/06/wordpress-js.jpg 1600w" sizes="(max-width: 1024px) 100vw, 1024px" /></p>
<h3 name="constants">PHP Constants for Debugging JavaScript</h3>
<p>Most WordPress developers are familiar with <code>WP_DEBUG</code> and know how to use that to debug WordPress. <code>WP_DEBUG</code> is designed as a global for turning debugging on and off, but <code>WP_DEBUG</code> has no affect on JavaScript files. Fewer developers know about <code>SCRIPT_DEBUG</code>. While <code>WP_DEBUG</code> helps debug the PHP code, <code>SCRIPT_DEBUG</code> helps with JavaScript. <code>SCRIPT_DEBUG</code> will output the normal, non-minified version of the JavaScript files. For example, with <code>SCRIPT_DEBUG</code> will output <code>wp-embed.js</code> while normally WordPress will output <code>wp-embed.min.js</code>. You can use this constant to output minified and non-minified your plugin/theme JavaScript files dynamically. For example:</p>
<p><a href="https://gist.github.com/6e676ff6c5516427bb04aac361cacf00" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<p>Alternatively, you could use a function that will do this for you:</p>
<p><a href="https://gist.github.com/6e676ff6c5516427bb04aac361cacf00" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<p>Or, you can use a constant or multiple constants:<br />
<a href="https://gist.github.com/6e676ff6c5516427bb04aac361cacf00" target="_blank"><em>View this code snippet on GitHub.</em></a>]</p>
<p>Or (just for fun) create a function for the suffix only:<br />
<a href="https://gist.github.com/6e676ff6c5516427bb04aac361cacf00" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<p>If <code>SCRIPT_DEBUG</code> is on, the filename will be <code>my-js-file.js</code> while if <code>SCRIPT_DEBUG</code> is false, the filename will be <code>my-js-file.min.js</code>. So if you have a Gulp/Grunt script or a PHPStorm File Watcher auto-minifying your JavaScript, WordPress will properly output the correct JavaScript file.</p>
<h3 name="registering">Registering and Deregistering Scripts</h3>
<p>Why register your scripts?</p>
<ol>
<li><em>DRY</em>: The script manager allows you to re-use and output the script in various places of your code.</li>
<li><em>Integrations</em>: The script manager allows for anyone to integrate, optimize, and build upon your script.</li>
<li><em>Prevents Duplication</em>: A script using the script manager will only be printed on the page once.</li>
<li><em>Client Focused</em> & <em>Client Friendly</em>: It allows your customers/clients to remove the scripts easily.</li>
</ol>
<h4>DRY</h4>
<p>The first reason (and one which I agree) is perfect for coders who subscribe to DRY (Don't Repeat Yourself) coding, which most of us prefer. It optimizes your code and makes your code clean and readable. <a href="https://developer.wordpress.org/reference/functions/wp_register_script/#core-registered-scripts" rel="noopener" target="_blank">WordPress Core</a> registers a ton of JavaScript files. Most notable of these are:</p>
<ul>
<li><code>jquery</code> (core and other parts&mdash;<code>jquery-ui</code>, <code>jquery-effects</code>)</li>
<li><code>thickbox</code></li>
<li><code>underscrore</code></li>
<li><code>backbone</code></li>
<li><code>media-element</code></li>
</ul>
<p>If you are using any of these, please use the WordPress core version. It ensures the best experience.</p>
<h4>Client Focused & Client Friendly</h4>
<p>Many developers do not like the second reason. They want to control every aspect of their code because they are afraid that their client/customer or another developer will break their plugin. However, to me, this is not a good reason. If a customer/client breaks the plugin/site because they chose to copy/paste code and place it in their <code>functions.php</code> site, it is their fault, and they can pay you to fix it. But by providing the client/customer code that is changeable, it makes you look like a better developer, and you will have return customers/clients because they can trust that you have their best interests in mind.</p>
<h4>Integrations & Prevents Duplication</h4>
<p>Plugins like WP Rocket and other optimization plugins can detect and handled registered scripts much easier than functions that echo <code>script</code> elements at random places throughout the document. WordPress filters, like <code>script_loader_src</code> and <code>script_loader_tag</code>, can be used to amend <em>how</em> one or more registered scripts are loaded in the DOM by amending the tag attributes (see below for the advanced examples), and finally other scripts can use those scripts as dependencies themselves.</p>
<p>By using a script manager, WordPress tries to prevent duplication of scripts. For example, if one plugin outputs <code>underscore</code> via a <code>script</code> tag and the other developer uses WordPress's version, then multiple <code>underscore</code> scripts will be printed on the page, which obviously will lead to problems.</p>
<h4>The Code: Registering/Deregistering Scripts</h4>
<p>There is a function for registering a JavaScript file (<code>wp_register_script</code>) and one for deregistering a JavaScript file (<code>wp_deregister_script</code>). Now, many developers, and even those on <a href="https://developer.wordpress.org/reference/functions/wp_register_script/#user-contributed-notes" rel="noopener" target="_blank">developers.wordpress.org</a>, recommend that you register scripts within the <code>wp_enqueue_scripts</code> hook. However, it is my opinion that you should always register scripts on <code>init</code> (for frontend scripts wrapped with <code>! is_admin()</code> conditional) and <code>admin_init</code> (for admin scripts) hooks. For the purposes of this article, we will be focusing all of the examples to frontend JavaScript, so we won't be using the <code>admin_init</code> hook. This allows your customers/clients to manipulate the scripts however <em>they need, if they need</em>.</p>
<h5>Registering JavaScript Files</h5>
<p><code>wp_register_script($handle, $src, $deps, $ver, $in_footer)</code> takes a couple parameters which are obvious: <code>$handle</code> (slug) <code>$src</code> (the script URL), <code>$in_footer</code> (whether to output in the <code>head</code> or footer). It is always recommended that <code>$in_footer</code> be <code>true</code> unless (1) there is a very specific reason for the script to be in the <code>head</code> (other than "my code doesn't work in the footer") or (2) you use <code>defer</code>. Two really good examples are Google Analytics and New Relic&mdash;both require to be run in the <code>head</code> at the top. IMHO Google Analytics should have the <code>async</code> attribute added to it. The two remaining parameters&mdash;dependencies (<code>$deps</code>) and version (<code>$ver</code>) are more fascinating.</p>
<h6><em>Script Version (</em><code>$ver</code><em>)</em></h6>
<p>Most people use a simple version number to identify the version (e.g., 0.0.1 or 2.1). In fact, most developers are either ignorant or lazy and only use the version of the theme or plugin via a constant or something hardcoded that never seems to change. So if you are doing development with an aggressively caching browser it becomes problematic and frustrating to ensure that your changes are being reflected in the DOM, even with <a href="https://browsersync.io/docs/gulp" rel="noopener" target="_blank">browsersync</a> or <a href="https://www.npmjs.com/package/gulp-livereload" rel="noopener" target="_blank">gulp-livereload</a>. However, the <em><strong>best option</strong></em> is to do <em>both</em> the version of the plugin and the file version. If you are like me, changing the version of the file every time in the JavaScript file and the correlating PHP file is such a hassle. Being a stickler on this yet also lazy about versioning myself, I need something simple that would be cacheable and yet also cache bust when needed (on update/change). My goal is to load the JavaScript file via WordPress and forget about that part and work on the JavaScript file only. So, I use <code>filemtime</code> for file versioning within my PHP and maintain semantic versioning within the JavaScript file properly. <code>filemtime</code> helps me accomplish this. It returns the epoch time (e.g., <code>1529330834</code>) of when the file was written/changed. So as long as the file does not change or update, the file will be cached.</p>
<p>So here is how I do versioning for my scripts:</p>
<p><a href="https://gist.github.com/6e676ff6c5516427bb04aac361cacf00" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<p>The resulting filename will be something like <code>myscript.js?ver=1.0.0-1528229721</code>. This will make it easy to identify the version of the plugin while also ensuring that the correct version of the script is on the frontend. Even WordPress.com does something similar outputting files with the version of the file and a date (e.g., <code>https://s1.wp.com/wp-content/js/mustache.js?ver=6.1.1-201824</code>).</p>
<h6><em>Script Dependencies (</em><code>$deps</code><em>)</em></h6>
<p>Finally, <code>$deps</code> are really cool because when I output the file, WordPress will also output all the dependencies without me having to do it...but more on that in the next section.</p>
<h6><em>Registering Scripts in Themes</em></h6>
<p><strong>For themes</strong>, you register files like this (using the previous best practice with the dynamic suffix):<br />
<a href="https://gist.github.com/6e676ff6c5516427bb04aac361cacf00" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<p>Alternatively, you could use a theme script register helper:<br />
<a href="https://gist.github.com/6e676ff6c5516427bb04aac361cacf00" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<h6><em>Registering Scripts in Plugins</em></h6>
<p><strong>For plugins</strong>, you register files like this (using the previous best practice with the dynamic suffix):<br />
<a href="https://gist.github.com/6e676ff6c5516427bb04aac361cacf00" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<p>Alternatively, you could use a plugin script register helper:<br />
<a href="https://gist.github.com/6e676ff6c5516427bb04aac361cacf00" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<h5>Deregistering JavaScript Files</h5>
<p>Deregistering is extremely straight forward as you can see here:<br />
<a href="https://gist.github.com/6e676ff6c5516427bb04aac361cacf00" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<p>However, actually deregistering a script can be quite tricky. The main problem with deregistering scripts is deregistering <em>AFTER</em> it has been registered. For plugins, this is why registering a script and enqueueing (or just enqueueing) a script in the same function (without a <code>do_action</code> between them) is an unfriendly and bad idea.</p>
<p>For example, here are three <em>bad</em> ways to do it:<br />
<a href="https://gist.github.com/6e676ff6c5516427bb04aac361cacf00" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<p><a href="https://gist.github.com/6e676ff6c5516427bb04aac361cacf00" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<p><a href="https://gist.github.com/6e676ff6c5516427bb04aac361cacf00" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<p>This last one looks that most right but the problem is that they both are hooked at the same priority and there is no way to hook in between the functions to do anything.</p>
<p>Here is a <em>better</em> way:<br />
<a href="https://gist.github.com/6e676ff6c5516427bb04aac361cacf00" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<p>This way, I can hook in between the functions within <code>wp_enqueue_scripts</code> hook to make any changes necessary.</p>
<p>Here is the <em>best</em> way (IMHO):<br />
<a href="https://gist.github.com/6e676ff6c5516427bb04aac361cacf00" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<p>So when do you deregister a script? You deregister a script for two primary reasons:</p>
<ol>
<li>If you want to re-register the script with different arguments (primarily <code>$src</code> URL).</li>
<li>If you want to ensure the script never gets placed on the frontend period.</li>
</ol>
<p><strong>Warning</strong>: Whenever you deregister a script (e.g., myscript) without re-registering a new version of that script, any script dependent upon that script (e.g., myscript) will not output either.</p>
<p>So, consider this example. In <code>wp-config.php</code>, we have <code>define( 'SCRIPT_DEBUG', true );</code>. Now, let's say we have this in an active plugin:<br />
<a href="https://gist.github.com/6e676ff6c5516427bb04aac361cacf00" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<p>With a single statement, our use of the active plugin outputs three files on the frontend in this order:</p>
<ul>
<li><code>js/plugin-script-base.js</code></li>
<li><code>js/plugin-script.js</code></li>
<li><code>js/plugin-script-ext.js</code></li>
</ul>
<p>Now in our theme, say we have this in the <code>functions.php</code> file:<br />
<a href="https://gist.github.com/6e676ff6c5516427bb04aac361cacf00" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<p>This function within <code>functions.php</code> will cause <code>plugin-script</code> and <code>plugin-script-ext</code> <strong>NOT</strong> to be placed on the frontend either because the WordPress script manager assumes that since <code>plugin-script</code> and <code>plugin-script-ext</code> are dependent upon <code>plugin-script-base</code>, they also won't work if <code>plugin-script-base</code> is missing. So WordPress will not output those files.</p>
<h4>A Note</h4>
<p>Many seasoned non-WordPress PHP developers will want to use their own version of jQuery. So they will deregister WordPress's jQuery and register their own. This may be a great idea <em>for your own project</em> <strong>ONLY</strong> that you will always control, but it is a terrible idea for any free/premium plugins and/or themes. Here's why:</p>
<ul>
<li>Other themes/plugins depend on the same version of that script WordPress provides, so you may break the theme or plugins accidentally. So if you deregister it and register your own (even if the same version), when WordPress upgrades that script (i.e., jQuery), it could break everything. Alternatively, if you deregister jQuery (for example) and register another specific version (older or newer), then you may break current plugins.</li>
<li>WordPress may upgrade that script for security reasons and now you have opened a security hole. This will cause a massive amount of support requests if you sell a premium theme/plugin and cause harm to your brand/reputation. Or, you may not even be around to fix the problem for your client.</li>
</ul>
<p>This is not client/customer friendly at all. As a developer, we need to get over our own opinions that using a CDN version or a specific version of a script is better and accept this part of WordPress and the WordPress ecosystem. Simply, play nice!</p>
<h3 name="enqueueing">Enqueueing and Dequeueing Scripts</h3>
<p>So far, we have only properly registered (or deregistered) the scripts within WordPress but that does not output the script tags on the frontend. To output the scripts on the frontend, you need to queue the script to be outputted by the WordPress script manager. To do this, you will need to use <code>wp_enqueue_script</code>.</p>
<p><code>wp_enqueue_script</code> does two things:</p>
<ol>
<li>Registers the script if it has not been registered already.</li>
<li>Outputs any files on the frontend during the <code>wp_head</code> hook via <code>print_head_scripts</code> (which calls <code>wp_print_scripts</code> hook) and <code>wp_footer</code> hook via <code>_wp_footer_scripts</code> which calls <code>print_late_styles()</code> and <code>print_footer_scripts()</code>.</li>
</ol>
<p>Sometimes, however, plugins and themes will just enqueue all their scripts even if the page doesn't use that particular script. They do this mostly because they provide their functionality through a shortcode and don't know how to properly test the page to determine whether that shortcode exists or not (blog post coming soon). In these cases, to increase the performance of your site, you may want to remove them. To do this, you will need to use <code>wp_dequeue_script</code>. Let's say that our script was "properly" registered on <code>init</code> and enqueued on <code>wp_enqueue_scripts</code> hooks. To dequeue the script, you just need to do this:</p>
<p><a href="https://gist.github.com/6e676ff6c5516427bb04aac361cacf00" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<h3 name="localizing">Localizing Scripts</h3>
<p>Sometimes, our scripts need some additional information or configuration for whatever reason (localizing strings, configuring a JavaScript object, etc). This is done via <code>wp_localize_script</code>. <code>wp_localize_script</code> takes three parameters: <code>$handle</code> (string), <code>$object_name</code> (string), and <code>$l10n</code> (array).</p>
<p>When you localize your script, the object name (the second parameter) is the name of your JavaScript object, so best practice is that this parameter string would be camelCase. There are no checks within WordPress, so if you pass something like <code>'my-object'</code>, your JavaScript will fail.</p>
<p>Whatever PHP array is passed to <code>wp_localize_script</code> will be placed ahead of your external script tag. You can organize the <code>$l10n</code> array however you'd like, but over time, I have learned and now prefer to do something like this:</p>
<p><a href="https://gist.github.com/6e676ff6c5516427bb04aac361cacf00" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<p>Again, please note that the string properties are camelCased.</p>
<p>Your JavaScript object <strong><em>will</em></strong> be placed in the Global Namespace. In our example, the JavaScript object is named <code>pluginScriptExt</code>. Therefore, our object is available globally via <code>window.pluginScriptExt</code>, so you must always prefix your objects unless you overwrite another object (if you need more information, see Mozilla's <a href="https://developer.mozilla.org/en-US/docs/Glossary/Global_object" rel="noopener" target="_blank">Global Object</a> definition).</p>
<p>For example, if we take our script <code>plugin-script-base</code> from above, it is dependent on <code>underscore</code>. Underscore has a global JavaScript object named <code>_</code>. If we were to do this, we would render Underscore useless and <code>_.each</code> would not be available; instead <code>_.strings</code> would be.</p>
<p><a href="https://gist.github.com/6e676ff6c5516427bb04aac361cacf00" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<p>Alternatively, calling <code>wp_localize_script</code> twice on the same script with the same object name will <em>overwrite</em> the object, not extend the object. For example,<br />
<a href="https://gist.github.com/6e676ff6c5516427bb04aac361cacf00" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<p>With this example, you will have:<br />
<a href="https://gist.github.com/6e676ff6c5516427bb04aac361cacf00" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<p>So, if you want to "expand" an object, it is better to create two objects (until WP_Scripts expands its capabilities).<br />
<a href="https://gist.github.com/6e676ff6c5516427bb04aac361cacf00" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<p>With this example, you will have:<br />
<a href="https://gist.github.com/6e676ff6c5516427bb04aac361cacf00" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<p>It is important to note that the script should either be registered (via <code>wp_register_script</code>) or enqueued (via <code>wp_enqueue_script</code>) before it can be localized.</p>
<h3 name="initializing">Initializing Scripts</h3>
<p>There are several scripts, like sliders, that require some sort of initialization. Take <a href="http://imakewebthings.com/waypoints/" rel="noopener" target="_blank">waypoints</a>, for example. It requires initialization before it can be used on the page. For example:<br />
<a href="https://gist.github.com/6e676ff6c5516427bb04aac361cacf00" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<p>To do this properly within WordPress, you need to use <code>wp_add_inline_script</code>.</p>
<p><a href="https://gist.github.com/6e676ff6c5516427bb04aac361cacf00" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<p><code>wp_add_inline_script</code> can also output JavaScript before a specific script tag. To do this:<br />
<a href="https://gist.github.com/6e676ff6c5516427bb04aac361cacf00" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<p>If you use <code>wp_localize_script</code> and <code>wp_add_inline_script</code>, <code>wp_localize_script</code> will always output <em>before</em> <code>wp_add_inline_script</code>.</p>
<p>Using <code>wp_add_inline_script</code> is a great way to keep your code clean using native WordPress functions and the script manager avoiding yet another hook and manually outputting this yourself.</p>
<p>It is important to note that the script should either be registered (via <code>wp_add_inline_script</code>) or enqueued (via <code>wp_add_inline_script</code>) before it can be initialized.</p>
<p>Extending the previous Waypoints example, let's only do something if <code>waypoints</code> is not already registered. You do this by using <code>wp_script_is</code>.</p>
<p><a href="https://gist.github.com/6e676ff6c5516427bb04aac361cacf00" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<p>With <code>wp_script_is</code>, you can check whether a script has been:</p>
<ul>
<li><code>registered</code></li>
<li><code>enqueued</code>/<code>queued</code></li>
<li><code>to_do</code>/<code>to_print</code></li>
<li><code>done</code>/<code>printed</code></li>
</ul>
<p><code>wp_script_is</code> is quite powerful in debugging scripts and in trying to find when a script was registered, enqueued, and printed on the page.</p>
<p>For example, with <code>wp_script_is( $handle, 'enqueued' )</code>, you can know that you can either deregister (if false) or dequeue the script (if true) in order to prevent that script from being printed on the page.</p>
<p>Finally (though this is becoming much less important), you can make your scripts conditional by adding <code>conditional</code> data to the script. You can do this by using</p>
<p><a href="https://gist.github.com/6e676ff6c5516427bb04aac361cacf00" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<h3 name="modifying">Modifying Script Tags on Print</h3>
<h4>Adding Additional Attributes to <code>script</code> tag&mdash;<code>async</code> and <code>defer</code></h4>
<p>WordPress does not automatically add <code>async</code> or <code>defer</code> to your script tags, nor is there an "easy" way to add it to the script manager (which is still being actively discussed in core (tickets <a href="https://core.trac.wordpress.org/ticket/22249" rel="noopener" target="_blank">22249</a> and <a href="https://core.trac.wordpress.org/ticket/12009" rel="noopener" target="_blank">12009</a>).</p>
<p>First, what is the difference between defer and async? <a href="https://bitsofco.de/async-vs-defer/" rel="noopener" target="_blank">bitsofcode</a> has two great diagrams that explains the difference between the two:<br />
<a href="https://wpsmith.net/wp-content/uploads/2018/06/js-async-execution.png"><img loading="lazy" src="https://wpsmith.net/wp-content/uploads/2018/06/js-async-execution.png" alt="JavaScript Async Execution" width="780" height="152" class="aligncenter size-full wp-image-69988" srcset="https://wpsmith.net/wp-content/uploads/2018/06/js-async-execution.png 780w, https://wpsmith.net/wp-content/uploads/2018/06/js-async-execution-300x58.png 300w, https://wpsmith.net/wp-content/uploads/2018/06/js-async-execution-768x150.png 768w" sizes="(max-width: 780px) 100vw, 780px" /></a></p>
<p><a href="https://wpsmith.net/wp-content/uploads/2018/06/js-defer-execution.png"><img loading="lazy" src="https://wpsmith.net/wp-content/uploads/2018/06/js-defer-execution.png" alt="JavaScript Defer Execution" width="780" height="152" class="aligncenter size-full wp-image-69987" srcset="https://wpsmith.net/wp-content/uploads/2018/06/js-defer-execution.png 780w, https://wpsmith.net/wp-content/uploads/2018/06/js-defer-execution-300x58.png 300w, https://wpsmith.net/wp-content/uploads/2018/06/js-defer-execution-768x150.png 768w" sizes="(max-width: 780px) 100vw, 780px" /></a></p>
<p>Simply stated both <code>defer</code> and <code>async</code> download/fetch the script immediately and do not pause/prevent further HTML parsing. The difference comes at JavaScript execution. <code>defer</code> executes after the HTML parsing is completed and DOM is ready. Because of this adding <code>defer</code> to scripts in the footer makes little sense. <code>async</code> executes when the script comes ready.</p>
<p><iframe loading="lazy" src="//caniuse.bitsofco.de/embed/index.html?feat=script-async&amp;periods=future_1,current,past_1" frameborder="0" width="100%" height="487px"></iframe></p>
<p><iframe loading="lazy" src="//caniuse.bitsofco.de/embed/index.html?feat=script-defer&amp;periods=future_1,current,past_1" frameborder="0" width="100%" height="509px"></iframe></p>
<p>To improve the performance of the page, you need to add these yourself. You can do this by using the <code>script_loader_tag</code> filter, which gives you the HTML of the script being printed on the page, including the conditional HTML and any added inline script.</p>
<p>To add async or defer to all, you can do this:<br />
<a href="https://gist.github.com/6e676ff6c5516427bb04aac361cacf00" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<p>Alternatively, you can be more specific and do something like this:<br />
<a href="https://gist.github.com/6e676ff6c5516427bb04aac361cacf00" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<p>If you use the <a href="https://wpsmith.net/go/genesis" rel="noopener" target="_blank">Genesis Framework</a>, this is already built-in for you. All you need to do is register your script with either <code>?async=true</code> or <code>?defer=true</code> and Genesis will automagically add async or defer to the script tag for you!!</p>
<p><a href="https://gist.github.com/6e676ff6c5516427bb04aac361cacf00" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<h4>Changing the Script Source&mdash;Cache Busting</h4>
<p>You can use the <code>script_loader_src</code> filter to cache bust everything.<br />
<strong><em>DO NOT USE THIS IN PRODUCTION.</em></strong><br />
<a href="https://gist.github.com/6e676ff6c5516427bb04aac361cacf00" target="_blank"><em>View this code snippet on GitHub.</em></a></p>
<h3>Summary</h3>
<p>With this overview of the native WordPress Script functions for script management, you should be able to use any type of JavaScript file in any plugin or theme extending parent theme or plugin JavaScript files.</p>
<ol>
<li><a href="#constants">PHP Constants for Debugging JavaScript</a>: <code>SCRIPT_DEBUG</code> allows you to manage whether your script outputs minified or not. You can also pass the value of <code>SCRIPT_DEBUG</code> to <code>wp_localize_script</code> to help you add debug messages within the console.</li>
<li><a href="#registering">Registering and Deregistering Scripts</a>: Use <code>wp_register_script</code> to register a script on <code>init</code> hook and <code>wp_deregister_script</code> <em>only if you plan to register an alternative</em> to avoid any unintended effects.</li>
<li><a href="#enqueueing">Enqueueing and Dequeueing Scripts</a>: Use <code>wp_enqueue_script</code> to output the script on the page and <code>wp_dequeue_script</code> to prevent the script's output. </li>
<li><a href="#localizing">Localizing Scripts</a>: Use <code>wp_localize_script</code> to output any configuration and translations of any strings used within your script.</li>
<li><a href="#initializing">Initializing Scripts</a>: Use <code>wp_add_inline_script</code> to add additional inline scripts to initialize external scripts or any thing else than adding a configuration object.</li>
<li><a href="#modifying">Modifying Script Tags on Print</a>: Use <code>script_loader_src</code> and <code>script_loader_tag</code> to make more advanced changes to the <code>script</code> tag including adding attributes like <code>async</code> or <code>defer</code>, which <a href="https://wpsmith.net/go/genesis" rel="noopener" target="_blank">Genesis</a> makes easy for you.</li>
</ol>
<p><small>Thank you to both <a href="https://gamajo.com/" rel="noopener" target="_blank">Gary Jones</a> and <a href="https://thestizmedia.com/" rel="noopener" target="_blank">Mike Hemberger</a> for pre-reviewing and providing some great insights!</small></p>
<p>The post <a rel="nofollow" href="https://wpsmith.net/2018/wordpress-javascript-manager-native-functions/">WordPress JavaScript Manager Native Functions</a> appeared first on <a rel="nofollow" href="https://wpsmith.net">WP Smith</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://wpsmith.net/2018/wordpress-javascript-manager-native-functions/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Causes of WordPress Site Performance Slowdown</title>
		<link>https://wpsmith.net/2018/causes-wordpress-site-performance-slowdown/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=causes-wordpress-site-performance-slowdown</link>
					<comments>https://wpsmith.net/2018/causes-wordpress-site-performance-slowdown/#comments</comments>
		
		<dc:creator><![CDATA[Travis Smith]]></dc:creator>
		<pubDate>Tue, 05 Jun 2018 12:00:40 +0000</pubDate>
				<category><![CDATA[Performance]]></category>
		<guid isPermaLink="false">https://wpsmith.net/?p=69952</guid>

					<description><![CDATA[<p>Previously, we discussed Why WordPress Performance Matters and the importance of your site's speed and performance. So what could be causing your site's slowdown? What is slowing down your WordPress website? What factors are affecting your site's performance? Your site's slowdown can be cause by a myriad of things including: HTTP Requests WordPress Configuration Theme Plugins [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://wpsmith.net/2018/causes-wordpress-site-performance-slowdown/">Causes of WordPress Site Performance Slowdown</a> appeared first on <a rel="nofollow" href="https://wpsmith.net">WP Smith</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><a href="https://wpsmith.net/wp-content/uploads/2018/06/website-performance-site-slowdown.jpg"><img loading="lazy" class="aligncenter wp-image-69958 size-large" src="https://wpsmith.net/wp-content/uploads/2018/06/website-performance-site-slowdown-1024x768.jpg" alt="" width="1024" height="768" srcset="https://wpsmith.net/wp-content/uploads/2018/06/website-performance-site-slowdown-1024x768.jpg 1024w, https://wpsmith.net/wp-content/uploads/2018/06/website-performance-site-slowdown-300x225.jpg 300w, https://wpsmith.net/wp-content/uploads/2018/06/website-performance-site-slowdown-768x576.jpg 768w, https://wpsmith.net/wp-content/uploads/2018/06/website-performance-site-slowdown.jpg 1200w" sizes="(max-width: 1024px) 100vw, 1024px" /></a>Previously, we discussed <a href="https://wpsmith.net/2018/wordpress-performance-matters/">Why WordPress Performance Matters</a> and the importance of your site's speed and performance. So what could be causing your site's slowdown? What is slowing down your WordPress website? What factors are affecting your site's performance?</p>
<p>Your site's slowdown can be cause by a myriad of things including:</p>
<ul>
<li><a href="#http-requests">HTTP Requests</a></li>
<li><a href="#wordpress-configuration">WordPress Configuration</a></li>
<li><a href="#theme">Theme</a></li>
<li><a href="#plugins">Plugins</a></li>
<li><a href="#page-size">Page Size, Images, &amp; Videos</a></li>
<li><a href="#hosting">Hosting, Bad architecture or Infrastructure (servers)</a></li>
</ul>
<p>The list could go on and on depending on the type of site you are running. Your site's speed could be fantastic but your admin horribly slow. So let's break some these down into some details.</p>
<h3><a name="http-requests"></a>HTTP Requests</h3>
<p><a href="https://wpsmith.net/wp-content/uploads/2018/06/http-requests-google-chrome.png"><img loading="lazy" class="wp-image-69960 size-medium alignright" src="https://wpsmith.net/wp-content/uploads/2018/06/http-requests-google-chrome-300x269.png" alt="" width="300" height="269" srcset="https://wpsmith.net/wp-content/uploads/2018/06/http-requests-google-chrome-300x269.png 300w, https://wpsmith.net/wp-content/uploads/2018/06/http-requests-google-chrome-768x688.png 768w, https://wpsmith.net/wp-content/uploads/2018/06/http-requests-google-chrome-1024x917.png 1024w, https://wpsmith.net/wp-content/uploads/2018/06/http-requests-google-chrome.png 1642w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>
<p>When doing a site audit or analysis, one of the first things I check when analyzing a site is the number of HTTP Requests a site is making. With HTTP Requests, the fewer the better your site will perform.</p>
<p>Take my site for example. At the time of writing this article, my site has 47 total HTTP Requests:</p>
<ul>
<li> Javascript: 19 <span class="kb">(620 KB)</span></li>
<li> CSS: 12 <span class="kb">(294 KB)</span></li>
<li> Images: 9 <span class="kb">(6978 KB)</span></li>
<li> Font: 4 <span class="kb">(105 KB)</span></li>
<li> HTML: 3 <span class="kb">(72 KB)</span></li>
</ul>
<p>Now compare that to some ad-driven sites (speedtest.net has 381 total HTTP Requests), 47 is really good. However, it can be drastically improved with some good workflow(s), combining of files, etc. (which I haven't done on my site yet and probably should). If you dive into it, you will see some files that I do not use at all. If you dive even deeper, you will find some CSS that I do not use at all. So I could reduce my CSS file size by clearing out some of my CSS.</p>
<p>How many HTTP Requests does your site have? You can easily check out yours at <a href="https://www.giftofspeed.com/request-checker/" target="_blank" rel="noopener">Gift Of Speed's HTTP Requests Checker</a>.</p>
<h3><a name="wordpress-configuration"></a>WordPress Database &amp; Configuration</h3>
<p>There are several things within WordPress that you can configure or add to your <code>functions.php</code> file to ease and improve the site's performance. These include:</p>
<ul>
<li><a href="#updates">Updates</a></li>
<li><a href="#comments">Comments</a></li>
<li><a href="#revisions">Revisions</a></li>
<li><a href="#emptying-trash">Emptying Trash</a></li>
<li><a href="#db-optimization">Database (DB) Optimization</a></li>
</ul>
<h4><a name="updates"></a>Updates</h4>
<p>Many WordPress site owners think that WordPress will take care of itself and never update WordPress or any of the plugins and themes in fear of something breaking, which is extremely valid (and why you should always have a staging site). If you are on a managed WordPress hosting company like <a href="https://wpsmith.net/go/wpengine/" target="_blank" rel="noopener">WP Engine</a>, then you are pretty much covered. However, if you are on Bluehost or Hostgator, then you need to add the ability for <a href="https://codex.wordpress.org/Configuring_Automatic_Background_Updates#Configuration_via_wp-config.php" target="_blank" rel="noopener">WordPress</a> to update itself automatically.</p>
<p>To configure automatic updates, add one of the following to <code>wp-config.php</code>:</p>
<pre>// Disable automatic updates.
define( 'AUTOMATIC_UPDATER_DISABLED', true );

// Enable all core updates.
define( 'WP_AUTO_UPDATE_CORE', true );

// Enable only minor core updates.
define( 'WP_AUTO_UPDATE_CORE', 'minor' );</pre>
<p>Personally, I always use the minor core updates configuration and leave major updates to be done manually as this really could break sites that are using more than a few plugins.</p>
<p>Regardless, <em><strong>all active plugins and themes</strong></em> should be updated, and any minor updates should be applied immediately. Minor updates are any updates where the last number in the version changes. So if your plugin is currently version 1.1.2, a minor update would be 1.1.3 or 1.1.4. If your plugin is currently version 1.1, 1.2 could be considered a minor update. Minor updates are usually fixing some small bug or security hole (<em>more below</em>).</p>
<p>While on the subject of auto-updates, auto-updates of translations are enabled by default but can be disabled by adding the following to your <code>functions.php</code> file:</p>
<pre>add_filter( 'auto_update_translation', '__return_false' );</pre>
<p>And finally, WordPress sends emails regarding the state of automatic updates. To disable these emails, add the following to your <code>functions.php</code> file:</p>
<pre>add_filter( 'auto_core_update_send_email', '__return_false' );</pre>
<h4><a name="comments"></a>Comments</h4>
<p>Content with lots of discussion can be a huge issue in the site's performance. More advanced configuration would shard comments from the database and host comments in its own instance. However, that is not even a possibility for most of us. Instead, you could use something like Jetpack's comment system or even Disqus, LiveFyre, etc. While I have not done my due diligence on Jetpack's comment system's performance, I have been most satisfied with theirs above the others. Yet, if you lazy load Disqus (e.g., using <a href="https://wordpress.org/plugins/disqus-conditional-load/" target="_blank" rel="noopener">Disqus Conditional Load</a>), then you can definitely improve the performance of your post page, or any page with comments.<a href="https://wpsmith.net/wp-content/uploads/2018/06/improve-comments-wordpress-performance.png"><img loading="lazy" class="aligncenter size-large wp-image-69962" src="https://wpsmith.net/wp-content/uploads/2018/06/improve-comments-wordpress-performance-1024x424.png" alt="" width="1024" height="424" srcset="https://wpsmith.net/wp-content/uploads/2018/06/improve-comments-wordpress-performance-1024x424.png 1024w, https://wpsmith.net/wp-content/uploads/2018/06/improve-comments-wordpress-performance-300x124.png 300w, https://wpsmith.net/wp-content/uploads/2018/06/improve-comments-wordpress-performance-768x318.png 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Alternatively, you can break your comment section into pages, which is available by default within WordPress core. To paginate comments, just go to <em>Settings » Discussions</em> and then choose the number of comments you want per page. This should help improve memory consumption and boost page load times for posts and pages with tons of comments.</p>
<p>Finally, removing and preventing spam comments is extremely important. You can easily do this with the <strong>Empty Spam</strong> button on the Comments admin page.<a href="https://wpsmith.net/wp-content/uploads/2018/06/remove-spam-comments-wordpress-performance.png"><img loading="lazy" class="aligncenter wp-image-69964 size-large" src="https://wpsmith.net/wp-content/uploads/2018/06/remove-spam-comments-wordpress-performance-e1528135055452-1024x455.png" alt="" width="1024" height="455" srcset="https://wpsmith.net/wp-content/uploads/2018/06/remove-spam-comments-wordpress-performance-e1528135055452-1024x455.png 1024w, https://wpsmith.net/wp-content/uploads/2018/06/remove-spam-comments-wordpress-performance-e1528135055452-300x133.png 300w, https://wpsmith.net/wp-content/uploads/2018/06/remove-spam-comments-wordpress-performance-e1528135055452-768x341.png 768w, https://wpsmith.net/wp-content/uploads/2018/06/remove-spam-comments-wordpress-performance-e1528135055452.png 1310w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<h4><a name="revisions"></a>Revisions</h4>
<p>One example is <strong>revisions</strong>. Your site creates <em>a lot</em> of revisions when you are writing. This will pollute your database and make database queries take longer time to process. To fix this, you can either disable or limit the number of revisions.</p>
<p>To disable revisions, add the following to <code>wp-config.php</code>:</p>
<pre>define( 'WP_POST_REVISIONS', false );</pre>
<p>To limit revisions, add the following to <code>wp-config.php</code>:</p>
<pre>define( 'WP_POST_REVISIONS', 3 );</pre>
<p>By default, WordPress auto-saves your posts every 60s. You can also slow down how often (in seconds) revisions are taken, add the following to <code>wp-config.php</code>:</p>
<pre>define( 'AUTOSAVE_INTERVAL', 300 );</pre>
<p>Personally, I would never turn off autosave because I cannot tell you how many times it has saved me, my friends or my clients.</p>
<h4><a name="emptying-trash"></a>The Trash</h4>
<p>Sometimes, you will have deleted items (e.g., posts, pages, images, comments, links, etc.) that have been placed into the trash. By default, WordPress <a href="https://codex.wordpress.org/Editing_wp-config.php#Empty_Trash" target="_blank" rel="noopener">empties the trash</a> every 30 days. However, you can also configure this by adding the following to <code>wp-config.php</code>:</p>
<pre>define( 'EMPTY_TRASH_DAYS', 14 );</pre>
<p>Or you can even disable this (though I highly discourage this as it will bloat your database).</p>
<pre>define( 'EMPTY_TRASH_DAYS', 0 );</pre>
<h4><a name="db-optimization"></a>Database Optimization</h4>
<p>Finally, you should optimize your database often. First and foremost, before touching the database, <em><strong>always</strong></em> create a backup. <em><strong>Always!</strong></em> This cannot be over stated. In a subsequent article, I will discuss several plugins that will help you achieve this, but let me give you a high level overview.</p>
<p>Your database should be optimize to remove any unnecessary data such as spam comments, pingbacks, trackbacks, expired transients, and orphaned data (usually from plugins being deactivated. deleted, or removed improperly). Again, before you do any of this, <em>backup your database</em>.</p>
<p>Almost all plugins store something in the database, whether it is in the <code>wp_options</code> table or custom tables. However, not all plugins have properly implemented an uninstall method to remove the data associated with the plugin (or the plugin forgets about some of the settings it set). So, the WordPress database can accumulate a lot of additional data that is unused.</p>
<p>Now, WordPress does have the ability to repair and optimize itself. You can  read more about this in the <a href="https://codex.wordpress.org/Editing_wp-config.php#Automatic_Database_Optimizing" target="_blank" rel="noopener">Automatic Database Optimizing</a>  within WordPress.org. To enable this, add the following to <code>wp-config.php</code>:</p>
<pre>define( 'WP_ALLOW_REPAIR', true );</pre>
<p>Then you can go to the repair page (<code>/wp-admin/maint/repair.php</code>) to use the optimization tool.</p>
<p>My favorite and go to plugin is the <a href="https://wpsmith.net/go/advanced-database-cleaner/" target="_blank" rel="noopener">Advanced Database Cleaner</a> (which has a free version) by <a href="https://wpsmith.net/go/sigma-plugin/" target="_blank" rel="noopener">Sigma Plugin</a>, but more about that later.</p>
<h3><a name="theme"></a>Your WordPress Theme &amp; Performance</h3>
<p>WordPress themes are written for a wide audience of people focusing on features, nice and pretty presentations, and flexibility in order to garner sales and revenue. Your theme may be slowing down your WordPress site because the theme is:</p>
<ul>
<li><a href="#theme-over-engineered">Over-engineered</a></li>
<li><a href="#theme-updates">Not updated</a></li>
<li><a href="#fonts">Fonts</a></li>
</ul>
<p>Generally speaking, WordPress themes (or child themes) do not focus on performance per se (e.g., conditionally outputting files when in use). For example, while Genesis focuses heavily on performance, the child theme that you are using <em>may not</em> focus on performance, and I have seen, even sadly created, some really bad child theme implementations.</p>
<h4><a name="theme-over-engineered"></a>Over-Engineered</h4>
<p>In the past, <a href="https://wpsmith.net/go/themeforest/" target="_blank" rel="noopener">ThemeForest</a> themes have been notoriously bad about providing over-engineered, poorly coded, feature-rich themes. These themes are focused on providing as much functionality and as many features as possible in order to sell to the widest audience as possible. However, <a href="https://wpsmith.net/go/themeforest/" target="_blank" rel="noopener">Evanto</a> has made great efforts of late to begin mitigating some of these issues they had when the site first started, and there <em>are</em> some really good themes in their marketplace. Other private theme shops are also extremely bad about this (<small>but I am not going to call any of these out explicitly</small>).</p>
<p>One example is shortcodes. Shortocdes are often include as a part of a theme to provide additional functionality, but often theme developers assume that you are going to use them and output the JavaScript and CSS assets without outputting them conditionally (e.g., using <code>has_shortcode</code> on the post's content).</p>
<h4><a name="theme-updates"></a>Not Updated</h4>
<p>Your site should be using a child theme, or provide a mechanism for you to customize the site without your site breaking due to a theme update.</p>
<p>Automatic updates can be configured for themes. To add support for automatic theme updates, add the folllowing to your <code>functions.php</code> file:</p>
<pre>add_filter( 'auto_update_theme', '__return_true' );</pre>
<p>Or if you want to prevent automatic updates, then add:</p>
<pre>add_filter( 'auto_update_theme', '__return_false' );</pre>
<p>Alternatively, you can also have finer control over what theme(s) you may want to auto-update.</p>
<pre>add_filter( 'auto_update_theme', 'prefix_auto_update_genesis', 10, 2 );
/**
 * Auto update specific theme.
 * 
 * @param bool   $update Whether to allow auto-update.
 * @param string $item   Item slug.
 *
 * @return bool Whether to update plugin.
 */
function prefix_auto_update_genesis( $update, $item ) {
    if ( 'genesis' === $item-&gt;theme ) {
        return true;
    } else {
        return $update; // Else, use the normal API response to decide whether to update or not
    }
}</pre>
<p><a href="https://wpsmith.net/wp-content/uploads/2018/06/google-fonts-performance-open-sans-all-weights-styles.png"><img loading="lazy" class="size-medium wp-image-69957 alignright" src="https://wpsmith.net/wp-content/uploads/2018/06/google-fonts-performance-open-sans-all-weights-styles-294x300.png" alt="Google Fonts Performance for All Weights and Styles" width="294" height="300" srcset="https://wpsmith.net/wp-content/uploads/2018/06/google-fonts-performance-open-sans-all-weights-styles-294x300.png 294w, https://wpsmith.net/wp-content/uploads/2018/06/google-fonts-performance-open-sans-all-weights-styles-768x784.png 768w, https://wpsmith.net/wp-content/uploads/2018/06/google-fonts-performance-open-sans-all-weights-styles-1004x1024.png 1004w, https://wpsmith.net/wp-content/uploads/2018/06/google-fonts-performance-open-sans-all-weights-styles.png 1178w" sizes="(max-width: 294px) 100vw, 294px" /></a></p>
<h4><a name="fonts"></a>Fonts</h4>
<p>Some themes will output several Google Fonts in all its font weights and styles but you may only use a subset. For example, if you were to select all styles and weights for the popular <a href="https://fonts.google.com/specimen/Open+Sans?selection.family=Open+Sans" target="_blank" rel="noopener">Open Sans</a>, even Google tells you that it will have a slow load time.</p>
<h3><a name="plugins"></a>The Plugins You Use &amp; Performance</h3>
<p><a href="https://wpsmith.net/wp-content/uploads/2018/06/wordpress-plugins-site-performance.png"><img loading="lazy" class="aligncenter size-large wp-image-69961" src="https://wpsmith.net/wp-content/uploads/2018/06/wordpress-plugins-site-performance-1024x335.png" alt="" width="1024" height="335" srcset="https://wpsmith.net/wp-content/uploads/2018/06/wordpress-plugins-site-performance-1024x335.png 1024w, https://wpsmith.net/wp-content/uploads/2018/06/wordpress-plugins-site-performance-300x98.png 300w, https://wpsmith.net/wp-content/uploads/2018/06/wordpress-plugins-site-performance-768x252.png 768w, https://wpsmith.net/wp-content/uploads/2018/06/wordpress-plugins-site-performance.png 1960w" sizes="(max-width: 1024px) 100vw, 1024px" /></a><br />
WordPress plugins are also written for a wide audience of people focusing on features and flexibility. The best plugins focus on a single feature and/or problem. Please note, it is not the <em><strong>number</strong></em> of plugins being used, but the quality of the plugins (<a href="https://wpsmith.net/go/not-number-quality-plugins/" target="_blank" rel="noopener">see this article)</a>. However, many WordPress (non-performance) plugins also do not consider performance. The biggest culprit and example are slider and gallery plugins. Both <a href="https://wpsmith.net/go/soliloquy" target="_blank" rel="noopener">Soliloquy</a> and <a href="https://wpsmith.net/go/envira/" target="_blank" rel="noopener">Envira Gallery</a> entered the market and took its marketshare entirely based on its performance capabilities.</p>
<p>Your site could be slow because you have plugins that may:</p>
<ul>
<li><a href="#duplicate-functionality">Duplicate functionality</a></li>
<li><a href="#unused-plugins">Not used</a></li>
<li><a href="#cpu-ram">Use too much CPU and Memory (RAM)</a></li>
<li><a href="#old-plugins">Be old and out-of-date</a></li>
<li><a href="#pirated-plugins">Pirated</a></li>
<li><a href="#poorly-coded-plugins">Poorly coded</a></li>
</ul>
<h4><a name="duplicate-functionality"></a>Duplicate Functionality Plugins</h4>
<p>We all use WordPress plugins to enhance our site(s). However, sometimes we use plugins that duplicate functionality that our theme has or even another plugin! Recently, I was working on site that had not one or two but <em>three</em> different slider plugins installed! That was the first thing that had to go! Another example is that we have plugins that we are using that your host may provide out of the box (e.g., No Revisions, Force Strong Passwords, etc. are some plugins that <a href="https://wpsmith.net/go/wpengine" target="_blank" rel="noopener">WP Engine</a> already helps on their managed hosting).</p>
<p>Let me given you a couple really good and easy examples. First, many of us love icons, and if you look at many WordPress sites, you will find Dashicons <em>and</em> Font Awesome in the HTML but only one of them is used (except when the user is logged into the site and admin bar is showing). This is often because one will be outputted by the theme and the other will be outputted by a plugin. There are many reasons why this happens but is something that we all need to be aware.</p>
<p>Second, we all need good SEO and sitemaps. But you do not need <a href="https://wordpress.org/plugins/google-sitemap-generator/" target="_blank" rel="noopener">Google XML Sitemaps</a> if you are running <a href="https://wordpress.org/plugins/wordpress-seo/" target="_blank" rel="noopener">Yoast's WordPress SEO plugin</a> or his <a href="https://yoast.com/wordpress/plugins/" target="_blank" rel="noopener">premium plugin</a>.</p>
<h4><a name="unused-plugins"></a>Unused Plugins</h4>
<p>Many people stop using a plugin but are afraid to deactivate the plugin because "it may be in use somewhere on the site." These excess plugins may be causing performance and/or security issues on your site that you are not even aware.</p>
<h4><a name="cpu-ram"></a>High CPU/Memory Plugins</h4>
<p>Some plugins are detrimental to your site's performance because they require heavy CPU or memory (RAM) to run. This could be due to the plugin's code and/or use. WP Engine maintains a phenomenal (and dynamic) list of <a href="https://wpsmith.net/go/disallowed-plugins/">Disallowed Plugins</a>, note especially the Related Posts Plugins, Broken Link Checker Plugins, and Email Plugins. One other is WordFence, which is a great security plugin but does affect performance.</p>
<p>These aren't <em>bad</em> plugins. They provide functionality that you may want or even need, but they are performance hogs preventing your site from performing its best. If you "need" any of these plugins, you may need to upgrade to a VPS or Dedicated Hosting plan (see below).</p>
<h4><a name="old-plugins"></a>Old Plugins</h4>
<p>All active plugins should be updated, and any minor updates should be applied immediately. Minor updates are any updates where the last number in the version changes. So if your plugin is currently version 1.1.2, a minor update would be 1.1.3 or 1.1.4. If your plugin is currently version 1.1, 1.2 could be considered a minor update. Minor updates are usually fixing some small bug or security hole. <em>So always keep your plugins up-to-date!</em></p>
<p>Automatic updates can be configured for plugins. To add support for automaticplugin updates, add the folllowing to your <code>functions.php</code> file:</p>
<pre>add_filter( 'auto_update_plugin', '__return_true' );</pre>
<p>Or if you want to prevent automatic updates, then add:</p>
<pre>add_filter( 'auto_update_plugin', '__return_false' );</pre>
<p>Alternatively, you can also have finer control over what plugins you may want to auto-update.</p>
<pre>add_filter( 'auto_update_plugin', 'prefix_auto_update_specific_plugins', 10, 2 );
/**
 * Auto update specific plugins.
 * 
 * @param bool   $update Whether to allow auto-update.
 * @param string $item   Item slug.
 *
 * @return bool Whether to update plugin.
 */
function prefix_auto_update_specific_plugins ( $update, $item ) {
    // Array of plugin slugs to always auto-update
    $plugins = array ( 
        'akismet',
        'buddypress',
    );
    if ( in_array( $item-&gt;slug, $plugins ) ) {
        return true; // Always update plugins in this array
    } else {
        return $update; // Else, use the normal API response to decide whether to update or not
    }
}</pre>
<h4><a name="pirated-plugins"></a>Pirated Plugins</h4>
<p><a href="https://wpsmith.net/wp-content/uploads/2018/06/wordpress-performance-pirated-plugins.jpg"><img loading="lazy" class="aligncenter wp-image-69972 size-large" src="https://wpsmith.net/wp-content/uploads/2018/06/wordpress-performance-pirated-plugins-e1528136777836-1024x438.jpg" alt="Pirated Plugins Steal Your Performance" width="1024" height="438" srcset="https://wpsmith.net/wp-content/uploads/2018/06/wordpress-performance-pirated-plugins-e1528136777836-1024x438.jpg 1024w, https://wpsmith.net/wp-content/uploads/2018/06/wordpress-performance-pirated-plugins-e1528136777836-300x128.jpg 300w, https://wpsmith.net/wp-content/uploads/2018/06/wordpress-performance-pirated-plugins-e1528136777836-768x328.jpg 768w, https://wpsmith.net/wp-content/uploads/2018/06/wordpress-performance-pirated-plugins-e1528136777836.jpg 1280w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Face it. Some people hate paying for WordPress plugins. After all GPL means free, right? Wrong. GPL means that the code can be freely distributed but does not mean that the plugin itself is free. Developers provide a service above and beyond the plugin. They provide updates and fixes as WordPress continues to evolve. They provide support in helping identify plugin conflicts with other plugins, etc. But regardless, some people still download premium plugins from non-reputable sites. These sites can and often do inject some "phone home" or other malware. Just remember, <em><strong>there is no honor among thieves</strong></em>. If you do take this risk, <a href="https://wpsmith.net/go/sucuri/" target="_blank" rel="noopener">Sucuri</a> is a great premium plugin to use to watch your site's malware issues.</p>
<h4><a name="poorly-coded-plugins"></a>Poorly Coded Plugins</h4>
<p>Like themes, not all plugins are created equal. Some are quick proof0-of-concepts to see if it can make money. Some are quickly done for clients to get the client off the developer's back. Some are coded by junior developers that do things "weirdly,"  or don't follow PHP/JavaScript coding best practices. Some are written by new WordPress developers (though they may be senior PHP/JavaScript developers or senior other-CMS developers) and just don't know how to code for WordPress, so they do not use WordPress best practices (e.g., not using WordPress's built-in JavaScript libraries).</p>
<p>Also, one of the best practices of figuring out what is causing your site slowness is to deactivate plugins one by one to see which one is causing said issue. So, when you add a new plugin, test your site thoroughly to make sure there are no ill effects.</p>
<h3><a name="page-size"></a>Page Size, Images, &amp; Videos</h3>
<p>Page size is incredibly important. For example a light weight page of 929KB (average web page size in 2011) will always load faster than the average website page of 2-3MB (average web page size today) which will always load faster than the outrageously heavy pages of 30MB (for more information see <a href="https://speedcurve.com/blog/web-performance-page-bloat/" target="_blank" rel="noopener">SpeedCurve's post</a>). The majority of new internet users are in regions where 2G is the basic internet connection. They also are paying for the data they use by the GB or even MB (<a href="https://whatdoesmysitecost.com/" target="_blank" rel="noopener">how much does my site cost the user</a>?). So in order to be fiscally and data responsible, we need to optimize our site the best we can.</p>
<p>Heavy pages are almost always caused by ads, images and videos.The performance of both <em>images</em> and <em>video</em> can be easily improved through lazy loading.</p>
<p><em>Images</em> are a fantastic way to engage users and prettify your site. However, many sites are heavy laden with tons of images that are <em>not</em> optimized. As a result, the reverse affect could be happening. Instead of engaging your users, you may be annoying your users. To prevent this, I recommend that you optimize your web images whether that is via the command line, some optimization program, or image editing software (e.g., PhotoShop, etc.).</p>
<p>Optimizing an image includes two things: (1.) image height and width and (2.) image file size. The height and width will affect your image file size. For example, if your site is designed to only be 1280px wide, your images don't need to be larger than 1280px wide. Of course there are reasons why you may want to offer larger image sizes but these sizes should be loaded on a user action (e.g., click for a modal or download).</p>
<p>You can resize your images using <a href="https://bulkresizephotos.com/" target="_blank" rel="noopener">Bulk Resize</a>, which allows you to resize images <em><strong>without uploading them!</strong></em> This program will also optimize your image approximately 20%. WordPress also attempts to optimize your JPEG images to ~80% quality. However, this too can be changed to improve the quality (e.g., 90%, which improves the files size) or reduce the quality (e.g., 70%, which reduces the file size).</p>
<pre>// Increase quality and image file size.
add_filter( 'jpeg_quality', create_function( '', 'return 90;' ) );

// Reduce quality and image file size.
add_filter( 'jpeg_quality', create_function( '', 'return 100;' ) );</pre>
<p><em>Videos</em>, in my opinion (from a user perspective), should never autoplay. From an advertiser/media company perspective, autoplay does provide some revenue potential, if properly pre-rolled (or even post-rolled). Also, videos should never be played from WordPress. Instead, use <a href="https://vimeo.com/" target="_blank" rel="noopener">Vimeo</a> or <a href="https://www.youtube.com/" target="_blank" rel="noopener">YouTube</a>. Both of them have the ability to make the videos private and able to play only on certain domains.</p>
<h3><a name="hosting"></a>Hosting, Architecture, &amp; Infrastructure</h3>
<p>Hosting is one of the biggest culprits of why your site is slow. However, this can <em><strong>only</strong></em> be determined by the process of eliminating all other issues. The primary indicator for determining that it is the host's performance is Time to First Byte (TTFB). Usually with many hosting companies like Hostgator or Bluehost, you have options like:</p>
<ul>
<li><a href="#shared-hosting">Shared hosting</a></li>
<li><a href="#wp-hosting">WordPress hosting</a></li>
<li><a href="#vps-hosting">VPS hosting</a></li>
<li><a href="#dedicated-hosting">Dedicated hosting</a></li>
<li><a href="#reseller-hosting">Reseller Hosting</a></li>
</ul>
<p>What is the difference between these?</p>
<h4><a name="shared-hosting"></a>Shared &amp; WordPress Hosting</h4>
<p><em>Shared Hosting </em>is a web hosting environment that is shared across multiple customers/accounts and websites from a single server. Shared hosting are servers than generally can run any type of website, whether it is written in PHP (like WordPress, Drupal, Joomla, etc.), nodejs, GoLang, Ruby, Python, etc. While many hosting companies have explicit clauses against running Minecraft or gaming servers on shared hosting, some people still do this.</p>
<p>Let me give you an example. Let's say a server can hold and run 100 websites, and let's say a customer has an average of 2.5 websites. This means that a company will place 40 customers (100 sites/2.5 sites per customer) on that server. So if the customers on that server average 5 websites per customer then the server will under perform. Or, say the server is perfectly allocated among all the customers, if any one of those customers begin to spam or send out a plethora of emails, this will affect your site's performance. If any of those customers get hacked, besides being potentially hacked (though most hosting companies have decent isolation between customers), your site's performance will wane due to their hacking.</p>
<p>Now, most of these web hosting companies have monitoring, algorithms, scripts to prevent this from happening as much as possible. However, these monitoring tools, etc. are designed to maximize the use of the server, not your specific site's performance. So if your site's performance begins to slow because of shared hosting, you can ask your host to investigate.</p>
<p>At some point, the only way to improve your site's performance will be to move away from a shared hosting environment to a VPS or dedicated hosting environment.</p>
<p><em><a style="margin-top: 15px;" name="wp-hosting"></a>WordPress Hosting</em> is only another flavor of shared hosting except that these servers are often tuned specifically for WordPress. This means that support for other languages is often removed (though not always). WordPress Hosting at companies like Hostgator or Bluehost is very inexpensive and a great solution for low traffic websites or a proof-of-concept site.</p>
<h4><a name="vps-hosting"></a>VPS Hosting</h4>
<p><em>Virtual Private Server (VPS) Hosting</em> is a website hosting environment that dedicates a specific amount of resources (e.g., RAM, CPU, Bandwidth, Storage, etc.) to your account. This is one step <span style="text-decoration: underline;">above</span> shared hosting, which does not guarantee any specific amount of resources to your account, and one step <span style="text-decoration: underline;">below</span> dedicated hosting. Within the datacenter, a VPS hosted account will receive a single virtual private server, but the physical server may have multiple VPS accounts on it with its resources split among the accounts appropriately.</p>
<p>Let me give you a basic example. Let's say a physical server has 16 CPU Cores and 64GB RAM, and the VPS company offers VPS solutions of</p>
<ol>
<li>4 Cores &amp; 8GB RAM,</li>
<li>8 Cores &amp; 16GB RAM,</li>
<li>8 Cores &amp; 32GB RAM, and</li>
<li>16 Cores &amp; 32GB RAM</li>
</ol>
<p>Now, the hosting company can host:</p>
<ul>
<li>four clients who select option #1,</li>
<li>2 clients who select option #2,</li>
<li>1 client who selects option #2 and 1 client who selects option #3,</li>
<li>2 clients who select option #3,</li>
<li>1 client who selects option #3.</li>
</ul>
<p>Generally speaking, there are two types of VPS Hosts: managed and semi/un-managed. Managed means that you will be given admin portal(s), some automated solutions (e.g., backups) and support to help you do what you need. Semi/Un-managed simply means that you are given the VPS with access and can do whatever you want. While support is given to unmanaged solutions, often it is limited for a variety of good reasons.</p>
<p>At some point, the only way to improve your site's performance will be to move away from both a shared hosting environment and a VPS hosting environment to a dedicated hosting environment.</p>
<h4><a name="dedicated-hosting"></a>Dedicated Hosting</h4>
<p><em>Dedicated Hosting</em> is a website hosting environment on a dedicated server for your account. This means that only you and your website(s) are on this server. These servers are much faster because you are not sharing anything with anyone, so all the server's resources are yours entirely. With dedicated, you also get full control of everything, which is both good and bad. As Uncle Ben says, "With great power comes great responsibility."</p>
<h4><a name="reseller-hosting"></a>Reseller Hosting</h4>
<p><em>Reseller Hosting</em>, depending on the company, is a VPS or Dedicated Hosting account for a company or agency to host (and bill) their clients without the overhead of server maintenance, server software, etc. It white labels the true, underlying hosting company. So say you are hosting with a Web Development Agency name WP Awesome Hosts. WP Awesome Hosts could be using Hostgator, Bluehost, Amazon, KnownHost, or any other cloud hosting company (with real data centers) white labeling it as though they are a true hosting company.</p>
<h3>Summary</h3>
<p>So what is causing your site slowdown? Is it:</p>
<ul>
<li><a href="#http-requests">HTTP Requests</a></li>
<li><a href="#wordpress-configuration">WordPress Configuration</a></li>
<li><a href="#theme">Theme</a></li>
<li><a href="#plugins">Plugins</a></li>
<li><a href="#page-size">Page Size, Images, &amp; Videos</a></li>
<li><a href="#hosting">Hosting, Bad architecture or Infrastructure (servers)</a></li>
</ul>
<p>In the next few posts, I will be diving further into WordPress performance and even more specifics around tooling and identifying performance bottlenecks and issues. Stay tuned!</p>
<p>The post <a rel="nofollow" href="https://wpsmith.net/2018/causes-wordpress-site-performance-slowdown/">Causes of WordPress Site Performance Slowdown</a> appeared first on <a rel="nofollow" href="https://wpsmith.net">WP Smith</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://wpsmith.net/2018/causes-wordpress-site-performance-slowdown/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Need for Speed</title>
		<link>https://wpsmith.net/2018/need-for-speed/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=need-for-speed</link>
					<comments>https://wpsmith.net/2018/need-for-speed/#respond</comments>
		
		<dc:creator><![CDATA[Travis Smith]]></dc:creator>
		<pubDate>Mon, 04 Jun 2018 14:00:10 +0000</pubDate>
				<category><![CDATA[Infographic]]></category>
		<guid isPermaLink="false">https://wpsmith.net/?p=69941</guid>

					<description><![CDATA[<p>The post <a rel="nofollow" href="https://wpsmith.net/2018/need-for-speed/">Need for Speed</a> appeared first on <a rel="nofollow" href="https://wpsmith.net">WP Smith</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><a href="https://www.getelastic.com/site-speed-infographic" rel="noopener" target="_blank"><img loading="lazy" class="aligncenter size-large wp-image-69942" src="https://wpsmith.net/wp-content/uploads/2018/06/need-for-speed-infographic-137x1024.jpg" alt="Website Performance: Need for Speed" width="137" height="1024" srcset="https://wpsmith.net/wp-content/uploads/2018/06/need-for-speed-infographic-137x1024.jpg 137w, https://wpsmith.net/wp-content/uploads/2018/06/need-for-speed-infographic-40x300.jpg 40w, https://wpsmith.net/wp-content/uploads/2018/06/need-for-speed-infographic.jpg 600w" sizes="(max-width: 137px) 100vw, 137px" /></a></p>
<p>The post <a rel="nofollow" href="https://wpsmith.net/2018/need-for-speed/">Need for Speed</a> appeared first on <a rel="nofollow" href="https://wpsmith.net">WP Smith</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://wpsmith.net/2018/need-for-speed/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Website Performance Optimization</title>
		<link>https://wpsmith.net/2018/website-performance-optimization-infographic/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=website-performance-optimization-infographic</link>
					<comments>https://wpsmith.net/2018/website-performance-optimization-infographic/#respond</comments>
		
		<dc:creator><![CDATA[Travis Smith]]></dc:creator>
		<pubDate>Sun, 03 Jun 2018 15:35:44 +0000</pubDate>
				<category><![CDATA[Infographic]]></category>
		<guid isPermaLink="false">https://wpsmith.net/?p=69946</guid>

					<description><![CDATA[<p>The post <a rel="nofollow" href="https://wpsmith.net/2018/website-performance-optimization-infographic/">Website Performance Optimization</a> appeared first on <a rel="nofollow" href="https://wpsmith.net">WP Smith</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><a href="https://www.nccgroup.trust/uk/about-us/resources/website-performance-optimisation-infographic/" rel="noopener" target="_blank"><img loading="lazy" src="https://wpsmith.net/wp-content/uploads/2018/06/website_performance_infographic_800e-768x1024.png" alt="" width="768" height="1024" class="aligncenter size-large wp-image-69943" srcset="https://wpsmith.net/wp-content/uploads/2018/06/website_performance_infographic_800e-768x1024.png 768w, https://wpsmith.net/wp-content/uploads/2018/06/website_performance_infographic_800e-225x300.png 225w, https://wpsmith.net/wp-content/uploads/2018/06/website_performance_infographic_800e.png 800w" sizes="(max-width: 768px) 100vw, 768px" /></a></p>
<p>The post <a rel="nofollow" href="https://wpsmith.net/2018/website-performance-optimization-infographic/">Website Performance Optimization</a> appeared first on <a rel="nofollow" href="https://wpsmith.net">WP Smith</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://wpsmith.net/2018/website-performance-optimization-infographic/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Web Performance Is User Experience</title>
		<link>https://wpsmith.net/2018/web-performance-user-experience/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=web-performance-user-experience</link>
					<comments>https://wpsmith.net/2018/web-performance-user-experience/#respond</comments>
		
		<dc:creator><![CDATA[Travis Smith]]></dc:creator>
		<pubDate>Sat, 02 Jun 2018 13:48:41 +0000</pubDate>
				<category><![CDATA[Infographic]]></category>
		<guid isPermaLink="false">https://wpsmith.net/?p=69939</guid>

					<description><![CDATA[<p>The post <a rel="nofollow" href="https://wpsmith.net/2018/web-performance-user-experience/">Web Performance Is User Experience</a> appeared first on <a rel="nofollow" href="https://wpsmith.net">WP Smith</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><a href="https://www.soasta.com/blog/web-performance-is-user-experience-infographic/" target="_blank" rel="noopener"><img loading="lazy" class="aligncenter size-large wp-image-69940" src="https://wpsmith.net/wp-content/uploads/2018/06/web-performance-is-user-experience-418x1024.png" alt="Web Performance Is User Experience" width="418" height="1024" srcset="https://wpsmith.net/wp-content/uploads/2018/06/web-performance-is-user-experience-418x1024.png 418w, https://wpsmith.net/wp-content/uploads/2018/06/web-performance-is-user-experience-123x300.png 123w, https://wpsmith.net/wp-content/uploads/2018/06/web-performance-is-user-experience-768x1880.png 768w, https://wpsmith.net/wp-content/uploads/2018/06/web-performance-is-user-experience.png 800w" sizes="(max-width: 418px) 100vw, 418px" /></a></p>
<p>The post <a rel="nofollow" href="https://wpsmith.net/2018/web-performance-user-experience/">Web Performance Is User Experience</a> appeared first on <a rel="nofollow" href="https://wpsmith.net">WP Smith</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://wpsmith.net/2018/web-performance-user-experience/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Why WordPress Performance Matters</title>
		<link>https://wpsmith.net/2018/wordpress-performance-matters/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=wordpress-performance-matters</link>
					<comments>https://wpsmith.net/2018/wordpress-performance-matters/#respond</comments>
		
		<dc:creator><![CDATA[Travis Smith]]></dc:creator>
		<pubDate>Fri, 01 Jun 2018 15:48:28 +0000</pubDate>
				<category><![CDATA[Performance]]></category>
		<guid isPermaLink="false">https://wpsmith.net/?p=69924</guid>

					<description><![CDATA[<p>Site performance is extremely important. It affects your SEO, conversions, page views, customer satisfaction, and revenue. This is nothing new since these effects have been proved out since 2012. For example, radware's post on "Mobile Stress" demonstrates that site slowness leads to user frustration and lower engagement directly relating performance to user experience. CresTech published a case [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://wpsmith.net/2018/wordpress-performance-matters/">Why WordPress Performance Matters</a> appeared first on <a rel="nofollow" href="https://wpsmith.net">WP Smith</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Site performance is extremely important. It affects your SEO, <a href="https://wpsmith.net/2018/web-performance-impacts-conversion-rates/" target="_blank" rel="noopener">conversions</a>, page views, customer satisfaction, and revenue. This is nothing new since these effects have been proved out since 2012. For example, <a href="https://blog.radware.com/applicationdelivery/wpo/2013/12/slower-web-pages-user-frustration/" target="_blank" rel="noopener">radware's post on "Mobile Stress"</a> demonstrates that site slowness leads to user frustration and lower engagement directly relating performance to <a href="https://wpsmith.net/2018/web-performance-user-experience/" target="_blank" rel="noopener">user experience</a>. <a href="http://www.crestechglobal.com/wp-content/uploads/2013/10/WhitePaper_AgileBottleneck_Performance.pdf" target="_blank" rel="noopener">CresTech</a> published a case study highlighting the need for performant and highly available infrastructure. In January 2018, on the <a href="https://webmasters.googleblog.com/2018/01/using-page-speed-in-mobile-search.html" target="_blank" rel="noopener">Webmaster Central Blog</a>, Google published that site speed would affect your mobile search ranking beginning in <em><strong>July 2018</strong></em> with their "Speed Update." According to <a href="https://www.thinkwithgoogle.com/marketing-resources/data-measurement/mobile-page-speed-new-industry-benchmarks/" target="_blank" rel="noopener">Think with Google</a>, as your page load time increases, so does your conversion and bounce rate.</p>
<blockquote><p>The neural net, which had a 90% prediction accuracy, found that as page load time goes from one second to 10 seconds, the probability of a mobile site visitor bouncing increases 123%. Similarly, as the number of elements—text, titles, images—on a page goes from 400 to 6,000, the probability of conversion drops 95%.</p></blockquote>
<p>In 2016, <a href="https://docs.google.com/presentation/d/e/2PACX-1vTcI47H-9B7UaygGZWxfhieMcGNY_Z03R0u8fXtwZuSD9-A-fXtK2VTpb5PJEvlmC73OjBK4g1y38he/pub?start=false&amp;loop=false&amp;delayms=3000&amp;slide=id.g2b24c904ac_11_28" target="_blank" rel="noopener">DoubleClick</a> published that 53% of users abandon sites that take longer than 3 seconds to load. Many web developers forget that the majority of world-wide connections are only 2G. Furthermore, consider these reasons to care about your site's performance (published by <a href="https://www.globaldots.com/10-reasons-to-speed-up-your-website/" target="_blank" rel="noopener">GlobalDots</a>):</p>
<ul>
<li>Each second delay results in a direct loss in sales (~<strong>-7%</strong>).</li>
<li>Increased bounce rate, even abandonment for sites <strong>&gt; 6s</strong>.</li>
<li><strong>~80%</strong> of shoppers will never buy again if dissatisfied with site's performance.</li>
<li>Potential customers will use a competitor's site if their site is faster by a mere <strong>250ms</strong>.</li>
<li>Most mobile users expect the sites to load <strong>faster</strong> than the desktop site, if not just as fast.</li>
<li>Faster sites <strong>save money</strong> in hosting costs.</li>
<li>Site changes that slow your site down just <strong>400ms</strong> affect your SEO and appearance in search results.</li>
</ul>
<p>In the Performance Series, we will be investigating various components of how to improve your WordPress site's performance including:</p>
<ul>
<li>Performance KPIs/Measurements</li>
<li>Tools for Measuring Performance</li>
<li>Plugins</li>
<li>Hosting</li>
<li>CDN</li>
</ul>
<p>So stay tuned!</p>
<p>Consider these infographics:</p>
<p>
<img width="598" height="703" src="https://wpsmith.net/wp-content/uploads/2018/06/Conversion-Infographic-Final.png" class="attachment-full size-full" alt="Web Performance Impacts Conversion Rates" loading="lazy" link="none" size="full" columns="2" gallery-classes="masonry" ids="69938,69940,69942,69943" orderby="post__in" include="69938,69940,69942,69943" srcset="https://wpsmith.net/wp-content/uploads/2018/06/Conversion-Infographic-Final.png 598w, https://wpsmith.net/wp-content/uploads/2018/06/Conversion-Infographic-Final-255x300.png 255w" sizes="(max-width: 598px) 100vw, 598px" />
<img width="800" height="1958" src="https://wpsmith.net/wp-content/uploads/2018/06/web-performance-is-user-experience.png" class="attachment-full size-full" alt="Web Performance Is User Experience" loading="lazy" link="none" size="full" columns="2" gallery-classes="masonry" ids="69938,69940,69942,69943" orderby="post__in" include="69938,69940,69942,69943" srcset="https://wpsmith.net/wp-content/uploads/2018/06/web-performance-is-user-experience.png 800w, https://wpsmith.net/wp-content/uploads/2018/06/web-performance-is-user-experience-123x300.png 123w, https://wpsmith.net/wp-content/uploads/2018/06/web-performance-is-user-experience-768x1880.png 768w, https://wpsmith.net/wp-content/uploads/2018/06/web-performance-is-user-experience-418x1024.png 418w" sizes="(max-width: 800px) 100vw, 800px" />
<img width="600" height="4489" src="https://wpsmith.net/wp-content/uploads/2018/06/need-for-speed-infographic.jpg" class="attachment-full size-full" alt="Website Performance: Need for Speed" loading="lazy" link="none" size="full" columns="2" gallery-classes="masonry" ids="69938,69940,69942,69943" orderby="post__in" include="69938,69940,69942,69943" srcset="https://wpsmith.net/wp-content/uploads/2018/06/need-for-speed-infographic.jpg 600w, https://wpsmith.net/wp-content/uploads/2018/06/need-for-speed-infographic-40x300.jpg 40w, https://wpsmith.net/wp-content/uploads/2018/06/need-for-speed-infographic-137x1024.jpg 137w" sizes="(max-width: 600px) 100vw, 600px" />
<img width="800" height="1066" src="https://wpsmith.net/wp-content/uploads/2018/06/website_performance_infographic_800e.png" class="attachment-full size-full" alt="" loading="lazy" link="none" size="full" columns="2" gallery-classes="masonry" ids="69938,69940,69942,69943" orderby="post__in" include="69938,69940,69942,69943" srcset="https://wpsmith.net/wp-content/uploads/2018/06/website_performance_infographic_800e.png 800w, https://wpsmith.net/wp-content/uploads/2018/06/website_performance_infographic_800e-225x300.png 225w, https://wpsmith.net/wp-content/uploads/2018/06/website_performance_infographic_800e-768x1024.png 768w" sizes="(max-width: 800px) 100vw, 800px" />
</p>
<p>The post <a rel="nofollow" href="https://wpsmith.net/2018/wordpress-performance-matters/">Why WordPress Performance Matters</a> appeared first on <a rel="nofollow" href="https://wpsmith.net">WP Smith</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://wpsmith.net/2018/wordpress-performance-matters/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Web Performance Impacts Conversion Rates</title>
		<link>https://wpsmith.net/2018/web-performance-impacts-conversion-rates/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=web-performance-impacts-conversion-rates</link>
					<comments>https://wpsmith.net/2018/web-performance-impacts-conversion-rates/#respond</comments>
		
		<dc:creator><![CDATA[Travis Smith]]></dc:creator>
		<pubDate>Fri, 01 Jun 2018 13:45:44 +0000</pubDate>
				<category><![CDATA[Infographic]]></category>
		<guid isPermaLink="false">https://wpsmith.net/?p=69937</guid>

					<description><![CDATA[<p>The post <a rel="nofollow" href="https://wpsmith.net/2018/web-performance-impacts-conversion-rates/">Web Performance Impacts Conversion Rates</a> appeared first on <a rel="nofollow" href="https://wpsmith.net">WP Smith</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><a href="https://loadstorm.com/2014/04/infographic-web-performance-impacts-conversion-rates/" rel="noopener" target="_blank"><img loading="lazy" class="aligncenter size-full wp-image-69938" src="https://wpsmith.net/wp-content/uploads/2018/06/Conversion-Infographic-Final.png" alt="Web Performance Impacts Conversion Rates" width="598" height="703" srcset="https://wpsmith.net/wp-content/uploads/2018/06/Conversion-Infographic-Final.png 598w, https://wpsmith.net/wp-content/uploads/2018/06/Conversion-Infographic-Final-255x300.png 255w" sizes="(max-width: 598px) 100vw, 598px" /></a></p>
<p>The post <a rel="nofollow" href="https://wpsmith.net/2018/web-performance-impacts-conversion-rates/">Web Performance Impacts Conversion Rates</a> appeared first on <a rel="nofollow" href="https://wpsmith.net">WP Smith</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://wpsmith.net/2018/web-performance-impacts-conversion-rates/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
