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:


I want the links inside the blog, for example a link to a post, to still have the query strings:


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) ;

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))) ;


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.

| improve this answer | |
  • Thanks @Paul 'Sparrow Hawk' Biron , this code should be added to functions? – Fadi Mar 19 '17 at 19:47
  • @Fadi: Personally, I always put this kind of code (i.e., code that is not directly related to how a site looks) into a Site-specific Plugin. But functions.php is fine as well. – Paul 'Sparrow Hawk' Biron Mar 19 '17 at 20:04
  • @Fadi I know it's long after you accepted my answer, but I just realized that I made a mistake: I had the conditions under which post_link and post_type_link were applied backwards. I just edited my answer to correct this. – Paul 'Sparrow Hawk' Biron Apr 2 '17 at 14:15
  • 1
    +1 for details, but you have error in code, extra } after foreach. – Scott Apr 2 '17 at 15:37

You can access the query string with the global variable $_SERVER, with $_SERVER['QUERY_STRING']. The next step is to append this to all internal links in your blog. This is slightly more difficult, because the links may be hiding anywhere.

Links that are hiding in post content can be tracked down and adapted with the_content filter. Here is an example for a slightly different use of that filter only on internal links.

Permalinks in themes and plugins should pass the post_link filter, which you can also use to append the string.

| improve this answer | |
  • Hi @cjbj , let say I want only links of the theme, what should I do inside post_link exactly? – Fadi Mar 18 '17 at 20:59
  • Up-vote for explanation, but can't I get query string from $_GET too? or does WP remove that? – Scott Apr 2 '17 at 15:39

So you want to "keep" the variable value? Maybe you're best to set a cookie? This would probably make things much easier and cleaner. Have a look at this article, it seems to have everything you need to set a cookie: https://premium.wpmudev.org/blog/set-get-delete-cookies/ and you should be able to use get_query_var to get the variable from the URL: https://codex.wordpress.org/Function_Reference/get_query_var

| improve this answer | |
  • I'm currently using cookies, but it's buggy since I also use W3 Total Cache, and it doesn't update the links dynamically. – Fadi Mar 18 '17 at 20:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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