This is somewhat possible and not possible,
First you cannot get a URL structure like domain/postname/custom_var and play with its rewrite rule, the rewrite rule for this is use by wordpress default URL structure and messing with it could cause a lot of problems
.e.g
domain/category/cat-1 - for category
domain/taxonomy/tax-1 - for taxonomy
domain/archive/2022 - for archive
and so on.....
If you dump the WP_Rewrite Object, you'll see under the rules property this has already been handled [[^/]+/([^/]+)/?$] => index.php?attachment=$matches[1] and the url with structure domain/sub-1/sub-2/ will do index.php?attachment=$matches[1] request
On the other hand, you could add a rewrite tag e.g.
add_rewrite_tag('%custom_var%', '([^/]+)', 'custom_var=');
then use that tag on your post permalink /%postname%/%custom_var%/
but this set-up would break your first goal and this URL structure domain/postname would no longer work.
However, there's another option you can do, and that is to add a pre-fix on your 2nd level path and add rewrite rule matching that url structure prefix,
Here's a whole example
create a rewrite rule that matches domain/***/s-***/ and set a custom query
add_action('init', function() {
add_rewrite_rule('([^/]+)?/s-([^/]+)/?$','index.php?pname=$matches[1]&custom_var=$matches[2]','top');
});
(you need flush your rewrite rule after adding that code above, simply go to permalinks, switch it plain, then swtich it back to postname) or just run this function flush_rewrite_rules() you can then dump $wp_rewrite global variable and verify your rule is their
and set those query on wordpress query vars so you can simply access them
add_filter( 'query_vars', function( $vars ) {
$vars[] = 'pname';
$vars[] = 'custom_var';
return $vars;
});
Now the exciting part; modify the global $post and $wp_query variable when query var pname exist.
Something like this would do
add_action( 'wp', function() {
global $wp, $wp_query, $post; //define global variable
//include $wp variable so you can check the url request
// check if pname var is set
if ( isset( $wp_query->query['pname'] ) ) {
// build query argument
$args = [
'page' => '', //assuming its a page
'pagename' => $wp_query->query['pname']
];
// run the query and assign it to $wp_query global variable
$wp_query = new WP_Query( $args );
// modify is_single wp_query param and tell it its not a post
$wp_query->is_single = '';
// modify is_page wp_query param and tell it its a page
$wp_query->is_page = 1;
//assign (1st) found post to global post variable
$post = $wp_query->posts[0];
//done
}
// Test Dump
//echo '<pre>', print_r($wp_query, 1), '</pre>';
//echo '<pre>', print_r($wp_rewrite, 1), '</pre>';
//echo '<pre>', print_r($wp, 1), '</pre>';
});
So if you try to access.
domain/page-1/s-test
it should display the page as long as page-1 is a post object