Subtle diagonal pinstripe pattern in light grey and cream, giving an impression of printed editorial paper

How to Rewrite WordPress URLs for Taxonomy Archives and Pagination

WordPress taxonomy archives can provide a clear path through a large site, but their default URLs are not always suitable for a production project. A structure such as /category/news/page/2/ may be adequate for a blog, while a WooCommerce catalogue, documentation library, or custom post type often needs more meaningful paths.

Changing the visible URL is only part of the task. WordPress must also register rewrite rules, recognise taxonomy query variables, generate working pagination links, and redirect older addresses when the structure changes. A reliable implementation keeps those layers aligned so visitors and search engines reach the intended archive without redirect chains or 404 errors.

Understand WordPress Rewrite Layers

A taxonomy archive is generated from a relationship between a taxonomy and its terms. Categories and tags are built in, while custom taxonomies might describe product brands, suburbs, documentation topics, or editorial subjects. When WordPress receives a request such as /topics/security/, its rewrite system translates that path into an internal query containing the taxonomy and term.

The rewrite process does not rename database values. It maps a human-readable URL to a query, usually through rules stored in the rewrite array. WordPress then selects an archive template such as taxonomy.php, taxonomy-topic.php, or archive.php. Pagination adds another path segment, commonly /page/2/, and must still resolve to the same taxonomy query with a different page number.

This distinction matters when debugging. A template can be correct while the rewrite rule is stale, or the URL can look correct while the query returns an empty result. Inspect the registered taxonomy, its rewrite settings, the generated links, and the final main query separately rather than treating every failure as a template problem.

Choose A Stable Taxonomy URL

Before writing PHP, decide whether the taxonomy should have a visible base. A URL such as /topic/wordpress/ is explicit and usually safer when the site contains several types of archive. A shorter path such as /wordpress/ may look cleaner, but it can collide with a page, post, custom post type, author archive, or another taxonomy term.

For a publishing site, /guides/php/ and /guides/php/page/2/ communicate the archive clearly. A product website might use /brand/acme/, while a local service directory could use /areas/newcastle/. Australian sites often use a .com.au domain with subdirectories that reflect the catalogue or region, so stable, descriptive slugs are generally easier to manage than clever shortened paths.

Use lowercase slugs, avoid unnecessary dates, and keep the base singular or plural consistently. If the taxonomy is called resource_topic, a public rewrite base of topics is perfectly reasonable. The internal name is for code; the rewrite slug is for visitors and search engines. Avoid changing that public base after launch unless redirects and a full crawl are part of the release plan.

A taxonomy base can also help prevent conflicts with existing pages. If the site publishes an article about wild reel odds, a dedicated archive path such as /stories/topic/odds/ keeps the content URL distinct from taxonomy URLs and reduces ambiguity in WordPress's request matching.

Register The Taxonomy Correctly

The most maintainable approach is to define the taxonomy during registration rather than editing generated rewrite rules manually. The rewrite argument controls the public base, while with_front determines whether the site-wide permalink prefix is included.

add_action( 'init', 'acme_register_topic_taxonomy' );

function acme_register_topic_taxonomy() {
    register_taxonomy(
        'resource_topic',
        array( 'resource' ),
        array(
            'labels' => array(
                'name'          => 'Topics',
                'singular_name' => 'Topic',
            ),
            'public'            => true,
            'hierarchical'      => true,
            'show_admin_column' => true,
            'show_in_rest'      => true,
            'rewrite'           => array(
                'slug'         => 'topics',
                'with_front'   => false,
                'hierarchical' => true,
            ),
        )
    );
}

With a post type named resource, this produces term URLs such as /topics/wordpress/. Because hierarchical is enabled, a child term may use a nested path such as /topics/development/php/. The taxonomy registration and the post type registration should run on every request before WordPress resolves the main query.

If the taxonomy is attached to a custom post type, set the post type's has_archive and rewrite values independently. A post archive at /resources/ does not automatically determine the taxonomy archive at /topics/. Keep each public namespace distinct, especially when a site has pages with common names such as news, shop, or events.

After changing rewrite arguments, flush rewrite rules once. Visit Settings → Permalinks and save without changing anything, or use WP-CLI:

wp rewrite flush

Do not flush rules on every request. Calling flush_rewrite_rules() inside a template or ordinary init callback creates unnecessary database writes and can slow the site. Plugin activation and deactivation hooks are appropriate places for an explicit flush when a plugin owns the taxonomy.

Make Pagination Resolve Reliably

WordPress normally creates taxonomy pagination when the main query has multiple pages. In a taxonomy template, use the query's pagination values rather than hard-coding links. the_posts_pagination() is usually preferable to assembling URLs manually because it respects the site's permalink settings and pagination base.

if ( have_posts() ) :
    while ( have_posts() ) :
        the_post();
        get_template_part( 'template-parts/content', get_post_type() );
    endwhile;

    the_posts_pagination(
        array(
            'mid_size'  => 2,
            'prev_text' => 'Previous',
            'next_text' => 'Next',
        )
    );
else :
    echo '<p>No resources were found.</p>';
endif;

For the example structure, the links should resolve to /topics/wordpress/page/2/, not to a query-string variation such as /topics/wordpress/?paged=2. Query-string pagination can work, but mixing formats makes canonical URLs, caching, analytics, and testing harder. If a custom loop is used, pass the correct paged value and ensure the query includes the expected max_num_pages.

Requirement Recommended implementation Typical failure
Taxonomy archive base Set rewrite['slug'] during registration Editing links only in the template
Pagination path Use WordPress pagination helpers Hard-coded /page/2/ URLs
Page number query Read get_query_var( 'paged' ) Reading only page for a normal archive
Rewrite refresh Flush after registration changes Flushing rules on every request
Canonical address Keep one preferred URL format Indexing both path and query-string versions
Custom archive loop Set paged and posts_per_page explicitly Every page showing the same posts

A common source of confusion is the difference between paged and page. paged is used for paginated archives and ordinary loops. page is commonly associated with paginated static content or a page template. On a taxonomy archive, inspect get_query_var( 'paged' ) first.

If pagination returns a 404 only on page two, test the rewrite rules before changing the query. A stale ruleset, an incorrect taxonomy base, or a server-level rewrite problem is often responsible. Apache must pass requests to index.php, while Nginx needs an equivalent try_files configuration.

Control Queries, Canonicals, And Redirects

Use the main taxonomy query wherever possible. WordPress has already determined the current term, post type, page number, and relevant archive flags. Replacing it with a secondary WP_Query can create mismatched pagination, duplicate database work, and incorrect canonical metadata.

When a custom loop is necessary, preserve the archive context and calculate its page number explicitly:

$paged = max( 1, get_query_var( 'paged' ) );

$resources = new WP_Query(
    array(
        'post_type'      => 'resource',
        'posts_per_page' => 12,
        'paged'          => $paged,
        'tax_query'      => array(
            array(
                'taxonomy' => 'resource_topic',
                'field'    => 'slug',
                'terms'    => get_queried_object()->slug,
            ),
        ),
    )
);

The pagination function should use $resources->max_num_pages, and the custom query should be reset with wp_reset_postdata(). If the archive shows twelve posts per page, the query and the pagination calculation must use the same value. Inconsistent limits can produce empty pages or links that claim more pages exist than the query can supply.

Canonical handling is equally important. A taxonomy term should have one preferred address, with old bases redirected using a permanent redirect. Avoid redirecting every paginated page to the first page. /topics/wordpress/page/2/ is a legitimate archive URL and should remain distinct from /topics/wordpress/.

For Australian businesses, this matters when an archive is linked from local campaigns, email newsletters, or paid search landing pages aimed at Sydney, Melbourne, Perth, or Brisbane. A clean path makes campaign reporting easier and avoids wasting crawl or advertising traffic through several redirects. The same principle applies when a site migrates from a staging domain before a public launch.

Account For Server And Caching Behaviour

WordPress rewrite rules operate inside the application, but the web server must first deliver the request to WordPress. A typical Apache setup uses the standard .htaccess front controller. Nginx commonly requires a rule such as:

location / {
    try_files $uri $uri/ /index.php?$args;
}

The exact server configuration depends on the hosting stack, PHP handler, and document root. A WordPress administrator on managed hosting may not have access to Nginx configuration, in which case the host needs to verify that nested paths ending in /page/2/ are routed to index.php. A server-level 404 cannot be repaired with a taxonomy template.

Caching can hide successful changes. Page caches, object caches, CDN rules, and security plugins may retain an old 404 or an outdated redirect. Purge the relevant layers after changing permalink settings, then test with a fresh browser session and command-line requests. On a site serving Australian customers from infrastructure in Sydney or Melbourne, CDN cache rules should also be checked at the edge rather than only on the origin server.

A useful diagnostic sequence is to request the first term page, the second page, a nonexistent term, and an old URL. Check the HTTP status, Location header, canonical link, title, breadcrumb, and post list. Tools used while following a WordPress developer event such as DevPulseCon resources can help inspect requests, but the core checks can be performed with browser developer tools and WP-CLI.

Test Taxonomy Archives Before Release

Build a small test matrix covering parent terms, child terms, empty terms, terms with accented characters, and terms containing hyphens. Confirm that each archive has the intended title and description, that child paths resolve correctly, and that pagination stops at the actual final page. Test logged-out visitors because administrator sessions can bypass some cache and security behaviour.

Use WP-CLI to inspect the result of registration and rewrite changes:

wp taxonomy list
wp rewrite list --format=table
wp post list --post_type=resource --taxonomy=resource_topic

The rewrite list should contain rules for the taxonomy base and its pagination pattern. If the rules are missing, registration may be running too late, the taxonomy may not be public, or a plugin may be unregistering and re-registering it with different arguments.

Search engines should see a 200 response for valid archive pages, a 404 for genuinely invalid terms, and a single canonical URL for each valid page. Check XML sitemaps, internal links, breadcrumbs, Open Graph URLs, and structured data after deployment. Pagination links generated by the theme should point to the same public format used in the taxonomy registration.

Finally, record the old URL pattern and redirect mapping before launch. A clear release checklist prevents a small permalink change from breaking indexed pages, bookmarked resources, or links in Australian business directories. Once the rewrite rules, templates, server routing, and cache layers agree, taxonomy archives and their pagination can remain stable as the site grows.