I’m trying to add url query parameters to all internal links inside a WordPress blog. For example, client lands on the blog with this link:
www.example.com/?p1=test&p2=test
I want the links inside the blog, for example a link to a post, to still have the query strings:
www.example.com/post1/?p1=test&p2=test
Is there is a way to do it?
The following is not a complete solution (i.e., as @cjbj mentioned, it won’t handle links in post content), but it will achieve what you want for any link whose URL is obtained (in WP Core, a theme or a plugin) via get_permalink() (including the output of wp_page_menu(), and kin).
$filters = array (
'post_link', // when post_type == 'post'
'page_link', // when post_type == 'page'
'attachment_link', // when post_type == 'attachment'
'post_type_link', // when post_type is not one of the above
) ;
foreach ($filters as $filter) {
add_filter ($filter, 'wpse_add_current_requests_query_args', 10, 3) ;
}
function
wpse_add_current_requests_query_args ($permalink, $post, $leavename)
{
if (!is_admin ()) {
// we only want to modify the permalink URL on the front-end
return ;
}
// for the purposes of this answer, we ignore the $post & $leavename
// params, but they are there in case you want to do conditional
// processing based on their value
return (esc_url (add_query_arg ($_GET, $permalink))) ;
}
Explanation
Before returning it’s result, get_permalink()
applies one of 4 filters (named in the $filters
array above) on the permalink it has generated. So, we hook into each of those filters.
The function we hook to these filters calls add_query_arg() to add any query args present in the current request (i.e., $_GET
).
Important Security Consideration
As mentioned in add_query_arg():
Important: The return value of add_query_arg() is not escaped by default. Output should be late-escaped with esc_url() or similar to help prevent vulnerability to cross-site scripting (XSS) attacks.
Calling esc_url() in wpse_add_current_requests_query_args()
is not what I would call “late-escaped” in all cases. But unfortunately, a number of WP Core funcs (e.g. Walker_Page::start_el(), which is ultimately called by wp_page_menu()
), don’t call esc_url()
on the return value of get_permalink()
, so we have to call it in our filter hook to be safe.