How to filter the custom permalinks format?

Permalink Manager allows you to filter the default custom permalinks for both post types and taxonomies programmatically. This might be handy if you want the permalink format to be determined by a variable such as the assigned term, language, custom field, or another parameter

Permalink Manager, as opposed to the native permalink system, allows you greater control when it comes to rewriting your URL structures. The plugin's filters may be highly useful if you want to set different/conditional permastructures based on the provided categories, post publishing date, author, title, or other criteria.

Some of the functionalities presented in this article are not available in free version (Permalink Manager Lite).

Buy Permalink Manager Pro

You may programmatically change the default permalink formats by using the plugin hooks described below. Normally, the plugin uses the user-specified permalink formats provided in the "Permastructure" settings to generate new permalinks. If you want to make certain permalinks different when a specific condition is satisfied, just use the filters and adapt them to your requirements.

Basically, there are two methods to programmatically change the default custom permalinks. You may either filter the raw permastructure format that contains the tags such as %postname% or %category%. The alternative way is to change the final permalink after the permastructure tags are dynamically changed with distinct values for each post/term.

Keep in mind that your new, customized permalink formats will be used by default only for newly created content. The new programmatically updated formats may be applied to existing items when the permalinks are regenerated.

New permalink formats and existing content

The default permalinks mentioned in this article are used only for the new posts & terms permalinks. To apply the new permalink formats to existing items please use "Regenerate/reset" functionality.

The filter below may be handy if you wish to, for example, use a different URL structure for posts linked to certain categories. Similarly, instead of registering new post types or taxonomies only to give them alternative URLs depending on the circumstances, you may dynamically generate permalink bases.

A sample permastructure
Example permalink format (Tools -> Permalink Manager -> Permastructures)
permalink_manager_filter_permastructure($permastructure, $term_or_post)
Variable Description
$permastructure The permastructure string used when default custom permalink is generated (string)
Example input: store/%product_cat%/%product%
$term_or_post Post or term object (WP_Post|WP_Term)

The aforementioned filter may be used to dynamically update the generic permalink format, which is made up of specialized infrastructure tags (that are formatted in this manner: %postname%, %category%). When a post or term permalink is generated, the permastructure tags are dynamically replaced with actual data.

If necessary, you may update the default version of the custom permalink after the permastructure tags have been populated by using the filters mentioned below. One example of how this approach may be used is to automatically truncate the permalink if it becomes too lengthy.

In general, "default permalinks" are the individually processed version of generic permastructure formats. Only new posts and terms use them by default in normal circumstances. If you use the "Regenerate/reset" tool, they will also be used for existing items.

How can I programmatically modify post permalinks?

permalink_manager_filter_default_post_uri($default_uri, $native_slug, $post, $slug, $native_uri)
Variable Description
$default_uri Default custom peramlink based on your Permastructure settings (string)
Example input: https://example.com/men/clothes/shirts/jersey-cotton-shirt
$native_slug Native, unfiltered post’s slug. It may differ from slug defined with $slug variable if “Force custom slugs” is enabled in Permalink Manager settings (string)
$post Post object (WP_Post)
$slug Slug used normally by Permalink Manager to generate a custom permalink (string)
$native_uri To target only the custom permalinks and not the native ones, check if its value is set to "false" (boolean)

How can I programmatically modify term permalinks?

permalink_manager_filter_default_term_uri($default_uri, $native_slug, $term, $slug, $native_uri)
Variable Description
$default_uri Default custom peramlink based on your Permastructure settings (string)
Example input: https://example.com/women/clothes/dresses/
$native_slug Native, unfiltered post’s slug. It may differ from slug defined with $slug variable if “Force custom slugs” is enabled in Permalink Manager settings (string)
$term Term object (WP_Term)
$slug Slug used normally by Permalink Manager to generate a custom permalink (string)
$native_uri To target only the custom permalinks and not the native ones, check if its value is set to "false" (boolean)

Examples

Please keep in mind that the examples in this post have been purposefully simplified. You may totally modify the function's code and adjust the parameters or conditions used inside it.

How to truncate the custom permalinks?

One of the most interesting uses of above hooks would be to shorten the length of the slugs. In particular, you may restrict the number of words in each slug that is the part of the custom permalink.

For example:

http://example.com/a-very-long-slug-with-seven-words/slug-with-exactly-five-words/another-pretty-long-sentence-that-should-be-shorten

will be shorten to:

http://example.com/a-very-long-slug-with/slug-with-exactly-five-words/another-pretty-long-sentence-that

The snippet shown in following example sets the maximal number of words to 5 but you can simply modify the limit in $max_words variable.

function pm_limit_slugs_length($uri) {
$max_words = 5; // If any part of URI contains more than 5 words, the slug will be limited to first 5 words
$new_title = '';
$slugs = explode('/', $uri);
for($i=0, $count = count($slugs); $i < $count; $i++) { $slug = $slugs[$i]; $words = explode('-', $slug); $new_title .= "/"; if(count($words) > $max_words) {
$new_title .= implode("-", array_slice($words, 0, $max_words));
} else {
$new_title .= $slug;
}
}
// Remove trailing slashes
$new_title = trim($new_title, "/");
return $new_title;
}
add_filter('permalink_manager_filter_default_post_uri', 'pm_limit_slugs_length', 99);
add_filter('permalink_manager_filter_default_term_uri', 'pm_limit_slugs_length', 99);

There are many compelling arguments for transliterating your WordPress permalinks. According to some experts, URL romanization may have a favorable impact on SEO and search engine rankings. Furthermore, international visitors will find it easier to browse via understandable URLs that only include Latin characters.

Although several WordPress plugins allow for the transliteration of WordPress slugs, most of them are either limited or no longer maintained. Using the Permalink Manager plugin, you can easily convert Greek, Bulgarian, Russian and Serbian Cyrillic letters to their Latin equivalents in your WordPress permalinks. To have the plugin transliterate URLs, you must use a custom code snippet.

/**
* A. Russian
*/
function pm_ru2lat($str) {
$tr = array(
"А"=>"a", "Б"=>"b", "В"=>"v", "Г"=>"g", "Д"=>"d",
"Е"=>"e", "Ё"=>"yo", "Ж"=>"zh", "З"=>"z", "И"=>"i",
"Й"=>"j", "К"=>"k", "Л"=>"l", "М"=>"m", "Н"=>"n",
"О"=>"o", "П"=>"p", "Р"=>"r", "С"=>"s", "Т"=>"t",
"У"=>"u", "Ф"=>"f", "Х"=>"kh", "Ц"=>"ts", "Ч"=>"ch",
"Ш"=>"sh", "Щ"=>"sch", "Ъ"=>"", "Ы"=>"y", "Ь"=>"",
"Э"=>"e", "Ю"=>"yu", "Я"=>"ya", "а"=>"a", "б"=>"b",
"в"=>"v", "г"=>"g", "д"=>"d", "е"=>"e", "ё"=>"yo",
"ж"=>"zh", "з"=>"z", "и"=>"i", "й"=>"j", "к"=>"k",
"л"=>"l", "м"=>"m", "н"=>"n", "о"=>"o", "п"=>"p",
"р"=>"r", "с"=>"s", "т"=>"t", "у"=>"u", "ф"=>"f",
"х"=>"kh", "ц"=>"ts", "ч"=>"ch", "ш"=>"sh", "щ"=>"sch",
"ъ"=>"", "ы"=>"y", "ь"=>"", "э"=>"e", "ю"=>"yu",
"я"=>"ya"
);
return strtr($str, $tr);
}
function pm_transliterate_russian($slug) {
return pm_ru2lat($slug);
}
add_filter('permalink_manager_filter_default_post_uri', 'pm_transliterate_russian', 999);
add_filter('permalink_manager_filter_default_term_uri', 'pm_transliterate_russian', 999);
/**
* B. Bulgarian
*/
function pm_bg2lat($str) {
$tr = array(
"а"=>"a", "б"=>"b", "в"=>"v", "г"=>"g", "д"=>"d",
"е"=>"e", "ж"=>"zh", "з"=>"z", "и"=>"i", "й"=>"y",
"к"=>"k", "л"=>"l", "м"=>"m", "н"=>"n", "о"=>"o",
"п"=>"p", "р"=>"r", "с"=>"s", "т"=>"t", "у"=>"u",
"ф"=>"f", "х"=>"h", "ц"=>"ts", "ч"=>"ch", "ш"=>"sh",
"щ"=>"sht", "ъ"=>"a", "ь"=>"y", "ю"=>"yu", "я"=>"ya",
"А"=>"a", "Б"=>"b", "В"=>"v", "Г"=>"g", "Д"=>"d",
"Е"=>"e", "Ж"=>"zh", "З"=>"z", "И"=>"i", "Й"=>"y",
"К"=>"k", "Л"=>"l", "М"=>"m", "Н"=>"n", "О"=>"o",
"П"=>"p", "Р"=>"r", "С"=>"s", "Т"=>"t", "У"=>"u",
"Ф"=>"f", "Х"=>"h", "Ц"=>"ts", "Ч"=>"ch", "Ш"=>"sh",
"Щ"=>"sht", "Ъ"=>"a", "Ь"=>"y", "Ю"=>"yu", "Я"=>"ya"
);
return strtr($str, $tr);
}
function pm_transliterate_bulgarian($slug) {
return pm_bg2lat($slug);
}
add_filter('permalink_manager_filter_default_post_uri', 'pm_transliterate_bulgarian', 999);
add_filter('permalink_manager_filter_default_term_uri', 'pm_transliterate_bulgarian', 999);
/**
* C. Serbian
*/
function pm_srb2lat($str) {
$tr = array(
"А"=>"a", "Б"=>"b", "В"=>"v", "Г"=>"g", "Д"=>"d",
"Ђ"=>"dj", "Е"=>"e", "Ж"=>"z", "З"=>"z", "И"=>"i",
"Ј"=>"j", "К"=>"k", "Л"=>"l", "Љ"=>"lj", "М"=>"m",
"Н"=>"n", "Њ"=>"nj", "О"=>"o", "П"=>"p", "Р"=>"r",
"С"=>"s", "Ш"=>"s", "Т"=>"t", "Ћ"=>"c", "У"=>"u",
"Ф"=>"f", "Х"=>"h", "Ц"=>"c", "Ч"=>"c", "Џ"=>"dz",
"а"=>"a", "б"=>"b", "в"=>"v", "г"=>"g", "д"=>"d",
"ђ"=>"dj", "е"=>"e", "ж"=>"z", "з"=>"z", "и"=>"i",
"ј"=>"j", "к"=>"k", "л"=>"l", "љ"=>"lj", "м"=>"m",
"н"=>"n", "њ"=>"nj", "о"=>"o", "п"=>"p", "р"=>"r",
"с"=>"s", "ш"=>"s", "т"=>"t", "ћ"=>"c", "у"=>"u",
"ф"=>"f", "х"=>"h", "ц"=>"c", "ч"=>"c", "џ"=>"dz",
"Ња"=>"nja", "Ње"=>"nje", "Њи"=>"nji", "Њо"=>"njo", "Њу"=>"nju",
"Ља"=>"lja", "Ље"=>"lje", "Љи"=>"lji", "Љо"=>"ljo", "Љу"=>"lju",
"Џа"=>"dza", "Џе"=>"dze", "Џи"=>"dzi", "Џо"=>"dzo", "Џу"=>"dzu",
);
return strtr($str, $tr);
}
function pm_transliterate_serbian($slug) {
return pm_srb2lat($slug);
}
add_filter('permalink_manager_filter_default_post_uri', 'pm_transliterate_serbian', 999);
add_filter('permalink_manager_filter_default_term_uri', 'pm_transliterate_serbian', 999);
/**
* D. German
*/
function pm_germanlat($str) {
$tr = array(
"ä"=>"a", "Ä"=>"a", "Ö"=>"o", "ö"=>"o", "ü"=>"u",
"Ü"=>"u", "ß"=>"ss", "ẞ"=>"ss"
);
return strtr($str, $tr);
}
function pm_transliterate_german($slug) {
return pm_germanlat($slug);
}
add_filter('permalink_manager_filter_default_post_uri', 'pm_transliterate_german', 999);
add_filter('permalink_manager_filter_default_term_uri', 'pm_transliterate_german', 999);
/**
* E. Greek
*/
function pm_greeklat($str) {
$tr = array(
"Α"=>"a", "Ά"=>"a", "Β"=>"v", "Γ"=>"g", "Δ"=>"d",
"Ε"=>"e", "Έ"=>"e", "Ζ"=>"z", "Η"=>"i", "Ή"=>"i",
"Θ"=>"th", "Ι"=>"i", "Ί"=>"i", "Ϊ"=>"i", "ΐ"=>"",
"Κ"=>"k", "Λ"=>"l", "Μ"=>"m", "Ν"=>"n", "Ξ"=>"x",
"Ο"=>"o", "Ό"=>"o", "Π"=>"p", "Ρ"=>"r", "Σ"=>"s",
"Τ"=>"t", "Υ"=>"y", "Ύ"=>"y", "Ϋ"=>"y", "ΰ"=>"y",
"Φ"=>"f", "Χ"=>"ch", "Ψ"=>"ps", "Ω"=>"o", "Ώ"=>"o",
"α"=>"a", "ά"=>"a", "β"=>"v", "γ"=>"g", "δ"=>"d",
"ε"=>"e", "έ"=>"e", "ζ"=>"z", "η"=>"i", "ή"=>"i",
"θ"=>"th", "ι"=>"i", "ί"=>"i", "ϊ"=>"i", "κ"=>"k",
"λ"=>"l", "μ"=>"m", "ν"=>"n", "ξ"=>"x", "ο"=>"o",
"ό"=>"o", "π"=>"p", "ρ"=>"r", "σ"=>"s", "ς" => "s",
"τ"=>"t", "υ"=>"y", "ύ"=>"y", "ϋ"=>"y", "φ"=>"f",
"χ"=>"ch", "ψ"=>"ps", "ω"=>"o", "ώ"=>"o"
);
return strtr($str, $tr);
}
function pm_transliterate_greek($slug) {
return pm_greeklat($slug);
}
add_filter('permalink_manager_filter_default_post_uri', 'pm_transliterate_greek', 999);
add_filter('permalink_manager_filter_default_term_uri', 'pm_transliterate_greek', 999);
/**
* F. Arabic
*/
function pm_arabic2lat($str) {
$tr = array(
"ا" => "a", "ب" => "b", "ت" => "t", "ث" => "th", "ج" => "j",
"ح" => "h", "خ" => "kh", "د" => "d", "ذ" => "dh", "ر" => "r",
"ز" => "z", "س" => "s", "ش" => "sh", "ص" => "s", "ض" => "d",
"ط" => "t", "ظ" => "z", "ع" => "a", "غ" => "gh", "ف" => "f",
"ق" => "q", "ك" => "k", "ل" => "l", "م" => "m", "ن" => "n",
"ه" => "h", "و" => "w", "ي" => "y", "ة" => "h", "ء" => "a",
"آ" => "aa", "ؤ" => "w", "ئ" => "y", "ئ" => "y", "أ" => "a",
"إ" => "i"
);
return strtr($str, $tr);
}
function pm_transliterate_arabic($slug) {
return pm_arabic2lat($slug);
}
add_filter('permalink_manager_filter_default_post_uri', 'pm_transliterate_arabic', 999);
add_filter('permalink_manager_filter_default_term_uri', 'pm_transliterate_arabic', 999);
Go up