# Duplicate Posts and Pages

> Adds a "Duplicate" link to the row actions of posts, pages and custom post types. It creates a draft copy with the same content, taxonomies and custom fields.

- Type: PHP
- Runs: Admin only
- Category: [Admin](https://wpide.com/library/category/admin/)
- Tags: duplicate, clone, copy, posts
- Author: WPIDE Team
- Installs: 0
- Updated: 2026-10-28
- Page: https://wpide.com/library/duplicate-posts-and-pages/

## Code

```php
$wpide_duplicate_link = function ( $actions, $post ) {
    if ( 'trash' === $post->post_status || 'product' === $post->post_type || ! current_user_can( 'edit_post', $post->ID ) ) {
        return $actions;
    }

    $url = wp_nonce_url(
        add_query_arg( array( 'action' => 'wpide_duplicate_post', 'post' => $post->ID ), admin_url( 'admin.php' ) ),
        'wpide_duplicate_post_' . $post->ID
    );

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

    return $actions;
};

add_filter( 'post_row_actions', $wpide_duplicate_link, 10, 2 );
add_filter( 'page_row_actions', $wpide_duplicate_link, 10, 2 );

add_action( 'admin_action_wpide_duplicate_post', function () {
    $post_id = isset( $_GET['post'] ) ? absint( $_GET['post'] ) : 0;
    check_admin_referer( 'wpide_duplicate_post_' . $post_id );

    $post = get_post( $post_id );
    $type = $post ? get_post_type_object( $post->post_type ) : null;

    if ( ! $post || ! $type || ! current_user_can( 'edit_post', $post_id ) || ! current_user_can( $type->cap->create_posts ) ) {
        wp_die( esc_html__( 'Sorry, you are not allowed to do that.' ) );
    }

    $new_id = wp_insert_post( wp_slash( array(
        'post_title'     => $post->post_title . ' (copy)',
        'post_content'   => $post->post_content,
        'post_excerpt'   => $post->post_excerpt,
        'post_status'    => 'draft',
        'post_type'      => $post->post_type,
        'post_author'    => get_current_user_id(),
        'post_parent'    => $post->post_parent,
        'menu_order'     => $post->menu_order,
        'comment_status' => $post->comment_status,
        'ping_status'    => $post->ping_status,
        'post_password'  => $post->post_password,
    ) ), true );

    if ( is_wp_error( $new_id ) ) {
        wp_die( esc_html( $new_id->get_error_message() ) );
    }

    foreach ( get_object_taxonomies( $post->post_type ) as $taxonomy ) {
        $terms = wp_get_object_terms( $post_id, $taxonomy, array( 'fields' => 'ids' ) );

        if ( ! is_wp_error( $terms ) && $terms ) {
            wp_set_object_terms( $new_id, $terms, $taxonomy );
        }
    }

    $skip = array( '_edit_lock', '_edit_last', '_wp_old_slug', '_wp_old_date' );

    foreach ( get_post_meta( $post_id ) as $key => $values ) {
        if ( in_array( $key, $skip, true ) ) {
            continue;
        }

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

    wp_safe_redirect( admin_url( 'post.php?action=edit&post=' . $new_id ) );
    exit;
} );
```

## Notes

WooCommerce products are skipped because WooCommerce has its own Duplicate action.

## How to use it

Install the free WPIDE plugin (https://wordpress.org/plugins/wpide/), find "Duplicate Posts and Pages" in its snippet library and add it in one click; or create a new PHP snippet in WPIDE (or any code snippets plugin) and paste the code above. More snippets: https://wpide.com/library/
