I am dividing my page templates into linkable regions. I'd like to be able to use clean urls to do so.

My page urls look like so www.example.com/page-name/?section=example

I'd like to rewrite the url to www.example.com/page-name/example

I've scoured for an answer but I'm not quite getting there.


function thick_section_rewrite(){

    add_rewrite_tag([what goes here?], '([^&/]+)');
    add_rewrite_rule( [what goes here?], '?section=$matches[1]', 'top' );


What do I put in that first param of add_rewrite_rule and add_rewrite_tag?

1 Answer 1


The issue with your desired structure is that adding a rewrite rule to intercept anything appended to a page URL will override and break child pages. In your example:


is example a section, or a child page of page-name? It's not so simple to accommodate both cases.

A very quick and easy solution to this is to add something unique in the middle of the URL to signal a section rather than a child page. This can be done via add_rewrite_endpoint, and WordPress will take care of generating the proper rewrite rules to make it work.

function wpa_rewrite_endpoint(){
    add_rewrite_endpoint( 'section', EP_PAGES );
add_action( 'init', 'wpa_rewrite_endpoint' );

Now any level of page can have section/section-name/ appended, for example:




and that value can then be accessed via get_query_var:

$this_section = get_query_var( 'section' );


Another possible, similar, option, depending on your requirements- If all of your section names are fixed, for example, there are only 3 potential sections: introduction, body, and conclusion, you can use add_rewrite_endpoint for each and instead name them the names of the sections:

function wpa_rewrite_endpoint(){
    add_rewrite_endpoint( 'intro', EP_PAGES );
    add_rewrite_endpoint( 'body', EP_PAGES );
    add_rewrite_endpoint( 'conclusion', EP_PAGES );
add_action( 'init', 'wpa_rewrite_endpoint' );

You can then have URLs:


Determining what section is loaded is a bit different here though, as you now don't have anything for the value of your query vars, they're all empty, so you'll have to check if they exist in the array of query vars.

if( array_key_exists( 'intro', $wp_query->query_vars ) ){
    echo 'intro requested!';
  • Ah, I see! Thanks for taking the time @Milo. This is enlightening. I hadn't considered clashes with child pages. I'm going to sue the method from your later edit. It's just simpler.
    – Niels
    Jul 25, 2013 at 1:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.