{"id":358056,"date":"2026-08-27T12:49:17","date_gmt":"2026-08-27T12:49:17","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/freshet-pages-plus\/"},"modified":"2026-09-17T10:57:56","modified_gmt":"2026-09-17T10:57:56","slug":"freshet-pages-plus","status":"publish","type":"plugin","link":"https:\/\/ltz.wordpress.org\/plugins\/freshet-pages-plus\/","author":15137713,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.5.2","stable_tag":"1.5.2","tested":"7.1.1","requires":"6.0","requires_php":"7.4","requires_plugins":null,"header_name":"Freshet Pages Plus","header_author":"Freshet Studio","header_description":"Fixes the WP Admin list-table gripes: a sortable \"Modified\" column (with ID and author), the full URL path under every title, a parent filter + sortable Parent column for hierarchical content, a template column + filter, slug\/path search, and one-click + bulk Duplicate.","assets_banners_color":"3443ff","last_updated":"2026-09-17 10:57:56","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"","header_author_uri":"https:\/\/freshet.studio","rating":0,"author_block_rating":0,"active_installs":0,"downloads":133,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.5.1":{"tag":"1.5.1","author":"kristoffbertram","date":"2026-08-27 12:48:51","revision":3668857},"1.5.2":{"tag":"1.5.2","author":"kristoffbertram","date":"2026-09-17 10:57:56","revision":3700128}},"upgrade_notice":[],"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3700128,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3700128,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256},"icon.svg":{"filename":"icon.svg","revision":3700128,"resolution":false,"location":"assets","locale":false}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3700128,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3700128,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{"blueprint.json":{"filename":"blueprint.json","revision":3700128,"resolution":false,"location":"assets","locale":"","contents":"{\"$schema\":\"https:\\\/\\\/playground.wordpress.net\\\/blueprint-schema.json\",\"description\":\"Freshet Pages Plus on a small, nested site: eighteen pages three levels deep, two authors and staggered edit dates, landing straight on the Pages screen.\",\"landingPage\":\"\\\/wp-admin\\\/edit.php?post_type=page\",\"preferredVersions\":{\"php\":\"8.3\",\"wp\":\"latest\"},\"features\":{\"networking\":true},\"steps\":[{\"step\":\"login\",\"username\":\"admin\"},{\"step\":\"installPlugin\",\"pluginData\":{\"resource\":\"wordpress.org\\\/plugins\",\"slug\":\"freshet-pages-plus\"},\"options\":{\"activate\":true},\"progress\":{\"weight\":1,\"caption\":\"Installing Freshet Pages Plus\"}},{\"step\":\"setSiteOptions\",\"options\":{\"blogname\":\"Northwind Studio\",\"blogdescription\":\"A site with enough pages to lose one\"}},{\"step\":\"runPHP\",\"code\":\"<?php\\n\\\/**\\n * Freshet Pages Plus - Playground preview fixture.\\n *\\n * A blank WordPress has two pages, so the Pages screen would show none of what\\n * this plugin does. This seeds a small site: a three-level page tree, two\\n * authors, and eighteen distinct modified timestamps, so the path under each\\n * title, the parent filter and the sortable Modified column all have something\\n * to say the moment the preview lands.\\n *\\\/\\nrequire_once 'wordpress\\\/wp-load.php';\\n\\nglobal $wp_rewrite, $wpdb;\\n\\n\\\/\\\/ The URL path under each title is the point of the preview: it needs pretty permalinks.\\n$wp_rewrite->set_permalink_structure('\\\/%postname%\\\/');\\n$wp_rewrite->flush_rules(false);\\n\\n\\\/\\\/ A second author, so the Modified column's \\\"by ...\\\" is not one name repeated.\\n$editor    = get_user_by('login', 'robin');\\n$editor_id = $editor ? (int) $editor->ID : (int) wp_insert_user([\\n    'user_login'   => 'robin',\\n    'user_pass'    => wp_generate_password(24),\\n    'user_email'   => 'robin@example.com',\\n    'display_name' => 'Robin Vale',\\n    'first_name'   => 'Robin',\\n    'last_name'    => 'Vale',\\n    'role'         => 'editor',\\n]);\\n$admin    = get_user_by('login', 'admin');\\n$admin_id = $admin ? (int) $admin->ID : 1;\\n\\n\\\/\\\/ slug => [title, parent slug, status, menu_order, edited N days ago, created N days before that edit, author, blurb]\\n$pages = [\\n    'home'               => ['Home',               '',             'publish',   0,   2, 320, 'admin', 'The front door. Everything below it is nested, which is exactly the shape WordPress&#8217; own list table stops describing once a site grows.'],\\n    'about'              => ['About',              '',             'publish',  10,   9, 210, 'robin', 'Who we are, in one screen.'],\\n    'our-team'           => ['Our Team',           'about',        'publish',   0,  27, 140, 'robin', 'Portraits and job titles. Edited whenever somebody joins.'],\\n    'careers'            => ['Careers',            'about',        'draft',    10,   4,  30, 'robin', 'A draft: note that it still shows the path it will get once published.'],\\n    'press-and-media'    => ['Press & Media',     'about',        'publish',  20,  61, 190, 'admin', 'Logos, boilerplate and a contact for journalists.'],\\n    'services'           => ['Services',           '',             'publish',  20,   6, 300, 'admin', 'The parent of the deepest branch on this site.'],\\n    'consulting'         => ['Consulting',         'services',     'publish',   0,  13, 260, 'robin', 'A child page with children of its own.'],\\n    'discovery-audit'    => ['Discovery Audit',    'consulting',   'publish',   0,  41, 120, 'admin', 'Three levels down. The path under the title is the only place that is visible at a glance.'],\\n    'migration-planning' => ['Migration Planning', 'consulting',   'publish',  10,  88, 150, 'robin', 'Also three levels down, and edited three months ago rather than last week.'],\\n    'web-development'    => ['Web Development',    'services',     'publish',  10,  19, 240, 'admin', 'A sibling of Consulting.'],\\n    'support-plans'      => ['Support Plans',      'services',     'publish',  20,  34, 200, 'robin', 'Retainers and response times.'],\\n    'case-studies'       => ['Case Studies',       '',             'publish',  30,  52, 170, 'admin', 'A second parent, so the parent filter has more than one useful option.'],\\n    'northwind-bakery'   => ['Northwind Bakery',   'case-studies', 'publish',   0,  74,  90, 'robin', 'Filter the list by this page&#8217;s parent and only its siblings remain.'],\\n    'harbour-logistics'  => ['Harbour Logistics',  'case-studies', 'publish',  10, 118,  60, 'admin', 'Four months since the last edit, which the Modified column says without being asked twice.'],\\n    'pricing'            => ['Pricing',            '',             'publish',  40,   1, 275, 'robin', 'The most recently edited page on the site. Sort by Modified and it comes first.'],\\n    'contact'            => ['Contact',            '',             'publish',  50, 156, 330, 'admin', 'Address, map, and a form nobody has touched in five months.'],\\n    'terms-of-service'   => ['Terms of Service',   '',             'publish',  60, 213, 120, 'admin', 'Seven months old. Sort Modified ascending and this end of the list is the interesting one.'],\\n    'style-guide'        => ['Style Guide',        '',             'draft',    70, 289,  45, 'robin', 'The oldest edit here, and a draft, so it shows both ends of what the column reports.'],\\n];\\n\\n$ids = [];\\n\\nforeach ($pages as $slug => $page) {\\n    list($title, $parent, $status, $order, $edited_days, $age_days, $author, $blurb) = $page;\\n\\n    \\\/\\\/ Relative, not hard-coded: the preview should read as a live site in any year.\\n    $modified = time() - ($edited_days * DAY_IN_SECONDS) - (($order + 3) * HOUR_IN_SECONDS);\\n    $created  = $modified - ($age_days * DAY_IN_SECONDS);\\n\\n    $id = wp_insert_post([\\n        'post_type'     => 'page',\\n        'post_title'    => $title,\\n        'post_name'     => $slug,\\n        'post_status'   => $status,\\n        'post_author'   => 'robin' === $author ? $editor_id : $admin_id,\\n        'post_parent'   => '' !== $parent && isset($ids[$parent]) ? $ids[$parent] : 0,\\n        'menu_order'    => $order,\\n        'post_content'  => '<!-- wp:paragraph --><p>' . $blurb . '<\\\/p><!-- \\\/wp:paragraph -->',\\n        'post_date'     => gmdate('Y-m-d H:i:s', $created),\\n        'post_date_gmt' => gmdate('Y-m-d H:i:s', $created),\\n    ], true);\\n\\n    if (is_wp_error($id)) {\\n        continue;\\n    }\\n\\n    $ids[$slug] = (int) $id;\\n\\n    \\\/\\\/ wp_insert_post ties post_modified to post_date on insert, which would give\\n    \\\/\\\/ every row one timestamp per creation date and nothing to sort. Stagger it.\\n    $wpdb->update(\\n        $wpdb->posts,\\n        [\\n            'post_modified'     => gmdate('Y-m-d H:i:s', $modified),\\n            'post_modified_gmt' => gmdate('Y-m-d H:i:s', $modified),\\n        ],\\n        ['ID' => (int) $id]\\n    );\\n    clean_post_cache((int) $id);\\n}\\n\\n\\\/\\\/ Show the tree, not the blog: a static front page makes Home read as the front door.\\nif (isset($ids['home'])) {\\n    update_option('show_on_front', 'page');\\n    update_option('page_on_front', $ids['home']);\\n}\\n\",\"progress\":{\"weight\":2,\"caption\":\"Seeding a page tree worth looking at\"}}]}"}},"all_blocks":[],"tagged_versions":["1.5.1","1.5.2"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3700128,"resolution":"1","location":"assets","locale":"","width":1280,"height":768}},"screenshots":{"1":"The Pages screen with the plugin active: the URL path under every title, a Parent column and parent filter, a sortable Modified column with ID, age and author, and Duplicate among the row and bulk actions."}},"plugin_section":[],"plugin_tags":[2892,24939,23177,2919,243],"plugin_category":[],"plugin_contributors":[276640],"plugin_business_model":[],"class_list":["post-358056","plugin","type-plugin","status-publish","hentry","plugin_tags-admin-columns","plugin_tags-duplicate-page","plugin_tags-duplicate-post","plugin_tags-last-modified","plugin_tags-pages","plugin_contributors-kristoffbertram","plugin_committers-kristoffbertram"],"banners":{"banner":"https:\/\/ps.w.org\/freshet-pages-plus\/assets\/banner-772x250.png?rev=3700128","banner_2x":"https:\/\/ps.w.org\/freshet-pages-plus\/assets\/banner-1544x500.png?rev=3700128","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":"https:\/\/ps.w.org\/freshet-pages-plus\/assets\/icon.svg?rev=3700128","icon":"https:\/\/ps.w.org\/freshet-pages-plus\/assets\/icon.svg?rev=3700128","icon_2x":false,"generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/freshet-pages-plus\/assets\/screenshot-1.png?rev=3700128","caption":"The Pages screen with the plugin active: the URL path under every title, a Parent column and parent filter, a sortable Modified column with ID, age and author, and Duplicate among the row and bulk actions."}],"raw_content":"<!--section=description-->\n<p>WordPress' admin list tables were built for a blog with forty posts. On a site with four hundred pages nested six deep they stop answering the questions you actually have: where does this page live, which template renders it, what changed last, and who changed it.<\/p>\n\n<p>Freshet Pages Plus puts those answers in the list tables you already use \u2014 Pages, Posts, and every public custom post type. There is no settings screen: each enhancement appears on the screens where it applies and nowhere else.<\/p>\n\n<p><strong>What it adds<\/strong><\/p>\n\n<ul>\n<li><strong>Sortable \"Modified\" column<\/strong> \u2014 when it was last edited, by whom, with the post ID underneath. On every public post type.<\/li>\n<li><strong>Full URL path under every title<\/strong> \u2014 see where a page actually lives without opening it. Drafts show the path they will get.<\/li>\n<li><strong>Parent filter and sortable Parent column<\/strong> \u2014 for hierarchical content, including a \"Top level only\" option.<\/li>\n<li><strong>Template column and filter<\/strong> \u2014 see and filter by page template, wherever the theme registers templates for that post type.<\/li>\n<li><strong>Slug\/path search<\/strong> \u2014 find a page by its URL fragment instead of guessing the title someone gave it.<\/li>\n<li><strong>One-click and bulk Duplicate<\/strong> \u2014 copies a page with its terms and meta, as a draft.<\/li>\n<\/ul>\n\n<p>In search terms: it lets you duplicate a page or duplicate a post (clone or copy it, one at a time or in bulk), sort by modified date with a last modified column, filter child pages by their parent, filter by page template, and search by slug \u2014 admin columns and filters on the Pages screen and every public post type, with nothing to configure.<\/p>\n\n<p>Part of the Freshet plugin suite. Full documentation: <a href=\"https:\/\/freshet.studio\/docs\">freshet.studio\/docs<\/a>.<\/p>\n\n<!--section=installation-->\n<ol>\n<li>Install and activate the plugin.<\/li>\n<li>Open <strong>Pages<\/strong> (or any other public post type). The columns, filters and the Duplicate action are already there.<\/li>\n<\/ol>\n\n<p>There is nothing to configure.<\/p>\n\n<!--section=faq-->\n<dl>\n<dt id=\"where%20are%20the%20settings%3F\"><h3>Where are the settings?<\/h3><\/dt>\n<dd><p>There are none. Every enhancement appears where it applies \u2014 the parent filter only on hierarchical post types, the template column only where the theme registers templates \u2014 and stays out of the way everywhere else.<\/p><\/dd>\n<dt id=\"which%20post%20types%20does%20it%20touch%3F\"><h3>Which post types does it touch?<\/h3><\/dt>\n<dd><p>Every public post type with an admin UI, except attachments: the media library is a different screen with its own column plumbing.<\/p><\/dd>\n<dt id=\"how%20do%20i%20duplicate%20a%20page%20or%20post%3F\"><h3>How do I duplicate a page or post?<\/h3><\/dt>\n<dd><p>Hover a row on Pages, Posts or any public post type and click <strong>Duplicate<\/strong>: the copy is created as a draft and the editor opens on it. To clone several at once, tick them and pick <strong>Duplicate<\/strong> from the Bulk actions dropdown; the list reports how many copies were made.<\/p><\/dd>\n<dt id=\"how%20do%20i%20sort%20pages%20by%20last%20modified%20date%3F\"><h3>How do I sort pages by last modified date?<\/h3><\/dt>\n<dd><p>Click the <strong>Modified<\/strong> column header. It sorts on WordPress' own modified ordering and shows the date, the post ID, how long ago that was, and the author, so the page someone touched this morning is one click away on a site with thousands.<\/p><\/dd>\n<dt id=\"how%20do%20i%20see%20the%20child%20pages%20of%20a%20page%3F\"><h3>How do I see the child pages of a page?<\/h3><\/dt>\n<dd><p>Pick the page in the parent filter dropdown above the list. You get its whole branch \u2014 children, grandchildren, all the way down \u2014 nested, in the site's own menu order. <strong>Top level only<\/strong> shows just the root pages.<\/p><\/dd>\n<dt id=\"what%20does%20duplicate%20copy%3F\"><h3>What does Duplicate copy?<\/h3><\/dt>\n<dd><p>Content, excerpt, parent, menu order, password, comment and ping status, taxonomy terms and post meta. The copy is created as a draft, owned by you, titled \"\u2026 (Copy)\", with an empty slug so it never collides with the original.<\/p><\/dd>\n<dt id=\"the%20template%20column%20isn%27t%20showing\"><h3>The Template column isn't showing<\/h3><\/dt>\n<dd><p>Then the active theme registers no page templates for that post type. The column and its filter appear only where there is something to show.<\/p><\/dd>\n<dt id=\"does%20it%20change%20the%20front%20end%3F\"><h3>Does it change the front end?<\/h3><\/dt>\n<dd><p>No. Everything it does happens in wp-admin.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.5.2<\/h4>\n\n<ul>\n<li>Listing: a screenshot of the Pages screen with the plugin active, a Live Preview that boots to a populated Pages screen, and a description written in the words people search for. No code changes.<\/li>\n<\/ul>\n\n<h4>1.5.1<\/h4>\n\n<ul>\n<li>The text domain now matches the directory slug (freshet-pages-plus), so wordpress.org-delivered translations load.<\/li>\n<\/ul>\n\n<h4>1.5.0<\/h4>\n\n<ul>\n<li>Fix: Duplicate no longer strips backslashes from content and meta (wp_insert_post\/add_post_meta expect slashed data).<\/li>\n<li>New: Template column + filter dropdown, on post types where the theme registers page templates.<\/li>\n<li>New: post ID in the Modified column subline.<\/li>\n<\/ul>\n\n<h4>1.4.0<\/h4>\n\n<ul>\n<li>Plugin-check escaping pass.<\/li>\n<\/ul>","raw_excerpt":"Duplicate page or post in one click, sortable last modified column, parent and template filters, the URL path under every title, search by slug.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/ltz.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/358056","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ltz.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/ltz.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/ltz.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=358056"}],"author":[{"embeddable":true,"href":"https:\/\/ltz.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/kristoffbertram"}],"wp:attachment":[{"href":"https:\/\/ltz.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=358056"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/ltz.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=358056"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/ltz.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=358056"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/ltz.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=358056"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/ltz.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=358056"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/ltz.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=358056"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}