Create WordPress Demo Site with Multisite

Create WordPress Demo Site with Multisite - Featured image
Cristian Antohe
Last Updated: 22/01/24

Creating a WordPress demo site with Multisite is a quick way to let your potential customers try out your WordPress theme, widget, or plugin in a true-to-life environment, all while benefiting your SEO.

Setting up a demo site for WordPress plugins and widgets or WordPress themes can be as simple as installing WordPress and giving everyone a demo account. You could also set different theme options for a specific experience. This, however, has several drawbacks:

  • anyone can overwrite what the other testers did and this will lead to a messy demo site;
  • you can limit what the demo account can do, crippling the effectiveness of the demo content;
  • you have to reset/clean the demo site every few weeks;
  • you lose some of the SEO you’ve built up;
  • your contact form could start receiving more spam.

Alternatively, you could use a plugin like Ninja Demo, however, we decided not to approach the subject this way. Not due to the price (~ $200), but simply because we figured out this can be a really fun project to play with.

With WordPress Multisite you can let users modify, delete or upload on your demo without interacting with other demo accounts by simply allowing your users to create a brand new demo site and demo content through your e-commerce WordPress site. They can even create new pages through the page builder and update theme options with the customizer.

In this tutorial we’ll go through:

To see the finished product, just check out Profile Builder or Paid Member Subscriptions demo site. You’ll get a new WordPress demo site where you can make any changes as an administrator, like updating styles in the customizer. You can also log out and test Profile Builder’s features and widgets as a subscriber or as a non-logged in user.

Creating a Demo Subdomain to the Main Domain

Since this is fairly dependent on the hosting you currently have, I’m not going into much detail here. Basically, for cPanel users it should be something like this:

  • Open cPanel and create a new sub-domain;
  • Give it the name ‘demo’;
  • Create a database and a database user;
  • Update the DNS to demo.yoursitename.com.

Installing WordPress Multisite

The Multisite Network feature comes with each WordPress installation. All you need to do is install and set up WordPress like you normally would and then enable Multisite.

To enable the Network Setup menu item, you must first define Multisite in the wp-config.php file.

1
2
/* MultiSite */
define( 'WP_ALLOW_MULTISITE', true );

After that, you will be able to create a Network out of your WordPress Install. Check out the Codex Network Documentation for more info regarding this.

Setting up Available Plugins, Widgets, and WordPress Theme Options

For our Profile Builder Demo, besides the plugin, we also installed all available add-ons (since users won’t be able to install plugins, like WooCommerce or certain contact forms, even though they are administrators in the demo e-commerce sites), as well as other plugins that Profile Builder is compatible with, like WooCommerce or Paid Member Subscriptions. You can also make changes to the styles through the customizer.

Except for Profile Builder, these plugins won’t be activated by default, however, the WordPress demo site users will be able to choose what features they want to use in a true-to-life environment with demo content which helps increase your SEO. This is really helpful when users want to create new pages with the page builder and they want to use certain shortcodes, like with compatible contact forms.

Profile Builder Pro Add-ons

Replacing the WordPress Sign-up with a “Create Demo” Button

The default WordPress Multisite sign-up functionality is a bit too “safe” for our demo e-commerce site. Basically, you have to:

  • Enter a username and email;
  • Enter the site title you want and choose if you want it to be indexable by search engines;
  • Get a notification email with the confirmation link;
  • Finally, be able to login into the newly created WordPress Demo Site.

While the above makes perfect sense in the general context of WordPress Multisite, it’s just not good enough for a WordPress demo site. It’s also more difficult for users who are on mobile devices. So we want to replace all of that with a simple “Create Demo” button.

Replacing the WordPress signup form with a “Create Demo” button

The “Create Demo Sub-Sites” Plugin

If you don’t want to go through all the hassle of creating a custom plugin and copy-pasting the code, then simply download the plugin by clicking the button below and install it site-wide.

Download Create Demo Sub-Sites

You can then add the [cds_register] shortcode in your main network site through a page builder which helps your SEO by keeping all of your demo content fast. You can update the styling in the customizer.

Breakdown of the Code

The plugin contains three main parts:

  • The register shortcode where we create the new user and subsite;
  • The automatic login of the user in the new website;
  • The math-CAPTCHA library and a few small functions to glue it all together.

Code for the “Create Demo Site” shortcode

The main functions we’re relying on here are the wpmu_create_user and wpmu_create_blog, which are specific WordPress Multisite functions.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// Add a Simple Math CAPTCHA
include_once('MathCaptcha.php');
 
// Need sessions for the Math CAPTCHA
add_action('init', 'cds_start_session');
function cds_start_session(){
	session_start();
}
 
// Create the shortcode that will output the Create Demo button.
add_shortcode('cds_register', 'cds_register');
function cds_register(){
 
	$cpa = new MathCaptcha();
	if(( 'POST' == $_SERVER['REQUEST_METHOD'] ) && ( $_POST['cbs_action'] == 'cbs_demo' )){
		$captcha_val = $_REQUEST['captcha'];
 
		if( ! $cpa->validate($captcha_val) ){
			return '
Incorect Captcha. Please try again. You will be redirected in 3 seconds
 
'; } // MultiSite domain $main_site = DOMAIN_CURRENT_SITE; do { $rand = 'demo' . cbs_rand_string(); if( is_subdomain_install() ) { $newdomain = "{$rand}.$main_site"; $path = '/'; } else { $newdomain = $main_site; $path = PATH_CURRENT_SITE . "{$rand}/"; } } while( username_exists($rand) && domain_exists($newdomain, $path) ); // Create the new user $username = $rand ; $email = $rand . '@mailinator.com'; $password = 'demo'; $user_id = wpmu_create_user( $username, $password, $email ); if( is_wp_error( $user_id ) ){ return '
 
The new demo account could not be created. Please try again. (You will be redirected in 5 seconds)
 
'; } // Create the new sub-site $title = 'Demo'; $blog_id = wpmu_create_blog( $newdomain, $path, $title, $user_id , array( 'public' => 1 ) ); if( is_wp_error( $blog_id ) ){ return '
 
The new demo account could not be created. Please try again. (You will be redirected in 5 seconds)
 
'; } $location = get_site_url( $blog_id ); $nonce = wp_create_nonce( 'cds_autologin-'.$user_id.'-'.(int)( time() / 60 ) ); $location .= "/?cds_autologin=true&amp;uid=$user_id&amp;_wpnonce=$nonce"; return "<script> window.location.replace('$location'); </script>"; } else { $cpa-&gt;reset_captcha(); ob_start(); ?&gt;

What we’re doing here is:

  • Check to see if the button has been clicked ($_POST[‘cbs_action’] exists and it’s cbs_demo);
  • Randomly generate the username and the domain name by verifying again and again until we find a pair that doesn’t exist in our install;
  • Create the username. The email of the demo admin account is a mailinator.com account so it’s easy to test emails sent by the WordPress website;
  • Create the WordPress demo e-commerce site;
  • If everything is successful (the CAPTCHA is correct and we could create both the user and the domain), redirect the user to the newly created demo WordPress website. Here we’re constructing a nonce that’s based on the new user ID and contains the current UNIX time in minutes.

Finally, we can now hide a few menu items like the My Sites admin bar link, the tools, or the comment pages in the backend if they won’t be needed for your WordPress demo site.

For this, we used the free Menus plugin. It simply adds a list of menus you can show/hide for all sub-sites, as simple as that.

Code for automatic user login

We’re doing this by using the wp_set_auth_cookie that takes as a parameter the user ID we’re sending in the $_GET request as a parameter.

Now, we don’t want to let everyone log in just by adding ?$uid=2134 in the URL, so we’re relying on the nonce setup after a successful user and demo content creation.

1
2
3
4
if ( ! ( wp_verify_nonce( $nonce , 'cds_autologin-'.$uid.'-'.(int)( time() / 60 ) ) || wp_verify_nonce( $nonce , 'cds_autologin-'.$uid.'-'.(int)( time() / 60 ) - 1 ) ) ){
	wp_redirect( $current_page_url );
	exit;
}

Basically, if there’s been more than 1 minute since the initial nonce creation in the shortcode, we’re not logging in the user. Since nonces are unique, it’s practically impossible for somebody else to randomly login to the site, even on mobile devices.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/*
 * Setup Autologin after creation of demo site
 */
 
/* Set action for automatic login after registration */
add_action( 'init', 'cds_autologin_after_creation' );
function cds_autologin_after_creation(){
	if( isset( $_GET['cds_autologin'] ) &amp;&amp; isset( $_GET['uid'] ) ){
		$uid = $_GET['uid'];
		$nonce  = $_REQUEST['_wpnonce'];
 
		$arr_params = array( 'cds_autologin', 'uid', '_wpnonce' );
		$current_page_url = remove_query_arg( $arr_params, cds_curpageurl() );
 
		if ( ! ( wp_verify_nonce( $nonce , 'cds_autologin-'.$uid.'-'.(int)( time() / 60 ) ) || wp_verify_nonce( $nonce , 'cds_autologin-'.$uid.'-'.(int)( time() / 60 ) - 1 ) ) ){
			wp_redirect( $current_page_url );
			exit;
		} else {
			wp_set_auth_cookie( $uid );
			wp_redirect( $current_page_url . 'wp-admin/' ) ;
			exit;
		}
	}
}

A few small functions to glue it all together

The rest of the code consists of the function that generates the random username/domain name and a function that finds the current URL so we can redirect to it in order for the login cookie to take effect and the user to be logged in.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// A simple and almost random string generator
// We don't really need 100% random strings, so SHA1 will do just fine 
function cbs_rand_string($length = 8)
{
	return substr(sha1(rand()), 0, $length);
}
 
 
function cds_curpageurl() {
	$pageURL = 'http';
 
	if ((isset($_SERVER["HTTPS"])) &amp;&amp; ($_SERVER["HTTPS"] == "on"))
		$pageURL .= "s";
 
	$pageURL .= "://";
 
	if ($_SERVER["SERVER_PORT"] != "80")
		$pageURL .= $_SERVER["SERVER_NAME"].":".$_SERVER["SERVER_PORT"].$_SERVER["REQUEST_URI"];
 
	else
		$pageURL .= $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"];
 
	if ( function_exists('apply_filters') ) apply_filters('wppb_curpageurl', $pageURL);
 
	return $pageURL;
}

That’s it for the Code!

There’s actually less than 160 lines of code in total, including the comments and WordPress plugin headers. It’s a really simple and straightforward mini-plugin that now allows us to:

  • Create a new user and new WordPress demo site;
  • Automatically log in the new user and redirect them to the dashboard.

Download Create Demo Sub-Sites

Profile Builder Pro

Create beautiful front-end registration and profile forms with custom fields. Setup member directories, custom redirects, cutomize user emails & more using the all in one user management plugin.

Get Profile Builder

Further Improving our WordPress Demo Site Setup

We now have a very nice setup where users can create new WordPress demo sites on the fly, without having to enter username/passwords/emails, etc. Just fill a simple math CAPTCHA. You can also do things like WooCommerce integration and handle a theme customizer.

It’s also a good idea to have some kind of support team in place for when users have questions. They can help users test out product pages, use the demo importer, and choose the best theme and theme customizer. A couple of themes to consider include Divi and Elementor.

Creating a WordPress Demo Site Template

All this is great, but it would be even greater if we could have a site template that would get applied every time a new demo site is created to help with our SEO.

For this, we’ve used the Multisite Cloner WordPress plugin. It hasn’t been updated in quite some time, however, it still works great for what we need like copying the settings, pages, posts, widgets, and menus to every new WordPress demo site created and can be used in your page builder, like Elementor.

Alternatively to this plugin, you can set up a lightweight template with WooCommerce integration in WordPress Multisite settings by:

  • Setting up the first page content with a page builder like Elementor;
  • First post content;
  • Network activating the plugins/addons you want the user to have access to.

It’s not ideal, but depending on the demo content you’re building it could work just fine. 

Hiding Back-end Menus from the Front-end Demo Site

Finally, we can now hide a few menu items and widgets like the My Sites admin bar link, the tools, or the comment pages in the back-end if they won’t be needed for your new WordPress demo site front-end.

Hiding backend menus from the front-end demo site

For this, we used the free Menus addon. It simply adds a list of menus you can show/hide for all sub-sites, as simple as that.

Update: Delete Sites After 24 Hours

It’s been almost a year since we introduced demo sites for our addons and it seems that they have fulfilled their purpose. Right now, they are accessed by tens of users each day.

With such a high rate of usage, it becomes inevitable to address the automatic site removal issue. Otherwise, over time you will end up with an enormous amount of sites that could reach your hosting’s storage limits.

For our solution, we have set up an hourly cron that will call a function to delete subsites older than 24 hours. The cron is registered on plugin activation and removed on plugin deactivation. (Keep this in mind when debugging. If your plugin is already active when you are adding this code, then deactivate the plugin and activate it back.)

The function that actually does the deleting makes two checks for each subsite in order to decide if it should be removed:

  • If 24 hours have already passed since the site creation;
  • If the super admin is not a member of the site. This will ensure that the sites created by the super admin, such as the main blog or any other subsites you wish to keep alive, are safe from removal.

If these 2 conditions are true, the subsite is deleted.

Let’s see the code!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
/**
 * Schedule event hourly to delete old subsites
 */
register_activation_hook( __FILE__, 'cds_cron_to_delete_subsites_activation' );
function cds_cron_to_delete_subsites_activation() {
	wp_schedule_event( time(), 'hourly', 'cds_check_subsites_hourly_event' );
}
 
register_deactivation_hook ( __FILE__, 'cds_cron_to_delete_subsites_deactivation' );
function cds_cron_to_delete_subsites_deactivation() {
	wp_clear_scheduled_hook( 'cds_check_subsites_hourly_event' );
}
 
 
/**
 * Delete subsites registered for more than 24 hours
 *
 * Only deletes subsites where super-admin is not part of the site's users
 */
function cds_check_subsites_for_deletion() {
 
	require_once( ABSPATH . 'wp-admin/includes/admin.php' );
	// get sites
	global $wpdb;
	$args = array(
	    'network_id' =&gt; $wpdb-&gt;siteid,
	);
	$sites_array = wp_get_sites( $args );
	$current_time = current_time( 'timestamp' );
 
	foreach ( $sites_array as $site ){
		// get each blog's users and check if super-admin is the creator so that it will not be deleted
		$user_args = array(
			'blog_id'		=&gt; $site[ 'blog_id' ],
			'fields'		=&gt; 'ID',
		);
		$users = get_users( $user_args );
 
		$delete_this_site = true;
		foreach ( $users as $user ){
			if ( is_super_admin( $user ) ) {
				$delete_this_site = false;
				break;
			}
		}
 
		$register_time = strtotime( $site[ 'registered' ], current_time( 'mysql' ) );
		$time_since_registration = $current_time - $register_time;
 
		// if the site has been created for more than 86400 seconds = 24 hours, delete it
		if ( $delete_this_site &amp;&amp; ( $time_since_registration &gt; 86400 ) ) {
   			if( ! function_exists( 'wpmu_delete_blog' ) ) return;
			wpmu_delete_blog( $site[ 'blog_id' ], true );
		}
	}
}
add_action( 'cds_check_subsites_hourly_event', 'cds_check_subsites_for_deletion' );

Conclusion

Building a WordPress demo site is not really complicated, however, if you want it done right, a few things need to happen like:

  • fast and easy demo content creation (with the help of the custom plugin explained above)
  • new demo sites should be based on a template (using the Replicator plugin)
  • hide admin menus you don’t want/need to be seen (using the Menus plugin)
  • automatic demo site removal after a few days since creation (using a cron)

Also, there’s still one thing we haven’t done yet but plan to integrate later on and that’s:

  • creating a dashboard widget where we can display certain information like the current username and its Mailinator email, the demo password, information on how to use the new WordPress demo site, etc.

This is all possible with the use of the Ninja Demo plugin, so if you’re on a tight schedule, honestly go for that.

Otherwise, if you want to mess a bit with WordPress Multisite and consider this as a chance to learn something new, the DIY route is not that hard.

41 thoughts on “Create WordPress Demo Site with Multisite

    Is it possible to create a demo user that can see what an administrator sees but all changed they made get deleted from the database after say 60mins?

    Reply

    Hello Cristian, thanks for the article and plug-in. Because Replicator plug-in does not work anymore is there another plug-in which works together with your plug-in?
    Because now on my multisite there is a new demo user/site created with your plug-in but without all the settings from the original site. Hope this is clear to you what I mean. Thanks!

    Reply

    Hi Damiaan,

    Can you please tell me what doesn’t work? We’re using it for our http://demo.cozmoslabs.com/ and it’s still working fine.

    Can you check to see if there’s something that’s not configured correctly? Or if the Replicator plugin is active?

    Reply

    thanks for this article!
    I just don’t understand one thing. In your http://demo.cozmoslabs.com/ you have three products to demo. Do you have a multisite installation for each of those?
    Or you just have one multisite installation (with subdomain ‘demo.’) and then three pages from where to create the demo websites for each product? In the latter case how do you set WordPress to create new sites with different templates for each of these three products?

    I set up everything but I miss this bit, basically how to get the following scenario:
    demo.wp.com
    demo.wp.com/plugin-a/ (will create based on template `plugin-a`)
    demo.wp.com/plugin-a/demo121a
    demo.wp.com/plugin-a/demo122a
    demo.wp.com/plugin-b/ (will create based on template `plugin-a`)
    demo.wp.com/plugin-b/demo123b
    demo.wp.com/plugin-b/demo124b
    demo.wp.com/plugin-c/ (will create based on template `plugin-a`)
    demo.wp.com/plugin-c/demo125c
    demo.wp.com/plugin-c/demo126c

    Thanks again anyway!

    Reply

    Yes, there’s a multisite for each individual one of those!

    So this tutorial duplicated three times 🙂

    Reply

    Hi Cristian, thanks for replying!
    I see, after I wrote you I started changing everything tweaking your plugin to have each demo domain prefixed the product slug, such as:
    demo.wp.com/plugin-b/ (will create based on template `plugin-b`)
    demo.wp.com/plugin-b–demo123b
    demo.wp.com/plugin-b–demo124b
    demo.wp.com/plugin-c/ (will create based on template `plugin-c`)
    demo.wp.com/plugin-c–demo125c
    demo.wp.com/plugin-c–demo126c

    What do you think? DO you see any benefit of having one multisite (like in this case) or having one multisite for each product (like in your current website)?

    When I realised I needed a ‘network of networks’ I thought to go for the ‘–‘ slug solution to organize the demos, and then in the homepage demo.wp.com I just list each products.

    I would be curious to hear your thoughts!
    best

    Reply

    If you can make it work so that one demo site works for all of your products, great! Honestly I haven’t thought of that. Might have been easier this way to manage then 3 multisites.

    The bottom line is, figure out what works for you best. We’ve added demos to our products in sequence, so it was easy to just duplicate a multisite in another folder then to write code to take care of different demos in the same instance.

    Hi,

    Nice article. I am going to try this. Just have one question, this will go on creating multiple sites. Is there a way to auto delete the new demo site and user ? Can not find that info here.

    Reply

    Hello Pallavi,

    I have updated the article with the full code on how to automatically delete demo sites after 24 hours. Check out the appended update about this topic!

    Reply

    Hi,

    Is there a way to direct the user to the home page instead of the admin section? I want to demo a page builder so it makes more sense if you go straight to home page.

    Reply

    Hello Luis,

    In the cds_autologin_after_creation() function, if you remove the ” . ‘wp-admin/’ ” part from the line ” wp_redirect( $current_page_url . ‘wp-admin/’ ) ; “, it should keep you on the homepage after the demo site is created.

    Reply

    Great article. I have used your method. 1 drawback, images. What are your suggestions on replicating media of site? Does replicator do that, or maybe my hosting service WP Engine is pointing to right directory.

    Reply

    Thanks for this very useful article!
    I have one question: why the autologin of the new user is done after a redirection (create user and blog –> redirection –> autologin –> redirection to wp-admin) and not directly after that the new blog has been created (create user and blog, autologin –> redirection to wp-admin).

    And for your information: in order to use a template site to create the demo sites, this plugin can be used: https://wordpress.org/plugins/multisite-cloner/. It is free 😉

    Reply

    I guess it could work just fine, doing the autologin immediately after redirection. It might be an oversight on the logic in the article. I think the autologin functionality is borrowed from our other plugins are doing auto-login in a similar fashion for reasons that are not really needed in this application.

    There’s also the possibility if I remember correclty, but I don’t have time to test this right now, that the autologin exactly after blog creation fails with caching in place, even though it’s unlikely we’ll have any sort of caching enabled on a demo site.

    Unfortunately I don’t think we have time to rethink this, so it will stay as this for the foreseeable future, as it is working.

    As for the Multisite Cloner, it does look like it’s the right plugin for the job and actively supported. So I’ve updated the article with it as a suggested alternative. Thanks a lot!

    Reply

    Now that I think about it, this is the only way it would work as the wp_set_auth_cookie( $user_id ) function needs to setup headers from PHP, and if you do this immediately after blog creation, you’ll get the Headers Already Sent PHP fatal error. So it just won’t work any other way.

    Reply

    Thanks for the reply. On top of a great article, you offer a great support!

    Reply

    Hi,
    Recently, I’ve seen your article and read it carefully. You’ve explained very good. I really liked it. So, keep up the good work.

    Reply

    Hi, thanks for the article but I have a problem with the Replicator plugin, I can’t access the site. I there any other plugin i can use to replace the Replicator plugin?

    Reply

    Hello Cristian,

    Thank you for this great article.

    Just one question, I saw that in your demo site some plugins are not available to site admins like “Create Demo Sub-Sites” plugin, please let me know how you do it?

    I want to do not allow site admins to see “Create Demo Sub-Sites” and “Multisite Cloner” plugins.

    Thanks.

    Reply

    Sounds promising, any chance to auto create user page on sign up process with auto login, the easy way?

    Thanks 😉

    Reply

    Great plugin! Unfortunately, the Captcha is not working for me. I do the math correctly and it says invalid answer. What could be causing this?

    Reply

    Auto login is not working.

    The query strings are not being recognized in the function cds_autologin_after_creation so the cookie is not set and the redirect is not happening.

    Everything else is working fine.

    Reply

    Never mind I figured it out, it;s working perfectly.

    Thanks this piece of code was very helpful.

    Reply

    Hello Cristian, thank you very much. A great post!
    Could you tell me how to indicate the subsite you want to copy, with its content and options?

    Reply

    Nice Informative post. Thanks for sharing your great ideas with us.

    Reply

    Thanks for sharing! This is so much clearer than other tutorials I’ve been read so far.

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.