PHPwordpressintermediate
WordPress Duplicate Post/Page
Add a quick duplicate button to posts and pages in WordPress admin
Faisal Yaqoob
November 6, 2025
#wordpress#admin#duplicate#post#productivity
Code
php
1 // Add duplicate link to post/page row actions 2 function add_duplicate_post_link($actions, $post) { 3 // Check user capabilities 4 if (current_user_can('edit_posts')) { 5 $duplicate_url = wp_nonce_url( 6 add_query_arg( 7 array( 8 'action' => 'duplicate_post', 9 'post' => $post->ID, 10 ), 11 admin_url('admin.php') 12 ), 13 'duplicate_post_' . $post->ID 14 ); 15
16 $actions['duplicate'] = '<a href="' . $duplicate_url . '" title="Duplicate this item" rel="permalink">Duplicate</a>'; 17 } 18
19 return $actions; 20 } 21 add_filter('post_row_actions', 'add_duplicate_post_link', 10, 2); 22 add_filter('page_row_actions', 'add_duplicate_post_link', 10, 2); 23
24 // Handle the duplication 25 function duplicate_post_handler() { 26 // Check if action is set and user has permission 27 if (empty($_GET['action']) || $_GET['action'] !== 'duplicate_post') { 28 return; 29 } 30
31 if (empty($_GET['post'])) { 32 wp_die('No post to duplicate!'); 33 } 34
35 $post_id = absint($_GET['post']); 36
37 // Verify nonce 38 if (!wp_verify_nonce($_GET['_wpnonce'], 'duplicate_post_' . $post_id)) { 39 wp_die('Security check failed!'); 40 } 41
42 // Check permissions 43 if (!current_user_can('edit_posts')) { 44 wp_die('You do not have permission to duplicate posts.'); 45 } 46
47 // Get the original post 48 $post = get_post($post_id); 49
50 if (!$post) { 51 wp_die('Post not found!'); 52 } 53
54 // Duplicate the post 55 $new_post_id = duplicate_post($post); 56
57 if ($new_post_id) { 58 // Redirect to edit screen 59 wp_redirect(admin_url('post.php?action=edit&post=' . $new_post_id)); 60 exit; 61 } else { 62 wp_die('Failed to duplicate post.'); 63 } 64 } 65 add_action('admin_action_duplicate_post', 'duplicate_post_handler'); 66
67 // Core duplication function 68 function duplicate_post($post) { 69 // Prepare post data 70 $current_user = wp_get_current_user(); 71 $new_post_author = $current_user->ID; 72
73 $args = array( 74 'post_author' => $new_post_author, 75 'post_content' => $post->post_content, 76 'post_excerpt' => $post->post_excerpt, 77 'post_title' => $post->post_title . ' (Copy)', 78 'post_status' => 'draft', 79 'post_type' => $post->post_type, 80 'comment_status' => $post->comment_status, 81 'ping_status' => $post->ping_status, 82 'post_parent' => $post->post_parent, 83 'menu_order' => $post->menu_order, 84 'to_ping' => $post->to_ping, 85 'pinged' => $post->pinged, 86 ); 87
88 // Insert the post 89 $new_post_id = wp_insert_post($args); 90
91 if (is_wp_error($new_post_id)) { 92 return false; 93 } 94
95 // Duplicate post meta 96 $post_meta = get_post_meta($post->ID); 97
98 if ($post_meta) { 99 foreach ($post_meta as $meta_key => $meta_values) { 100 // Skip certain meta keys 101 if ($meta_key === '_wp_old_slug' || $meta_key === '_edit_lock' || $meta_key === '_edit_last') { 102 continue; 103 } 104
105 foreach ($meta_values as $meta_value) { 106 add_post_meta($new_post_id, $meta_key, maybe_unserialize($meta_value)); 107 } 108 } 109 } 110
111 // Duplicate taxonomies 112 $taxonomies = get_object_taxonomies($post->post_type); 113
114 if ($taxonomies) { 115 foreach ($taxonomies as $taxonomy) { 116 $terms = wp_get_object_terms($post->ID, $taxonomy, array('fields' => 'slugs')); 117 wp_set_object_terms($new_post_id, $terms, $taxonomy); 118 } 119 } 120
121 return $new_post_id; 122 }
WordPress Duplicate Post/Page
Add a "Duplicate" link to the WordPress admin that allows you to quickly clone posts, pages, or custom post types with all metadata.
// Add duplicate link to post/page row actions
function add_duplicate_post_link($actions, $post) {
// Check user capabilities
if (current_user_can('edit_posts')) {
$duplicate_url = wp_nonce_url(
add_query_arg(
array(
'action' => 'duplicate_post',
'post' => $post->ID,
),
admin_url('admin.php')
),
'duplicate_post_' . $post->ID
);
$actions['duplicate'] = '<a href="' . $duplicate_url . '" title="Duplicate this item" rel="permalink">Duplicate</a>';
}
return $actions;
}
add_filter('post_row_actions', 'add_duplicate_post_link', 10, 2);
add_filter('page_row_actions', 'add_duplicate_post_link', 10, 2);
// Handle the duplication
function duplicate_post_handler() {
// Check if action is set and user has permission
if (empty($_GET['action']) || $_GET['action'] !== 'duplicate_post') {
return;
}
if (empty($_GET['post'])) {
wp_die('No post to duplicate!');
}
$post_id = absint($_GET['post']);
// Verify nonce
if (!wp_verify_nonce($_GET['_wpnonce'], 'duplicate_post_' . $post_id)) {
wp_die('Security check failed!');
}
// Check permissions
if (!current_user_can('edit_posts')) {
wp_die('You do not have permission to duplicate posts.');
}
// Get the original post
$post = get_post($post_id);
if (!$post) {
wp_die('Post not found!');
}
// Duplicate the post
$new_post_id = duplicate_post($post);
if ($new_post_id) {
// Redirect to edit screen
wp_redirect(admin_url('post.php?action=edit&post=' . $new_post_id));
exit;
} else {
wp_die('Failed to duplicate post.');
}
}
add_action('admin_action_duplicate_post', 'duplicate_post_handler');
// Core duplication function
function duplicate_post($post) {
// Prepare post data
$current_user = wp_get_current_user();
$new_post_author = $current_user->ID;
$args = array(
'post_author' => $new_post_author,
'post_content' => $post->post_content,
'post_excerpt' => $post->post_excerpt,
'post_title' => $post->post_title . ' (Copy)',
'post_status' => 'draft',
'post_type' => $post->post_type,
'comment_status' => $post->comment_status,
'ping_status' => $post->ping_status,
'post_parent' => $post->post_parent,
'menu_order' => $post->menu_order,
'to_ping' => $post->to_ping,
'pinged' => $post->pinged,
);
// Insert the post
$new_post_id = wp_insert_post($args);
if (is_wp_error($new_post_id)) {
return false;
}
// Duplicate post meta
$post_meta = get_post_meta($post->ID);
if ($post_meta) {
foreach ($post_meta as $meta_key => $meta_values) {
// Skip certain meta keys
if ($meta_key === '_wp_old_slug' || $meta_key === '_edit_lock' || $meta_key === '_edit_last') {
continue;
}
foreach ($meta_values as $meta_value) {
add_post_meta($new_post_id, $meta_key, maybe_unserialize($meta_value));
}
}
}
// Duplicate taxonomies
$taxonomies = get_object_taxonomies($post->post_type);
if ($taxonomies) {
foreach ($taxonomies as $taxonomy) {
$terms = wp_get_object_terms($post->ID, $taxonomy, array('fields' => 'slugs'));
wp_set_object_terms($new_post_id, $terms, $taxonomy);
}
}
return $new_post_id;
}
Add Admin Bar Link
// Add duplicate link to admin bar when editing
function add_duplicate_admin_bar_link($wp_admin_bar) {
global $post;
if (!is_admin() || !$post) {
return;
}
if (!current_user_can('edit_posts')) {
return;
}
$duplicate_url = wp_nonce_url(
add_query_arg(
array(
'action' => 'duplicate_post',
'post' => $post->ID,
),
admin_url('admin.php')
),
'duplicate_post_' . $post->ID
);
$wp_admin_bar->add_node(array(
'id' => 'duplicate-post',
'title' => 'Duplicate This',
'href' => $duplicate_url,
'meta' => array(
'title' => 'Duplicate this post/page',
),
));
}
add_action('admin_bar_menu', 'add_duplicate_admin_bar_link', 90);
Support Custom Post Types
// Add duplicate for specific custom post types
function add_duplicate_custom_post_type_link($actions, $post) {
$allowed_post_types = array('post', 'page', 'product', 'portfolio');
if (in_array($post->post_type, $allowed_post_types) && current_user_can('edit_posts')) {
$duplicate_url = wp_nonce_url(
add_query_arg(
array(
'action' => 'duplicate_post',
'post' => $post->ID,
),
admin_url('admin.php')
),
'duplicate_post_' . $post->ID
);
$actions['duplicate'] = '<a href="' . $duplicate_url . '">Duplicate</a>';
}
return $actions;
}
add_filter('post_row_actions', 'add_duplicate_custom_post_type_link', 10, 2);
add_filter('page_row_actions', 'add_duplicate_custom_post_type_link', 10, 2);
Features
- One-Click Duplication: Quick duplicate from post list
- Complete Copy: Duplicates content, meta, and taxonomies
- Draft Status: New posts created as drafts
- Safe: Includes nonce verification
- Extensible: Works with custom post types
- User-Friendly: Adds clear duplicate link in admin
Related Snippets
Add Custom Admin Column
Add custom columns to the WordPress admin posts list with sortable functionality
PHPwordpressintermediate
phpPreview
// Add the custom column header
function add_featured_image_column($columns) {
// Insert after title column
$new_columns = array();
...#admin#custom-column#wordpress+2
1/9/2025
View
Disable Gutenberg Block Editor
Disable the Gutenberg editor and use the Classic Editor instead
PHPwordpressbeginner
phpPreview
// Method 1: Disable Gutenberg completely
add_filter('use_block_editor_for_post', '__return_false', 10);
// Method 2: Disable for specific post types only
...#gutenberg#classic-editor#wordpress+1
1/9/2025
View
WordPress Custom Breadcrumbs
Create SEO-friendly breadcrumb navigation without plugins
PHPwordpressintermediate
phpPreview
// Display breadcrumbs
function custom_breadcrumbs() {
// Settings
$separator = ' » ';
...#wordpress#breadcrumbs#navigation+2
11/15/2025
View