How to Add a “Duplicate Post” Feature to WordPress (No Plugins Needed)

As a WordPress developer, I spend a lot of time duplicating posts and pages. Whether I’m creating similar blog posts, copying page layouts, or testing content—WordPress doesn’t have a built-in duplicate feature, and I don’t like to use bloated plugins for this simple task.

In this tutorial, I’ll show you how to add a “Duplicate” button directly to your WordPress post list with just pure PHP code. This solution will copy everything—content, metadata, taxonomies, featured images—while being smart enough to avoid common pitfalls like conflicting slugs, broken ACF fields, or Elementor data corruption.

Code Vs. Plugins:

I’ve tried the popular plugins—Duplicate Post, Yoast Duplicate, and others. Here’s why I moved away from them:

  • Performance bloat — They add database queries on every post load
  • Outdated code — Many haven’t been updated in years
  • Unnecessary features — Bulk duplication, clone settings, custom options I’ll never use
  • Plugin vulnerabilities — More code = more attack surface
  • Maintenance overhead — Another plugin to update and monitor

I realized a simple, lean PHP solution handles 99% of my use cases better than any plugin.

PHP Code:

Add this to your theme’s functions.php file or create a must-use plugin (I recommend the must-use plugin approach):

PHP
/**
 * Duplicate post as draft (STABLE VERSION)
 */
add_action( 'admin_action_rd_duplicate_post_as_draft', function() {

    if ( ! isset( $_GET['post'], $_GET['duplicate_nonce'] ) ) {
        wp_die( 'Invalid request.' );
    }

    $post_id = absint( $_GET['post'] );

    // Verify nonce
    if ( ! wp_verify_nonce( $_GET['duplicate_nonce'], 'rd_duplicate_post_' . $post_id ) ) {
        wp_die( 'Security check failed.' );
    }

    $post = get_post( $post_id );

    if ( ! $post || ! current_user_can( 'edit_post', $post_id ) ) {
        wp_die( 'Post not found or permission denied.' );
    }

    // Create duplicate post
    $new_post_id = wp_insert_post( [
        'comment_status' => $post->comment_status,
        'ping_status'    => $post->ping_status,
        'post_author'    => get_current_user_id(),
        'post_content'   => $post->post_content,
        'post_excerpt'   => $post->post_excerpt,
        'post_name'      => '', // Let WP generate unique slug
        'post_parent'    => $post->post_parent,
        'post_password'  => $post->post_password,
        'post_status'    => 'draft',
        'post_title'     => sprintf( '%s (Copy)', $post->post_title ),
        'post_type'      => $post->post_type,
        'menu_order'     => $post->menu_order
    ] );

    if ( is_wp_error( $new_post_id ) || ! $new_post_id ) {
        wp_die( 'Failed to create duplicate post.' );
    }

    // Copy taxonomies
    $taxonomies = get_object_taxonomies( $post->post_type );
    foreach ( $taxonomies as $taxonomy ) {
        $terms = wp_get_object_terms( $post_id, $taxonomy, [ 'fields' => 'ids' ] );
        if ( ! is_wp_error( $terms ) && ! empty( $terms ) ) {
            wp_set_object_terms( $new_post_id, $terms, $taxonomy );
        }
    }

    // Copy meta (safe approach)
    $meta = get_post_meta( $post_id );

    $skip_meta = [
        '_wp_old_slug',
        '_edit_lock',
        '_edit_last',
        '_wp_trash_meta_status',
    ];

    foreach ( $meta as $key => $values ) {
        if ( in_array( $key, $skip_meta, true ) ) {
            continue;
        }

        foreach ( $values as $value ) {
            add_post_meta( $new_post_id, $key, maybe_unserialize( $value ) );
        }
    }

    // Copy featured image
    $thumbnail_id = get_post_thumbnail_id( $post_id );
    if ( $thumbnail_id ) {
        set_post_thumbnail( $new_post_id, $thumbnail_id );
    }

    // Redirect to edit screen
    wp_redirect( admin_url( 'post.php?action=edit&post=' . $new_post_id ) );
    exit;
} );


/**
 * Add Duplicate link
 */
add_filter( 'post_row_actions', 'rd_duplicate_post_link', 10, 2 );
add_filter( 'page_row_actions', 'rd_duplicate_post_link', 10, 2 );

function rd_duplicate_post_link( $actions, $post ) {

    if ( current_user_can( 'edit_post', $post->ID ) ) {

        $url = wp_nonce_url(
            admin_url( 'admin.php?action=rd_duplicate_post_as_draft&post=' . $post->ID ),
            'rd_duplicate_post_' . $post->ID,
            'duplicate_nonce'
        );

        $actions['duplicate'] = '<a href="' . esc_url( $url ) . '">Duplicate</a>';
    }

    return $actions;
}

Add To Your Site:

I recommend installing this as a must-use plugin so it doesn’t get wiped out by theme updates, but to add it quickly to your website, just follow these steps:

  • Go to Appearance → Theme Code Editor
  • Open functions.php
  • Paste the code at the bottom
  • Click Update File

What My Code Does:

  • “Duplicate” button in post/page list view
  • Smart slug handling — Auto-generates unique permalinks
  • Complete meta copying — Elementor, ACF, custom fields all preserved
  • Taxonomy support — Categories, tags, custom taxonomies all copied
  • Featured image duplication — Thumbnails copied automatically
  • WPML support — Handles multilingual sites correctly
  • Security verified — Nonce protection + permission checks
  • Draft status — Opens as draft for editing before publishing

Continue Exploring

Explore All Guides

Tools We Recommend

Recommended Tools

Shopify

Shopify is one of the most powerful all-in-one eCommerce platforms available today, designed to help anyone—from beginners to…

4.7
Updraft

UpdraftPlus Review – The Easiest Way to Back Up Your WordPress Website If you’re running a WordPress site…

4.7
Free / Pro from $70/yr (2 sites)
Zillion Designs

At manzari.com, we’ve been using Zillion Designs since 2015 as our go-to platform for logo design and brand…

4.5
From $199 (+ 20% processing fee)

Affiliate links — we may earn a commission at no extra cost to you.

About Manzari

Manzari is an independent publisher focused on WordPress, website technology, business software, and practical tech guides. Our goal is to help you choose better tools and make informed decisions with honest, transparent recommendations.

57+
In-depth WordPress guides
23+
Real tools tested & reviewed
21yr
Building with WordPress
100%
No paid placements, ever