Skip to content
duplicate WordPress posts featured

How to Duplicate WordPress Posts, Pages and Custom Post Types Without A Plugin

As an administrator, editor or even developer, it’s really useful to be able to duplicate WordPress posts, pages and other post types on your website with a single click. Plus, you shouldn’t need to re-enter tags, categories, meta fields and other related options to post every time. 

In this blog post we’re going to add a small code snippet to your website so you will be able to duplicate any post type with a single click. This method works with the JupiterX theme and all other WordPress themes.

Adding a Link Button to Each Post to Duplicate It

To duplicate WordPress posts, first let’s add a link button under each post title so that when it is clicked the post will be duplicated.
Go to the function.php file of your theme and add following code at the end of it:

add_filter( 'post_row_actions', 'jupiterx_add_duplicate_post_button', 10, 2 );
 
function jupiterx_add_duplicate_post_button( $actions, $post ) {
    $args = [
        'jupiterx-to-duplicate' => $post->ID,
        'jupiterx-duplicate-posts' => wp_create_nonce( 'jupiterx-duplicate-nonce' ),
    ];
 
    if ( 'post' !== $post->post_type ) {
        $args['post_type'] = $post->post_type;
    }
 
    $url  = add_query_arg( $args, admin_url( 'edit.php' ) );
 
    $actions['duplicate_post'] = "<a href='{$url}'>Duplicate</a>";
    return $actions;
}

By adding this code, if you navigate to the Edit Post screen you will see the following button under each post:

duplicate WordPress posts - duplicate button

If you click the button now the page will simply reload.

In the next section we are going to add functionality to this button so it will duplicate the related post.

Add Functionality to the Button

After the button is clicked we get post information including tags, categories, meta fields and everything else that belongs to that post. We will then create a new post using this information, completing the process.
Copy and add the following code at the end of your function.php file in your theme, where you added the previous code snippet.

add_action( 'admin_init', 'jupiterx_create_duplicate_button_functionality' );
 
function jupiterx_create_duplicate_button_functionality() {
    if ( ! isset( $_GET['jupiterx-duplicate-posts'] ) ) {
        return;
    }
 
    check_ajax_referer( 'jupiterx-duplicate-nonce', 'jupiterx-duplicate-posts', true );
 
    $post_id = absint( $_GET['jupiterx-to-duplicate'] );
 
    $post = get_post( $post_id );
 
    if ( ! $post ) {
        wp_die( 'We could not find any post to duplicate it.' );
    }
 
    // Create post array exactly like post that was clicked.
    $args = [
        'comment_status' => $post->comment_status,
        'ping_status'    => $post->ping_status,
        'post_author'    => wp_get_current_user()->ID,
        'post_content'   => $post->post_content,
        'post_excerpt'   => $post->post_excerpt,
        'post_name'      => $post->post_name,
        'post_parent'    => $post->post_parent,
        'post_password'  => $post->post_password,
        'post_status'    => 'draft',
        'post_title'     => $post->post_title . ' Duplicated',
        'post_type'      => $post->post_type,
        'to_ping'        => $post->to_ping,
        'menu_order'     => $post->menu_order
    ];
 
    $duplicated_post = wp_insert_post( $args );
 
    // Copy taxonomies.
    $taxonomies = get_object_taxonomies( get_post_type( $post ) );
    if( $taxonomies ) {
        foreach ( $taxonomies as $taxonomy ) {
            $post_terms = wp_get_object_terms( $post_id, $taxonomy, [ 'fields' => 'slugs' ] );
            wp_set_object_terms( $duplicated_post, $post_terms, $taxonomy, false );
        }
    }
 
    // Copy meta fields.
    $post_meta = get_post_custom( $post_id );
    if( $post_meta ) {
        foreach ( $post_meta as $meta_key => $meta_values ) {
            update_post_meta( $duplicated_post, $meta_key,  $meta_values[0] );
        }
    }
 
    $args = [];
 
    if ( 'post' !== $post->post_type ) {
        $args['post_type'] = $post->post_type;
    }
 
    $url  = add_query_arg( $args, admin_url( 'edit.php' ) );
 
    wp_safe_redirect( $url );
    exit;
}

Now if you press the duplicate link, the related post will be duplicated and the word “Duplicated” will be added to its title, so you will know which one is the original post.

In following picture you see that the post has been duplicated :

duplicate WordPress posts - duplicated post

Now we have successfully added duplicate post functionality to posts. But what about other post types such as  “page”’, “product” and more?

Let’s tackle this in step 3.

Add Duplication Functionality to any Post Type

To add this functionality to any kind of post type, you need to know the post type slug. For example, the WooCommerce product post type slug is “product”.

After you’ve learned the post type slug, you need to add this line of code to the first code snippet you already added to your function.php file.

To add this functionality to posts we added following code :

add_filter( 'post_row_actions', 'jupiterx_add_duplicate_post_button', 10, 2 );

To add this to pages we just need to add the following line, as we already know that the pages slug is “page”:

add_filter( 'page_row_actions', 'jupiterx_add_duplicate_post_button', 10, 2 );

As you can see, we just replaced “post” with “page”, which means that we just need to add the post type slug at the beginning of the above filter instead of “post” or “page” and the duplication functionality will be added.

Conclusion

Some plugins like Post Duplicator enable you to duplicate WordPress posts on your site, but with just a few lines of code you can add this functionality to your website without using any third party plugin.

If you have any questions about this article, feel free to ask us in the comments. I hope this post has helped you to improve your website’s functionality.

Create Your
Dream Website with

Stay in the Loop

Sign up for our newsletter and stay up-to-date on the
latest WordPress trends, insights, and resources.

By entering your email, you agree to our Privacy policy and Terms of Services.

Share

Hadi Mohammade

Hadi Mohammade

I am a web artisan with more than 6 years of experience and am really interested to share my knowledge with everyone out there. Alongside programming I am a professional gamer, playing some online video games with friends after work is the best of fun for me.

3 Comments

  1. Very useful tip, thx mate.

  2. I find the information you provide to be both fascinating and instructive, therefore I read it often.

  3. To add this feature to any post type, you must first know its slug.


Add a Comment

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