Asynchronous publishing actions on VIP Go

Often when a post is published, there’s a number of actions associated with that publication. Some of those actions can take a while to perform, for example syndicating content out to sibling sites, pushing to social media, etc.

On VIP Go you can easily offload actions to be processed asynchronously on the Cron infrastructure for your site when a post is published or transitions status. Offloading actions reduces the processing time required for your publish action, which makes for a much faster and nicer publishing experience for your editors.

How to offload actions

Offloading an action on publish for asynchronous processing is as simple as changing the publish action hook to one of our async_ equivalents. The hooks we have available for asynchronous processing are:

  • async_transition_post_status, the asynchronous equivalent of transition_post_status (core hook docs)
  • async_{$old_status}_to_{$new_status}, the asynchronous equivalent of {$old_status}_to_{$new_status} (core hook docs)
  • async_{$new_status}_{$post->post_type}, the asynchronous equivalent of {$new_status}_{$post->post_type} (core hook docs)

This hypothetical code example splits off some functionality to be processed as the post is published, and some longer running functionality to be processed asynchronously:

 * Runs when a post of type `post` is published.
function my_post_publish_actions() {
	// This function performs quick actions,
	// and things which must happen immediately
add_action( 'publish_post', 'my_post_publish_actions' );

 * Runs asynchronously, when a post of type `post` is published.
function my_slower_post_publish_actions() {
	// This function performs slower actions,
	// like syndication and other longer 
	// running tasks
add_action( 'async_publish_post', 'my_slower_post_publish_actions' );

The code which powers our asynchronous offloading functionality works by scheduling an immediate Cron event to be processed on our dedicated Cron infrastructure, during which these async_* action hooks are called.


The asynchronous actions will be processed on separate infrastructure to the web requests; this means that the asynchronous action will not have access to anything which has been placed in the global context, or access files placed in the System temp directory, etc.

Setting Up the Ads.txt File

What is ads.txt?

It’s an IAB-approved text file to prevent unauthorized sales of inventory.  You can read more about it on their website:

Setting It Up

Since requirements specify that the /ads.txt file must be located in the root domain, we highly recommend to place the ads.txt file in your theme and then, create a rewrite rule for the URL. Here is an example for VIP platform:

// TODO: change `my_theme` prefix to my theme's prefix!
 * Register the rewrite rule for /ads.txt request.
function my_theme_adstxt_rewrite() {
	add_rewrite_rule( '^ads\.txt$', 'index.php?my_theme_adstxt=true', 'top' );
add_action( 'init', 'my_theme_adstxt_rewrite', 10 );

 * Filter the list of public query vars in order to allow the WP::parse_request
 * to register the query variable.
 * @param array $public_query_vars The array of whitelisted query variables.
 * @return array
function my_theme_adstxt_query_var( $public_query_vars ) {
	$public_query_vars[] = 'my_theme_adstxt';
	return $public_query_vars;
add_filter( 'query_vars', 'my_theme_adstxt_query_var', 10, 1 );

 * Hook the parse_request action and serve the ads.txt when custom query variable is set to 'true'.
 * @param WP $wp Current WordPress environment instance
function my_theme_adstxt_request( $wp ) {
	if ( isset( $wp->query_vars['my_theme_adstxt'] ) && 'true' === $wp->query_vars['my_theme_adstxt'] ) {
		 * Set proper content-type per specification in
		 * :
		 * The HTTP Content-type should be ‘text/plain’, and all other Content-types should be treated
		 * as an error and the content ignored.
		header( 'Content-Type: text/plain' );

		// The code expects an existing ads.txt file in the root of your active theme.
		echo file_get_contents( get_stylesheet_directory() . '/ads.txt' );
add_action( 'parse_request', 'my_theme_adstxt_request', 10, 1 );

On, there should be no need to flush your rewrite rules, as it happens automatically upon deploy. For VIP Go, and in cases where the redirect does not working as expected, please head to VIP => Rewrite Rules and hit the “Flush Rewrite Rules” button.

Note: this is just one way to go about doing so; if there is another way that works better for your theme, feel free to employ it!

If you’d like to be able to modify and validate your ads.txt file from the admin interface, the Ads.txt Manager plugin from VIP Featured Partner 10up allows you to do so, and is approved for use on both VIP and VIP Go.

Notices about PHP errors and warnings

PHP errors can be indicative of problems with theme functionality, security or performance and should be fixed to ensure everything on the site is working as expected. By reducing PHP errors on your site, you are:

  1. Making it easier to spot bugs on your site
  2. Creating a more defensive codebase
  3. Ensuring it’s easier for us to debug your site if there’s a problem
  4. Reducing the risk of your site breaking unintentionally

If you are not sure what to do about the errors on your site, please check with your development team as they should be able to assist in resolving them.

If you have SVN write access to a VIP repository, you may receive an email indicating there are PHP errors or warnings that need to be fixed:


This email is sent out when our system detects that your site has produced more than 100 errors in the last 24 hours.

If you are an Administrator on a VIP site, you may see a notice indicating there are PHP errors or warnings that need to be fixed:

Screen Shot 2016-03-25 at 16.37.35

This notice appears when our system detects that the site in question has generated over 100 errors and/or warnings in the PHP error logs associated with the site.

Administrators can view more information about the PHP errors by visiting the VIP Dashboard and scrolling down to view the widget titled “PHP Errors and Warnings from the last 24h.” It might look something like this:

Screen Shot 2016-03-25 at 16.42.13

This widget was made available in January 2016.

If you still have any questions, please open a support ticket.

Accommodating the toolbar in your layout

The toolbar will appear for all users logged into Here’s how to conditionally adapt your page layout based on its presence/absence.

* make use of body_class, typically, in your header.php’s HTML body tag
* provide 25px of margin-top for cases where the admin bar is present

Disabling unused features and assets comes with a bunch of useful features turned on by default, and most VIP sites make use of them every day. We also know that sites may want to disable some of these for various reasons, e.g. if you’re focused on performance and minimizing the number of assets loaded, you may want to disable any CSS/JS that would be loaded for features not in use.

We offer a number of helper functions to facilitate this:

  • wpcom_vip_disable_custom_customizer – disables the Customizer and Custom Design
  • wpcom_vip_disable_devicepx_js – devicepx.js loads retina/HiDPI versions of certain files (Gravatars, etc) for devices that run at a higher resolution (such as smartphones). Using this function disables it.
  • wpcom_vip_disable_global_terms – remove your taxonomy from the global taxonomy array
  • wpcom_vip_disable_hovercards – if you are not using Gravatars and Blavatars and need to disable the loading of related Javascript and CSS resources
  • wpcom_vip_disable_likes – disables Likes for Posts and Custom Post Types. Sharing can also be disabled from the Dashboard (Settings > Sharing).
  • wpcom_vip_remove_opensearch – disables rendering of the OpenSearch description documents at /osd.xml and /opensearch.xml
  • wpcom_vip_disable_sharing – disables Sharing in Posts and Pages
  • wpcom_vip_disable_sharing_resources – disables the CSS/JS involved in Sharing functions, powering things like smart buttons and share counts displayed alongside the buttons.
  • wpcom_vip_remove_playlist_styles – disables enqueuing of wp-mediaelement.css which is necessary for sites using Playlist shortcode
  • wpcom_vip_remove_mp6_styles – disables enqueuing f mp6-hacks.css stylesheet which adds backward compatibility for legacy .mp6 body classes
  • wpcom_vip_load_geolocation_styles_only_when_needed – Conditionally dequeues Geo Location stylesheets in case they are not needed. IE.: post is not actually using Geo Location
  • wpcom_vip_remove_bbpress2_staff_css – disables enqueueing of wpcom-bbpress-premium-themes.css stylesheet

Check out all of the helper functions available.

Detecting the production environment

If you want to detect whether or not your theme is running in the production environment, you can use logic like this:

if ( defined( 'WPCOM_IS_VIP_ENV' ) && true === WPCOM_IS_VIP_ENV ) {
    // Running on
} else {
    // Not running on

This can be helpful for setting other environment variables that are specific to the hostname or environment where the code is executed. However, we strongly advise against any logic that makes functionality exceptions for your development environment; development and production environments should be as close as possible to avoid unexpected production-specific issues.

Rolling Back / Reverting Changes to Your Theme Using Subversion

You can access your theme repository version history and, when necessary, quickly roll back your deployed theme to a previous state.

The Time Machine

Every time you commit a change to your theme to your VIP theme repository, Subversion remembers by creating a version. Each of these versions is assigned a unique number and certain other meta, namely: the username of the person who made the version, the date and time of the version, the number of lines of code changed in the version relative to the previous one and a commit message indicating the nature of the changes in the version.

You can inspect your theme’s version history on the command line using the svn log command (documentation: clitortoiseSVN.) Here’s some sample svn log output for Automattic’s test theme on VIP:

vip/test-theme$ svn log .
r69251 | viper007bond | 2012-06-20 21:09:52 +0000 (Wed, 20 Jun 2012) | 1 line

Remove testing code
r69209 | batmoo | 2012-06-20 13:59:49 +0000 (Wed, 20 Jun 2012) | 2 lines

auto-deploy: rm image in a subfolder
r69197 | batmoo | 2012-06-20 13:40:55 +0000 (Wed, 20 Jun 2012) | 2 lines

Auto-deploy: testing a php + css commit
r66930 | tottdev | 2012-05-27 11:19:52 +0000 (Sun, 27 May 2012) | 1 line

reverting error code

To inspect a commit in more detail (such as seeing the changes it introduced), svn provides the svn diff command (docs: clitortoiseSVN.) Here’s an example:

vip/test-theme$ svn diff -c 17546 .

Index: header.php
--- header.php	(revision 17545)
+++ header.php	(revision 17546)
@@ -6,7 +6,6 @@
-<meta name="generator" content="WordPress "/> 
 <link rel="stylesheet" href="?2" type="text/css" media="screen" />

The -c flag shows a change set resulting from a single revision, but there are many other options including -r n:m (show differences between revision n and m) and more — see the svn diff documentation for full details.


If you need to roll back code you’ve committed it to the deploy queue, the quickest way to do this is to revert and commit the code yourself. Here’s how to prepare and push a roll-back:

1. Update your theme’s working copy to the latest revision (use

svn up your-theme

or tortoiseSVN.)

2. Use svn log to find out how far you’d like to roll back. Suppose your log reveals something like:

r4 -- change paint color
r3 -- introduce clunk engine
r2 -- modify blee tag
r1 -- add snorkle

3. Use svn merge to roll back the code to the revision before things went ‘wrong.’ For example, a typical cli command for this would be:

vip/my-theme$ svn merge -c -4 -c -3 .

This “un-does” the commits with version numbers 3 and 4, and rolls the code back to its previous state as of revision 2. As with svn diff, the merge command admits lots of different syntax combinations. You can read about some of those here and here. You can also roll back easily using clients like tortoiseSVN.

4. The merge you just performed has produced a changeset in your working copy. Commit your roll-back like any other change using svn commit.

Make sure that you include an explanatory commit message such as “roll-back of r3 and r4 due to JS error”. Your message should indicate which versions are being rolled back, and for what reason. This will help VIP deploy engineers quickly deploy your changeset.

Pure roll-backs usually require little or no review, and can be deployed almost immediately, so make sure your change only contains the roll-back, and nothing else.

In an emergency situation, you can open an urgent ticket requesting a deploy of your roll-back. Generally this is not necessary, however, and we request that you reserve urgent tickets for when your site is down or for other serious end-user issues.

Best practices:

1. Think in terms of “rolling back” code instead of reverting individual commits. It’s possible to revert things out of sequence. For instance in the previous example we could have reverted r3 but not r4. However, to do so ignores the possibility that something in r4 may depend on something in r3. In almost all cases, it’s safer to roll back all commits in sequence, especially if doing so quickly.

2. Data dependencies. Before a major roll-back it’s good to take a second to consider whether the underlying data has changed in a way that would cause problems with the old code. Have the content or options been modified in any way, including by CLI scripts? This is not usually an issue, but can be in certain cases.

3. Confusingly, subversion also features a command called svn revert whose purpose is not to take your code to a previous state, but only to un-do local un-committed modifications. Therefore we use the term “revert” both in the sense of “roll-back” and the sense of svn revert.

4. Finally, There is an extremely large number of Subversion clients which make all of this very easy. Cornerstone is a great (though somewhat expensive) client for OSX.

Switching Themes on a VIP Site

This document is for VIP customers who:

  • Have an existing VIP site
  • Would like to enable a new theme on their existing site

Why not create a brand new site?
We strongly advise against creating an entirely new VIP instance because this will require a time intensive content migration. Creating a new instance requires exporting content from the old site, adding users to the new site, and then importing content. The quickest path for a redesign is to enable a new theme on the existing site.

1. Kick Off Call

Submit a ticket outlining the important elements of the theme redesign. Please include the following:

  • Scope of the redesign
  • Any major refactoring of the base code
  • New plugins
  • Content manipulation
  • Timeline

Once we receive the ticket, we’ll set up a kickoff call with your team.

2. Get your theme reviewed
If your redesign is mostly frontend or template changes, we strongly recommend the iterative model, where you commit changes through our deploy queue. If this is an entirely new theme, you will need to go through our Theme Review process.

Once the review is complete, your theme will be moved to production and available on your site under Appearance > Themes.

3. Content manipulation
Should your new theme require content manipulation (i.e. taxonomy or custom post type changes), you will most likely need to run scripts to modify the content.

Before running these scripts on a production site, we will set up a pre-production site for you to thoroughly QA the scripts. Once you’ve approved the resulting content, we’ll help you run it on your production site.

In addition to submitting the scripts for review, please also submit the order in which they are supposed to be run.

You could also consider providing starter content within your new WordPress theme, which will help you to set up widgets, content and menus as part of the activation process.

4. Staging

We strongly recommend staging your site using one of our recommended local environments.

5. Maintenance Mode

Should you need to put your site into maintenance mode while switching themes, you can use our Maintenance Mode plugin. When it’s enabled, no public visitors can access your site. Please be sure to test the plugin before launch day.

** Preserving Widgets: Typically, widgets are not preserved at theme switch. It’s best to export options, switch theme, and re-import them.

6. Launch!

Please provide us the time and date of the launch, so that we can schedule VIP developers to be around for any support that’s needed. We will spin up a Stormchat and share that with you to communicate in real-time.

Sending Useful Problem Reports

Got a bug to report? We know that our VIP clients` time is valuable, and we want to make sure we help you get the most efficient results out of our support communications as we work together.

As a starting point for creating a useful problem report ticket, we recommend starting with this template:

URL(s) where the issue is occurring:

What I expected to happen:

What actually happened:

Steps to reproduce the issue:

When it started and how long it's been going on:

Environment Info (browser and version, OS and version, device type):

Troubleshooting we've already tried:

Other details or notes that might be helpful:

As we work to troubleshoot your issue there are a variety of things we might ask you about, listed below. If you’re able to provide any of this information up front, that will help us get to the bottom of the issue faster!

  • Is it already an issue we know about, as posted on our status page or in the VIP Lobby?
  • Has your company already opened a ticket open about the same issue that you can add to, instead of opening a new ticket? Having a single ticket to coordinate on helps us stay focused on your issue.
  • Is the issue specific to a certain user, browser, or device? Or does it happen for all users, across multiple browsers, or on multiple devices? Does it happen all the time regardless of being logged in or logged out?
  • Is the issue reproducible? Can you make the same behavior happen over and over again consistently, or does it only happen once in a while?
  • Does the same thing happen in your development environment as in production on or VIP Go? If so, is your development team able to change the behavior or view error log messages that help explain the issue?
  • When did the issue start? Is it related to a particular change in your site’s theme, a configuration change you made, or any announced updates to the or VIP Go platform? Having specific dates and times of when the issue occurred is very helpful!
  • Do you have specific examples of the issue you can send us a link to? The more the better.
  • Are there any specific error or warning messages related to the issue that you can include in your report?
  • Screenshots or recordings are appreciated – It can be difficult or time consuming to type out all of the things you’re seeing on the screen with your issue, so if the problem can be captured in a screenshot or in a recording of your screen activity, please send it along!
  • What’s the impact and urgency of the issue for you? While this may not directly affect our ability to find a solution, it can be helpful to know for our own planning and communication purposes.
  • If there’s a third party involved (e.g. your site is pulling information from or sending information to a third party service), have you checked with them to see if they’re having any issues that could be related?

We know that each problem will be different and that not all of the above will apply in every case. But, the more information you can send us in your ticket, the faster we can help!

Here’s an idealized example of a problem report that provides much of the information above:

As of 3 PM Eastern today the user “username” seems to have lost access to the dashboard screen for managing the AcmeWidgets plugin that we’re using on our site. When they try to visit they get a permissions error message, “You do not have sufficient permissions to access this page.” I’m attaching a screenshot of the error.

The user is using Google Chrome 36.0.1985.125 on Mac OS X 10.9.4, and it looks like she gets the same error when trying this on multiple computers in our office. It happens every time. Other users in our office are able to get to that management page without a problem, for example user “username2” was able to get in fine just now.

We tried to replicate this issue in our local development environment, but the test user we created could get to that page just fine. We checked your status page and lobby blog and it doesn’t look like you’re having any general issues right now.

We need to get this figured out by the end of the week, as the user needs to perform a bunch of related tasks in that plugin for a series we’re doing next week.


Related Posts

You can take advantage of the Related Posts functionality to return related posts quickly. Enable it by turning on Related Posts in Settings > Reading and you’re done!

If you’d like to programmatically retrieve and display posts within your theme code, you can do so like this:

$posts = Jetpack_RelatedPosts::init_raw()->get_for_post_id( $post_id, $args );

// Returns an associative array in the form of id => $post_id:
    array ('id' => 12345),
    array ('id' => 54321),

Related Posts indexing will work regardless of whether your site is marked as “Private.” For self-hosted sites, Related Posts will currently only work for standard post-types; we are working on enabling it for custom post types.

For more information about ways to customize related posts, see

Ready to get started?

Drop us a note.

No matter where you are in the planning process, we’re happy to help, and we’re actual humans here on the other side of the form. 👋 We’re here to discuss your challenges and plans, evaluate your existing resources or a potential partner, or even make some initial recommendations. And, of course, we’re here to help any time you’re in the market for some robust WordPress awesomeness.