Custom Permalinks

Description

You want to take control of your WordPress site’s URLs? The Custom Permalinks plugin gives you the power to set unique, custom URLs for any post, page, tag, or category. This means you can design your site’s structure exactly how you envision it, rather than being limited by WordPress’s default settings. When you set a custom permalink, the original post URL will be automatically redirected to your new, customized URL.

Key Features

  • Individual Permalink Control: Assign unique URLs to any post, page, tag, or category.
  • Site Structure Control: Gain ultimate control over how your site’s URLs are organized.
  • Post Type Permalink Structures (v3.0.0+): Define custom permalink structures for each public Post Type using predefined tags, automatically generating URLs upon content creation. You can still manually edit any permalink. If left empty, default settings will apply.
  • Automatic Redirects: Old URLs keep working — visitors and search engines are redirected to the new custom permalink automatically.

Getting Started: Plugin Settings

You can configure Custom Permalinks by navigating to Settings > Custom Permalinks in your WordPress Dashboard.

To set a permalink for an individual post, page, category, or tag, edit that item and look for the Custom Permalink field near the top (or in the sidebar) of the editor screen — enter the URL path you want and save.

Available Tags for Permalink Structures

When setting up your custom permalink structures, you can use a variety of tags that will dynamically populate the URL. Here’s a breakdown of what’s available:

  • %year%: The year of the post in four digits, eg: 2025
  • %monthnum%: Month the post was published, in two digits, eg: 01
  • %day%: Day the post was published in two digits, eg: 02
  • %hour%: Hour of the day, the post was published, eg: 15
  • %minute%: Minute of the hour, the post was published, eg: 43
  • %second%: Second of the minute, the post was published, eg: 33
  • %post_id%: The unique ID of the post, eg: 123
  • %category%: A clean version of the category name (its slug). Nested sub-categories will appear as nested directories in the URL..
  • %author%: A sanitized version of the post author’s name.
  • %postname%: A clean version of the post or page title (its slug). For example, “This Is A Great Post!” becomes this-is-a-great-post in the URL.
  • %parent_postname%: Similar to %postname%, but uses the immediate parent page’s slug if a parent is selected.
  • %parents_postnames%: Similar to %postname%, but includes all parent page slugs if parents are selected.
  • %title%: The title of the post, converted to a slug. For example, “This Is A Great Post!” becomes this-is-a-great-post. Unlike %postname% which is set once, %title% automatically updates in the permalink if the post title changes (unless the post is published or the permalink is manually edited).
  • %ctax_TAXONOMY_NAME%: A clean version of a custom taxonomy’s name. Replace TAXONOMY_NAME with the actual taxonomy name. You can also provide a default slug for when no category/taxonomy is selected by using ?? (e.g., %ctax_type??sales% will use “sales” as a default).
  • %ctax_TAXONOMY_NAME_name%: The custom taxonomy term’s name (instead of its slug). Replace TAXONOMY_NAME with the actual taxonomy name. Supports a default value using ?? when no term is selected (e.g., %ctax_type_name??Sales%).
  • %ctax_parent_TAXONOMY_NAME%: Similar to %ctax_TAXONOMY_NAME%, but includes the immediate parent category/tag slug in the URL if a parent is selected.
  • %ctax_parent_TAXONOMY_NAME_name%: Similar to %ctax_TAXONOMY_NAME_name%, but includes the immediate parent term’s name if a parent is selected.
  • %ctax_parents_TAXONOMY_NAME%: Similar to %ctax_TAXONOMY_NAME%, but includes all parent category/tag slugs in the URL if parents are selected.
  • %ctax_parents_TAXONOMY_NAME_name%: Similar to %ctax_TAXONOMY_NAME_name%, but includes all parent term names if parents are selected.
  • %custom_permalinks_TAG_NAME%: Developers have the flexibility to define their own custom tags(replace _TAG_NAME with your desired name). To ensure these tags resolve to the correct permalinks, simply apply the custom_permalinks_post_permalink_tag filter.

Important Note: For new posts, Custom Permalinks will keep updating the permalink while the post is in draft mode, assuming a structure is defined in the plugin settings. Once the post is published or its permalink is manually updated, the plugin will stop automatic updates for that specific post.

Custom Permalinks: Fine-Tuning with Filters

Custom Permalinks offers a range of filters that empower developers to precisely control its behavior. You can explore all available filters, complete with example code snippets, in our GitHub repository.

For Assistance:

  • Premium Users: If you need assistance implementing these filters, please don’t hesitate to reach out to us via our Premium contact support.
  • Other Users: You can also directly reach out to the plugin author via LinkedIn.

Need Help or Found a Bug?

  • Support: For one-on-one email support, consider purchasing Custom Permalinks Premium. While some basic support may be provided on the WordPress.org forums, email support is prioritized for premium users.
  • Bug Reports: If you encounter a bug, please report it on GitHub. Make sure to provide complete information to reproduce the issue. GitHub is for bug reports, not general support questions.

If you experience any site-breaking issues after upgrading, please report them on the WordPress Forum or GitHub with detailed information. You can always revert to an older version by downloading it from https://wordpress.org/plugins/custom-permalinks/advanced/.

Installation

You have two ways to install Custom Permalinks:

From within WordPress

  1. Go to Plugins > Add New in your WordPress dashboard.
  2. Search for “Custom Permalinks”.
  3. Click “Install Now” and then “Activate” the plugin from your Plugins page.

Manually via FTP

  1. Download the custom-permalinks folder.
  2. Upload the custom-permalinks folder to your /wp-content/plugins/ directory.
  3. Activate Custom Permalinks through the “Plugins” menu in your WordPress dashboard.

FAQ

What happens to the original URL when I set a custom permalink?

Custom Permalinks automatically redirects the original (default) URL to your new custom permalink, so existing links, bookmarks, and search engine rankings keep working.

Will this affect my site’s SEO?

It shouldn’t hurt it — since the original URL redirects to the new one, search engines and existing backlinks continue to resolve correctly. Using clean, descriptive custom permalinks can also make your URLs more readable, which is generally good for SEO.

Can I set custom permalinks for categories and tags, not just posts and pages?

Yes. Custom Permalinks supports posts, pages, any public custom post type, and categories/tags (and other custom taxonomy terms).

Does it work with custom post types, like WooCommerce products?

Yes. You can set an individual custom permalink on any public custom post type, or define an automatic permalink structure for the entire post type from Settings > Custom Permalinks.

Is Custom Permalinks compatible with WPML or Polylang?

Yes, the plugin is compatible with both WPML and Polylang, including translated posts that each have their own custom permalink.

Can I let a non-administrator manage permalinks?

Yes. The plugin adds a dedicated Custom Permalinks Manager role (and matching capabilities) so you can let specific non-admin users view or edit permalinks without giving them full administrator access.

Can I use accented letters, uppercase letters, or extra hyphens in my permalinks?

By default, Custom Permalinks sanitizes permalinks the same way WordPress core does (lowercase, no accents, no repeated hyphens). Developers can lift these restrictions with the custom_permalinks_allow_accents, custom_permalinks_allow_caps, and custom_permalinks_redundant_hyphens filters. See the Advanced Customization and Filters section on GitHub.

Some page builders load their live/front-end preview in an iframe using a POST request carrying special values the builder needs (for example Cornerstone’s cs_preview_time). If that page also has a custom permalink, Custom Permalinks may redirect the request, and since redirects are followed as GET, the builder’s POST data is lost and the preview breaks.

You can tell Custom Permalinks to skip its redirect for that request with the custom_permalinks_avoid_redirect filter, added to your theme or a site-specific plugin:

add_filter( 'custom_permalinks_avoid_redirect', function( $permalink ) {
    if ( isset( $_POST['cs_preview_time'] ) ) { // Adjust to match the field your builder sends.
        return true;
    }
    return false;
} );

See the Advanced Customization and Filters section on GitHub for this and other available filters.

What happens to my custom permalinks if I deactivate or uninstall the plugin?

Deactivating the plugin keeps all your saved custom permalinks in the database — reactivating it restores them immediately. Uninstalling (deleting) the plugin permanently removes all saved custom permalinks and plugin settings, and your URLs will revert to WordPress’ default permalink structure.

My custom permalink isn’t saving, or the page isn’t redirecting — what should I check?

  • Make sure Settings > Permalinks isn’t set to “Plain”.
  • Confirm no other SEO/redirection plugin (Yoast, RankMath, Redirection, etc.) has a conflicting rule for the same URL.
  • Check that the permalink isn’t already used by another post — Custom Permalinks won’t apply a duplicate URL.
  • Still stuck? See “Need Help or Found a Bug?” above, or reach out via GitHub or Premium support.

Reviews

জুন 23, 2026
I have a website with thousands of posts on it, and using this for permalinks has caused a slew of issues over the years of me running it. Unfortunately, I’ve got little choice but to keep using it since it has all the data for my permalinks inside of it. The particular issue that I’m currently facing really hurts my website. It causes the inability to bulk edit posts properly. There is a bug in which the first post in the order of the ones I’ve selected has its permalink copied over the posts underneath it. So if I select a bunch of posts in the editor, with the intention of *just* changing tags, it’ll also copy the first post’s permalink to all the ones I’ve selected. When this happens, you have no choice but to go back and manually edit all of those permalinks back. This wastes hours of my time. I almost did this to a lot of pages on accident before I even noticed what happened. It’s hard to recommend something with such a glaringly bad bug. I’m not interested in going out of my way to purchase premium support for something that hasn’t been updated in nearly a year, either. I have nothing I can do except grit my teeth through this and press on. That’s hugely unacceptable in my eyes. I highly recommend skipping over this plugin and finding a different one. There’s plenty of others like it.
ফেব্রুয়ারি 21, 2024
Excellent plugin. I would really like to see categories included as well.
ডিসেম্বর 10, 2023
Once you have installed this plugin, there is no turning back. These redirections are causing SEO issues and Google won’t index my website because of them. I faced multiple URL crashes when I desactivated the plugin.
সব রিভিউ পড়ুন

ডেভেলপার এবং কন্ট্রিবিউটর

“Custom Permalinks” is open source software. The following people have contributed to this plugin.

কন্ট্রিবিউটর

“Custom Permalinks” has been translated into 18 locales. Thank you to the translators for their contributions.

Translate “Custom Permalinks” into your language.

ডেভেলপমেন্ট এ আগ্রহী?

Browse the code, check out the SVN repository, or subscribe to the development log by RSS.

Changelog

3.2.0 – Aug 20, 2026

Permalink Generation:
* Added support for name-based custom taxonomy permalink tags:
* %ctax_TAXONOMY_NAME_name%
* %ctax_parent_TAXONOMY_NAME_name%
* %ctax_parents_TAXONOMY_NAME_name%
* Use multiple custom taxonomies tags at the same time in permalink
* Updated documentation to describe the new tags and clarify the difference between slug-based and name-based taxonomy tags.

  • Bug:
    • Fixed a PHP warning (“Attempt to read property ‘term_id’ on null”) on tag/category archive pages in some setups. PR #138
    • Fixed an “Undefined array key _custom_permalinks_term_nonce warning when saving a category or tag without touching its Custom Permalink field.
    • Fixed the auto-generated slug silently failing to save on posts that didn’t yet have a post_name, when a permalink structure was set to auto-generate permalinks. PR #148
    • Fixed %parent_postname% and %parents_postnames% silently dropping the post’s own slug from the generated permalink when used without also including %postname% in the structure. PR #149
    • Fixed WPML internal links pointing to the original page instead of the translated page’s own custom permalink (e.g. links created with the Gutenberg link tool).
    • Fixed custom permalinks getting overwritten with another product’s permalink when bulk editing multiple products/posts in a single request.
    • Fixed the language directory getting duplicated (e.g. /de/de/your-slug/) in permalinks generated for WPML directory-based language negotiation, and hardened the WPML permalink filter against a non-string return value that could corrupt the REST API’s JSON response when saving a post from the Block Editor.
    • Fixed a stale permalink cache entry for permalinks with a trailing slash, which could cause a newly saved custom permalink to 404 until the cache expired. PR #153
    • Fixed translated pages resolving to the wrong language’s post (wrong-language redirects, 404s on a translation, editor opening the wrong translation) when two WPML/Polylang translations shared the same custom permalink outside of “different domain per language” mode.
    • Fixed WooCommerce My Account endpoints (e.g. edit-address, edit-account) redirecting back to the base My Account page instead of loading, when the My Account page has a custom permalink set.
    • Fixed emptying the Custom Permalink field and saving not removing the saved permalink.
    • Fixed a request that only differed from the saved permalink by a trailing slash failing to resolve — it now redirects to the canonical permalink instead.
    • Fixed the trailing-slash redirect ignoring the custom_permalinks_avoid_redirect filter, which could still break page builders’ front-end preview iframes (e.g. Cornerstone) after applying the documented workaround.

3.1.2 – Sep 24, 2025

3.1.1 – Sep 19, 2025

3.1.0 – Aug 01, 2025

Permalink Generation:

  • Resolved an issue where the custom_permalinks_generate_post_permalink function was creating duplicate permalinks with appended numbers when triggered programmatically. This ensures a unique, clean URL every time.
  • Updated the sanitize_text_field function to prevent the truncation of permalink tags, such as %category% and %day%, guaranteeing your custom permalink structure remains intact.

Performance:

  • The save_post hook will now only run on public post types. This change prevents unnecessary processing on post types like “Menus”, which can significantly improve performance on sites with complex configurations.

Maintenance:

  • Improved internationalization (I18N) support.
  • Fixed a bug where the cache group was not properly clearing when using the flush button.

Language:

  • Updated the plugin with the latest language packs.

3.0.1 – Jul 22, 2025

Fix PHP warning on url_to_postid() filter.

3.0.0 – Jul 22, 2025

This release of Custom Permalinks brings significant enhancements to post type permalink management, introduces new customization options, and refines the overall user and developer experience.

Added

  • Post Type Permalink Structures: Introduced robust functionality to define custom permalink structures for each public Post Type directly within the plugin settings. This allows for automatic URL generation based on predefined tags upon content creation, offering greater flexibility while still allowing manual edits.
  • New Available Permalink Tags: Expanded the list of dynamic tags that can be used in permalink structures, including:
    • %parent_postname%: For immediate parent page slugs.
    • %parents_postnames%: For all parent page slugs.
    • %title%: A dynamic slug that updates with post title changes (until published or manually edited).
    • %ctax_parent_TAXONOMY_NAME%: For immediate parent custom taxonomy slugs.
    • %ctax_parents_TAXONOMY_NAME%: For all parent custom taxonomy slugs.
    • %custom_permalinks_TAG_NAME%: Allows developers to define and resolve their own custom tags.
  • WP All Import Compatibility: Added support to generate/update permalinks when importing posts using the WP All Import plugin.
  • New Filter Examples: Included clear code examples for custom_permalinks_post_permalink_tag to set custom values from ACF fields, and for programmatically generating permalinks for single posts and entire post types.

Improved

  • Post Caching: Enhanced post caching mechanisms and optimized cache deletion upon updates for better performance.
  • Permalink Retrieval: Improved logic to allow fetching posts against customized permalinks.
  • Filter Documentation: Refined existing filter descriptions and improved code formatting for clarity.
  • Plugin Purpose Clarity: Updated documentation to explicitly state that original post URLs will automatically redirect to the customized URLs, ensuring seamless transitions.

Earlier versions

  • For the changelog of earlier versions, please refer to the separate changelog.txt file.