WordPress’s URL system is one of its most powerful features. Clean URLs — /blog/my-post instead of /?p=123 — improve SEO, user experience, and content organization. Behind the scenes, WordPress’s Rewrite API translates these clean URLs into the database queries that serve the right content. Understanding how rewrite rules work is essential for any plugin that introduces new URL structures.
This guide covers how WordPress rewrite rules and permalinks work, from the Rewrite API to custom URL structures for plugins.
How Permalinks Work
Permalinks are the permanent URLs to your individual posts, pages, and other content. WordPress uses a combination of Apache mod_rewrite (or Nginx equivalent) and PHP-based rewriting to translate clean URLs into WordPress queries. The .htaccess file contains the Apache rewrite rules that direct all requests to WordPress’s index.php file.
WordPress then parses the requested URL, matches it against registered rewrite rules, identifies the matched rule’s query variables, and runs the appropriate WordPress query. The entire process happens in milliseconds, but understanding it is crucial for debugging URL issues.
The Rewrite API
The Rewrite API is the set of functions WordPress provides for managing URL structures. add_rewrite_rule() registers a new rewrite rule, mapping a URL pattern to query variables. add_rewrite_tag() registers a new query variable that can be used in rewrite rules. flush_rewrite_rules() rebuilds the rewrite rules array — call this only during plugin activation or deactivation, not on every page load.
Rewrite rules are stored in the database as serialized arrays. They’re regenerated when permalinks are saved or when a plugin requests a flush. Flushing rewrite rules is an expensive operation, so do it sparingly.
Adding Custom Rewrite Rules
To add a custom URL structure for your plugin, use add_rewrite_rule() with a regular expression matching your URL pattern and an array of query variables. Register your rule early — during the init hook — so it’s available when WordPress parses the request.
Test your rewrite rules thoroughly. Use the Rewrite Rules Inspector plugin to see all registered rules and verify yours is in the list. Test URLs in your browser to ensure they’re matched by your rule and serve the expected content.
Custom Post Type URLs
Custom post types automatically get their own URL structure based on the rewrite parameter in register_post_type(). You can customize the URL slug, add a front prefix, and control whether the URL includes the post name. For hierarchical custom post types, WordPress supports nested URLs that mirror the page hierarchy.
When you register a custom post type, call flush_rewrite_rules() during plugin activation to register the new rewrite rules. call it again during deactivation to clean up.
Common Rewrite Issues
The most common rewrite issue is the 404 error on custom URL structures. This usually means the rewrite rules haven’t been flushed after registering new rules — go to Settings > Permalinks and click Save to trigger a flush. Another common issue is rule priority — more specific rules should be registered before less specific ones. Rewrite rules are evaluated top to bottom, and the first match wins.
Query variable collisions can also cause issues. If two plugins use the same query variable name, they’ll conflict. Always prefix your query variables with a unique identifier.
The Bottom Line
WordPress rewrite rules transform ugly query-string URLs into clean, SEO-friendly permalinks. The Rewrite API lets you add custom URL structures for your plugin’s content. Register rules during the init hook, flush rewrite rules during activation and deactivation, and test your rules thoroughly. Clean URLs are a hallmark of professional WordPress development.
