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:
- Creating a demo subdomain to the main domain
- Installing WordPress Multisite
- Setting up available plugins and themes
- Replacing the complex WordPress sign-up with a simple “Create Demo” button (custom plugin) that will:
- Further improving our setup by hiding certain back-end menus and using a site template so all new WordPress demo sites are all the same
- Update: Delete sites after 24 hours
- Conclusion
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.
Replacing the WP 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.
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&uid=$user_id&_wpnonce=$nonce"; return "<script> window.location.replace('$location'); </script>"; } else { $cpa->reset_captcha(); ob_start(); ?> |
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'] ) && 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"])) && ($_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 the pluginFurther improving our new 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.
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' => $wpdb->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' => $site[ 'blog_id' ], 'fields' => '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 && ( $time_since_registration > 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.
Subscribe to get early access
to new plugins, discounts and brief updates about what's new with Cozmoslabs!
Thanks for this amazing article!
Agreed!
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?
Hi Adam,
That’s exactly what this tutorial walks you through. All demo sites log you in as an administrator.
You can check out our own demo site for Profile Builder to see how that works: http://demo.cozmoslabs.com/profilebuilder/
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!
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?
Great article!
We have build a service for this purpose, it’s free for a limited capacity.
I hope I am allowed to post the link: https://wpdemo.cloud/
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!
Yes, there’s a multisite for each individual one of those!
So this tutorial duplicated three times 🙂
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
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.
Hey Kuus, If you need to create demos for different products from one multisite network, you can try a ready-made demo builder solution if you want, I recently reviewed it: http://www.getmotopress.com/plugins/demo-builder-plugin-for-wordpress/
If you read this message in time (if cozmoslabs post it), you can actually get is half discounted in terms of Black Friday sale.
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.
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!
Hi,
Wow..thanks a lot.
Will check that.
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.
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.
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.
Also, just realized that plugin only works if I had previously logged in as admin. When I use another browser or incognito mode, i get a CAPTCHA invalid error and get redirected.
http://trywpbpm.com/?page_id=1106
Just tested this out and it redirected me correctly at http://demo46bb25b3.trywpbpm.com/wp-admin/
Perhaps there’s something else going on there?
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 😉
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!
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.
Thanks for the reply. On top of a great article, you offer a great support!
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.
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?
Use the Multisite Cloner
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.
Sounds promising, any chance to auto create user page on sign up process with auto login, the easy way?
Thanks 😉
Hello Cristian,
Thank you for this great article.
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?
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.
Never mind I figured it out, it;s working perfectly.
Thanks this piece of code was very helpful.
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?
There is a small update in the article:
UPDATE:We recommend you also have a look at the Multisite Cloner plugin from wordpress.org that is working and actively developed: https://wordpress.org/plugins/multisite-cloner/
Thanks for your quick answer but how to create automatic copies with cloner?
thanks for this article help me a lot!!!
Nice Informative post. Thanks for sharing your great ideas with us.
Thanks for sharing! This is so much clearer than other tutorials I’ve been read so far.
This is great, I’m going to give it a try (paying customer of yours btw).
This demo, the captcha doesn’t work: https://pb-demo.cozmoslabs.com/#topmenu
Your PMS demo does still work tho. =)
Hi Alex, just tried it and it works for me.