Simple Customizations For the WPCloudDeploy Frontend

So, you’re building a SaaS on WordPress and you want your user to be able to see some elements of the WPCloudDeploy front-end for each of their instances.

By default, what your users will see is something similar to this:

So maybe you want to do this:

and then move some elements around similar to where these arrows are pointing:

Let’s jump in and see how you might be able achieve this:

Step 1: Get Rid of The Columns

First, let’s get rid of the extra columns. This is the easiest part:

  • Navigate to WPCloudDeploy → Settings → APP: WordPress – Settings → Frond-end Fields
  • Scroll down to the Sites – Hide Cards section
  • Check the boxes for Hide App Summary and Hide App Features
  • Scroll down and click the Save Settings button.

Now you should have only one column on your screen.

Add New Elements To Remaining Card

To add new data to the remaining column, you’ll need to write some custom code. Assuming you already have a custom plugin for your tenant sites and that it uses a class, you would need to hook into the wpcd_public_wpcd_app_table_after_row_actions_for_title action.

add_filter( 'wpcd_public_wpcd_app_table_after_row_actions_for_title', array( $this, 'app_admin_list_show_links_after_title_site' ), 8, 3 );

Notice the use of array() in the second parameter – this is necessary if you’re using a class. If not, you can use something like this instead:

add_filter( 'wpcd_public_wpcd_app_table_after_row_actions_for_title', 'app_admin_list_show_links_after_title_site', 8, 3 );

The actual code that goes into the app_admin_list_show_links_after_title_site function is this:

 * Show some links under the title column on the front-end sites list.
 * Action Hook: wpcd_public_wpcd_app_table_after_row_actions_for_title
 * @param array   $item Post details.
 * @param string  $column_name This should always be "title".
 * @param boolean $primary Is this is the primary column.
 * @return void Data is echoed to the screen.
public function app_admin_list_show_links_after_title_site( $item, $column_name, $primary ) {

	// We're only showing data on the front-end so if in wp-admin, bail out.
	if ( wpcd_is_admin() ) {

	$post_id = $item->ID;

	$view_link  = '';
	$admin_link = '';

	if ( ! empty( $post_id ) ) {

		if ( 'wpcd_app' === $item->post_type ) {
			// Check to see if we have a wc product id on the app post.
			if ( ! empty( $post_id ) ) {

				// Get WC product id.
				$product_id = get_post_meta( $post_id, 'wpapp_wc_product_id', true );

				if ( ! empty( $product_id ) ) {

					// Is the product a wc sites product?
					$is_a_site_product = WPCD()->classes['wpcd_app_wordpress_sell_wc_site_subs']->is_product_type( $product_id, 'wpapp_sites' );

					if ( true === $is_a_site_product ) {
						$view_link = WPCD_WORDPRESS_APP()->get_formatted_site_link( $post_id, __( 'View', 'wpcd' ) );
						// $admin_link = WPCD_WORDPRESS_APP()->get_formatted_public_admin_link( $post_id, __( 'Manage', 'wpcd' ) );
						$admin_link = WPCD_WORDPRESS_APP()->get_formatted_wpadmin_link( $post_id, __( 'Manage', 'wpcd' ) );

						// Get Domain Data.
						$domain_link  = __( 'Domain: ', 'wpcd' );
						$data         = get_post_meta( $post_id, 'wpapp_domain', true );
						$domain_link  = WPCD_POSTS_APP()->wpcd_column_wrap_string_with_span_and_class( $domain_link, 'domain', 'left' );
						$domain_link .= WPCD_POSTS_APP()->wpcd_column_wrap_string_with_span_and_class( wpcd_wrap_clipboard_copy( $data ), 'domain', 'right' );
						$domain_link  = WPCD_POSTS_APP()->wpcd_column_wrap_string_with_div_and_class( $domain_link, 'domain' );

						// Get User Data.
						$user_link  = __( 'User: ', 'wpcd' );
						$data       = get_post_meta( $post_id, 'wpapp_user', true );
						$user_link  = WPCD_POSTS_APP()->wpcd_column_wrap_string_with_span_and_class( $user_link, 'wp_login_user', 'left' );
						$user_link .= WPCD_POSTS_APP()->wpcd_column_wrap_string_with_span_and_class( wpcd_wrap_clipboard_copy( $data, false ), 'wp_login_user', 'right' );
						$user_link  = WPCD_POSTS_APP()->wpcd_column_wrap_string_with_div_and_class( $user_link, 'wp_login_user' );


		// If we have an admin link then add it to the bottom.
		$links = '';
		if ( ! empty( $admin_link ) ) {
			$admin_link = WPCD_POSTS_APP()->wpcd_column_wrap_string_with_span_and_class( $admin_link, 'wp_admin_link', 'left' );

		// If we have a view link then add it to the bottom.
		if ( ! empty( $view_link ) ) {
			$view_link = WPCD_POSTS_APP()->wpcd_column_wrap_string_with_span_and_class( $view_link, 'homepage_link', 'right' );
			$links     = WPCD_POSTS_APP()->wpcd_column_wrap_string_with_div_and_class( $admin_link . $view_link, 'site_links' );

		if ( ! empty( $links ) ) {
			echo '<hr />';
			echo wp_kses_post( $links );

		if ( ! empty( $user_link ) ) {
			echo '<hr />';
			echo wp_kses_post( $user_link );
			echo wp_kses_post( $domain_link );



So, that looks like a lot of code – but it’s not as bad as it looks. Let’s break it down a bit so you can understand what’s going on there. (You might want to copy the code into a code editor so that it doesn’t line-wrap while you’re reading it.)

The first 11 lines are simply comments. They describe the function, the hook it’s using and the function parameters. (You’ll see this type of function header a lot when you work with WordPress code.) The function parameters is what WordPress and WPCD declared will be passed in when the wpcd_public_wpcd_app_table_after_row_actions_for_title hook was set in the core code.

Then, the code is doing the following:

  • Check to make sure it’s not in the admin area (i.e.: we’re on the front-end). If not, the code exits.
  • Check to make sure that there is a post id available. If not, exit.
  • If a post id is available, make sure that it’s for a post type that we’re interested in – i.e.: the post type that stores data about WPCD sites. If not, exit.
  • IF all those checks passes, we grab the product id from the site record – if one isn’t present for some reason, you guessed it – just exit.
  • If a WooCommerce product id is present it will check to see if it is one that is a “sites” product. If not, it, again, exits.
  • At this point, all basic validation checks have passed. So after all that we’re using WPCD built-in functions to get the links to the front-end and admin areas.
  • Then we’re grabbing some more data out of the site record and constructing html that wraps that data.
  • Finally we output the data.

So, more than half the code is comments and validation checks to make sure we’re working with data that makes sense. (This is “defensive coding” 101 and goes along with the philosophy of assuming that “if it can go wrong it probably will at some point.” So it’s best to do basic sanity checks on the data you’re working with before using it.)

Note: It’s also possible that, instead of using nested-ifs, the code can be refactored to do more checks at the top of the function before proceeding. That is just as valid an option – it’s a matter of style preferences for a developer.

So, after all that, what do we have?

Great – the data is there and it doesn’t look half bad.


But, really, since most users will have only one subscription, there’s no need for the large horizontal gray background. Let’s remove it and add a background color to the column only.

To do that, add the following CSS to your theme or plugin (wherever custom CSS is enqueued for your front-end):

/* Background color on each row - remove which should make it match current background. */
.wpcd-grid-table-rows .wpcd-grid-table-row {
	/* Each table row */
	background-color: inherit !important;

/* Background color on each cell - make grayish. */
.wpcd-grid-table-cell {
	background-color: #F1F5F9 !important;

Applying this CSS results in:

If you broaden this image to view it in the context of other things that might appear on the screen, it will look like this:


Dropping columns in the WPCloudDeploy front-end is relatively easy – just a few clicks in settings. But moving elements around so that they appear on other cards require a bit of code.

Once you figure out the pattern, you’ll be able to add just about any element you like that is stored in the WPCD custom post types for the site (and/or related server) to the card.

Was This Article Useful? Or do you have questions or comments about it (or our products & services)? We'd love to hear from you!

Please enter your name.
Please enter a message.
You must accept the Terms and Conditions.
Please check the captcha to verify you are not a robot.

Automatic Notification Of New Articles

Sign up to get automatic notifications of new articles.  This is a different list than our standard list - you only get new articles once a week (usually on Mondays).  No other emails will be sent unless you sign up for our general list as well.

Posted in