Allow WordPress to Duplicate Page or Post

| By Webner

In WordPress, sometimes a situation occurs when we need to recreate a page with very similar content or design of another page. Then instead of recreating a page from scratch we can duplicate or clone a page and can modify it accordingly. But not all the WordPress themes provide facility to duplicate the pages. In that case, we need to create the similar pages again and again:


To avoid this issue, we have several plugins also that help to duplicate the pages like ‘Duplicate Page’ etc. But what is the need of a plugin if the same functionality is possible through a little code?

To achieve this we just need to paste this code to child theme’s functions.php. This will create an option to Duplicate the page in front of each page:

function duplicate_page(){
global $wpdb;
if (! ( isset( $_GET['post']) || isset( $_POST['post']) || ( isset($_REQUEST['action']) && 'duplicate_page' == $_REQUEST['action'] ) ) ) {
wp_die('No post to duplicate has been supplied!');
if ( !isset( $_GET['duplicate_nonce'] ) || !wp_verify_nonce( $_GET['duplicate_nonce'], basename( __FILE__ ) ) )
$post_id = (isset($_GET['post']) ? absint( $_GET['post'] ) : absint( $_POST['post'] ) ); //get the original post id

$post = get_post( $post_id ); //and all the original post data then
* if you don't want current user to be the new post author,
* then change next couple of lines to this: $new_post_author = $post->post_author;
$current_user = wp_get_current_user();
$new_post_author = $current_user->ID;
if (isset( $post ) && $post != null){ //if post data exists, create the post duplicate
$args = array(
'comment_status' => $post->comment_status,
'ping_status' => $post->ping_status,
'post_author' => $new_post_author,
'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,
'post_type' => $post->post_type,
'to_ping' => $post->to_ping,
'menu_order' => $post->menu_order
$new_post_id = wp_insert_post( $args ); //inserting post
/* get all current post terms and set them to the new post draft */
$taxonomies = get_object_taxonomies($post->post_type); // returns array of taxonomy names for post type, ex array("category", "post_tag");
foreach ($taxonomies as $taxonomy) {
$post_terms = wp_get_object_terms($post_id, $taxonomy, array('fields' => 'slugs'));
wp_set_object_terms($new_post_id, $post_terms, $taxonomy, false);
/*duplicate all post meta just in two SQL queries*/
$post_meta_infos = $wpdb->get_results("SELECT meta_key, meta_value FROM $wpdb->postmeta WHERE post_id=$post_id");
if (count($post_meta_infos)!=0) {
$sql_query = "INSERT INTO $wpdb->postmeta (post_id, meta_key, meta_value) ";
foreach ($post_meta_infos as $meta_info) {
$meta_key = $meta_info->meta_key;
if( $meta_key == '_wp_old_slug' ) continue;
$meta_value = addslashes($meta_info->meta_value);
$sql_query_sel[]= "SELECT $new_post_id, '$meta_key', '$meta_value'";
$sql_query.= implode(" UNION ALL ", $sql_query_sel);

/***** finally, redirect to the edit post screen for the new draft***/
wp_redirect( admin_url( 'post.php?action=edit&post=' . $new_post_id ) );
} else {
wp_die('Post creation failed, could not find original post: ' . $post_id);
add_action( 'admin_action_rd_duplicate_post_as_draft', 'duplicate_page' );

Above function will create the duplicate of the page or post.

Now, this below code will bind an option to duplicate the page to each page:

/*********Add the duplicate link to action list for post_row_actions*******/
function duplicate_link( $actions, $post ) {
if (current_user_can('edit_posts')) 
{$actions['duplicate'] = '<a href="' . wp_nonce_url('admin.php?action=duplicate_page&post=' . $post->ID, basename(__FILE__), 'duplicate_nonce' ) . '" title="Duplicate this item" rel="permalink">Duplicate</a>';
return $actions;
add_filter('page_row_actions', 'duplicate_link’, 10, 2);


Now we can simply click this link and can create a duplicate of a selected page.This saves our time as well as effort.

Leave a Reply

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