Multisite – create new site with precreated pages, menu etc

The proper hook for that is wpmu_new_blog. I will describe how we do that in Multilingual Press Pro. Our code is actually rather complex; I will extract the most important points.

We offer an option to select any existing blog as a template for the new blog. The nice part is that you can edit the template content, customize the theme, activate plugins … like in any other blog. No need to update the code when you change your mind about the default content later.

For your use case, you can just create one template blog and take the blog ID.

add_action( 'wpmu_new_blog', function( $blog_id ) {
    // copy the template blog here
});

What happens in the callback?

  1. We get the prefix for the template blog (ID 44):

    switch_to_blog( 44 );
    $template_prefix = $wpdb->prefix;
    restore_current_blog();
    
  2. We erase the fresh tables for the new blog and copy the content from the template blog.

    foreach ( $tables as $table )
    {
        // empty the tables
        $wpdb->query( 'TRUNCATE TABLE ' . $wpdb->prefix . $table );
        // insert template content
        $wpdb->query( "INSERT INTO $wpdb->prefix$table SELECT * FROM $template_prefix$table" );
    }
    
  3. We restore the most important options for the new blog (blogname, home, admin_email and so on) and rename the user_roles to match the current blog.

  4. Then we copy the attachments. These are … not simple. wp_upload_dir() is not reliable after switch_to_blog(). You have to add some workarounds to get the correct paths. This is actually a separate class with 250 lines. 🙂

There are other issues like domain mapping plugins, custom plugin tables and some minor compatibility problems with other plugins using the same hook or themes and plugins expecting an installation call. They shouldn’t bother you when you just need a solution for one site.