Support » Developing with WordPress » Add to end of esc_url

  • I’m currently using this code to get the URL of the category page I’m on.

    <?php $categories = get_the_category();
    if ( ! empty( $categories ) ) {
        echo '<a href="' . esc_url( get_category_link( $categories[0]->term_id ) ) . '">' . hiking . '</a>';

    It returns this URL:
    I want to add to end like this:

    Basically, I’m trying to make filters for the category china using other categories.

Viewing 8 replies - 1 through 8 (of 8 total)
  • Moderator bcworkz


    Sure, you can do that. Of course WP will need some help in knowing how to handle that. That is done through the “pre_get_posts” action. Your callback would extract the terms and construct a proper tax_query argument, as well as setting to empty strings any taxonomy related query vars that WP thought it needed because tax_query will cover everything taxonomy related in one (possibly elaborate) argument.

    I’m a little uneasy with multiple terms in one permalink element. In many ways /places-to-go/asia/china/hiking/ would be better, except you’ll then need to setup rewrite rules to tell WP how to handle the extra elements. But if you do that, you may not need the “pre_get_posts” callback.

    My own inclination would be to leave the URL itself alone and add query args by using add_query_arg(). You would then end up with something like /places-to-go/asia/china/?activity=hiking+equestrian+markets as an example with multiple added terms. This way, the URL itself remains a valid URL without needing to do anything. In the previous schemes, without doing something the URL will return “nothing found” because it’s invalid for the default WP. Of course if you did nothing with my scheme, the query args would be ignored.

    Some say query args are bad for SEO. That may be true, but it depends on what is important to index. Just the China category, or is the hiking category important? At least with Google’s Search Console, you can register query args as URL parameters so Googlebot will know how to treat the added data.

    With the query arg scheme using my example URL, you need to add “activity” to the query var whitelist by hooking “query_vars” and adding it to the passed array. You also still need to hook “pre_get_posts” to build a proper tax_query argument as previously described.

    Hi @bcworkz, thanks for responding. I probably didn’t explain myself very well. The link already works. I can type it in my browser and I get posts only if they are assigned to both categories, china and hiking. I didn’t realize I could even do that until I saw this post:

    So, what I’m trying to do is include a few different links in my category template. I figured if I can make a link that returns the current category page and then appends something like “+hiking” on the end it would make it so I didn’t have to create separate category templates for each category. I just want to append my activity categories to my destination categories.

    But now as I say this I think I just realized that when they click through to that link the other links would no longer be valid as they would return something like

    I don’t know, maybe I’m going about this the wrong way and using the query args would be a better solution. I’m really trying to make my navigation on my site a little more friendly. Could you point my toward some examples, I’m not sure I know how to fully implement that.


    Moderator bcworkz


    Oh, right. It’d totally escaped me that the + syntax would work like that! Args can be passed like that to new WP_Query instances, so of course they should work as permalink terms. Since I never use that syntax, it drew a blank. For some reason, I’m still a bit uneasy with this syntax. I think it could have SEO issues much like query args are said to be, except there is no mechanism to declare them to Google. Or I could be wrong and search bots understand the syntax perfectly. IDK.

    You shouldn’t need to create category templates for every category to achieve what you want regardless of what scheme you end up with. As long as your scheme is logical so that it can be encoded, one template should suffice. It’s possible to strip the + categories off of the current link and replace them with other categories if related links is all you’re after. But how would the template code know which categories to append?

    Where there’s a will, there’s a way. For example, which to append could be managed in meta data, either the post’s or the category term’s, depending on how you want to go about it. I think maybe why I’m uneasy about asia+hiking and the like is the categories are unrelated, location+activity. I have the urge to make a different taxonomy. Perhaps you already have in a way. Maybe hiking, sightseeing, etc. are children of an activity category. That would help, but they shouldn’t then be subordinate to places-to-go in a permalink, at least IMO.

    As long as it’s working the way you want, it doesn’t matter what I think. But is it? What really should matter is what sort of user experience are you after? The scheme should fit that. Not what you can easily make work. From that perspective, would it make more sense for activities on a location page to be more like a filter of current results instead of links to specific activities for the location? A series of checkboxes perhaps, the more that are selected, the greater the results?

    That’s very different query-wise because that is OR logic. Generally, WP always defaults to AND. When more than one activity is selected, should the results be greater or fewer? When thought of as filter terms, I think the query arg/URL parameter scheme starts to make more sense. Whether these are a different taxonomy or not doesn’t matter too much, though it affects how the scheme is implemented.

    Another factor is how much data would need to be updated if a different taxonomy were introduced. It could all be done by a one time custom script, so whether there are a dozen or a thousand doesn’t matter much, except manually updating a few may be easier than writing a script.

    The scheme could conceivably be reversed. Someone could request posts by activity, then filter by location. It gets complicated if there are more than location and activity categories. That would not mean it’s not possible or shouldn’t be done. Always go back to what is the intended user experience. Whatever that is, there ought to be a way to accommodate that. Don’t get caught up in how to accomplish something. I can tell you how to do that. I cannot tell you what your user experience ought to be. You tell me 🙂

    I know you simply wish to improve navigation, not overhaul the entire taxonomy scheme. Part of having clear navigation is having clear organization. What may seem like a major overhaul may not be that big a deal if the changes can be scripted. What you currently have may be fine. I’ve no idea what the overall nature of your data is. You asked for examples, but it’s difficult to make suggestions without understanding the dataset.

    Let’s try this. What would you ideally like to do? Forget about technicalities of how to implement it. In the end, you may not get what you really want, but it gives me an idea of your true goals. If they are not possible for some reason, I can probably suggest something fairly close. As it is now, I’m not even sure what to suggest.

    OK, you gave me a lot to think about. LOL, thanks for that. My two main categories are Places to Go (All the Destinations) and Things to do (All the Activities) Well, you can get a quick look at my category structure here if you care to. My basic thought is it’s too much. For instance, just viewing hiking and seeing posts from all over the world or just viewing china and seeing posts about anything and everything don’t really help anyone.

    From what you said I think this “activities on a location page to be more like a filter of current results instead of links to specific activities for the location? A series of checkboxes perhaps, the more that are selected, the greater the results?” may be a better solution.

    Like if someone arrived on the China Category by default all posts would show up but there would be some empty check-boxes that you could select and then hit a button that said “filter results” or something.

    Thanks again for helping me!

    Moderator bcworkz


    Nice site! Thanks for the link.

    I hope I haven’t overstepped reasonable bounds in suggesting things well beyond what your original question covered. I get the sense you appreciate the suggestions. It’s not my intention to make more work for you. I see opportunities for improvement and I can’t seem to not say something. Always feel free to tell me “No, I don’t want to go there, let’s focus only on X.” That would be totally fine.

    That said, yes, I think a post filter would be a great feature. I could see replacing the right hand categories widget with a filter. The categories are essentially the same as the left hand navigation, so is redundant. It’s a little confusing because one would expect the categories to be something else since they both appear on one page. But then we get the same thing regardless of which side we pick from. There’s no reason there couldn’t be both filters ans category picks on the right, but I don’t see the point. If anything, it would be even more confusing.

    Being in a sidebar area, it’s natural to look to widgets, but widgets are not absolutely required. You could instead modify the sidebar template to output the filter options before doing any widgets. Coding widgets does add some complexity, but it’s mainly organizing the same code somewhat differently. Naturally, creating a widget makes it easier to rearrange sidebar content in the future.

    Before getting into what’s required to implement filters, it might be a good idea to see if there are any plugins that provide similar filtering widgets. No use reinventing something already available! I suspect, due to the conditional nature of which categories are output, that such a plugin may not be available.

    Which filter options are presented would be dependent on the current page content. The best way to determine that is to use get_queried_object(), which returns the main WP_Query object that was requested. If your templates are using custom queries, something else would need to be figured out. Once the query is known, the proper set of categories can be output as checkbox form elements. Unless you want to get into fully interactive Ajax techniques, you will need an “Apply” button to have the form request a new set of posts matching the criteria.

    Ideally, the form request would be a properly formatted WP request that will return the proper set of posts without any custom processing server side. Given the likely request that would be desired, I don’t think this is possible. Some kind of server side processing will be required.

    The filter category output will need to be able to discern which categories in the query (if any) belong to this code and which belong to the main navigation. It may not be clear from the query object since it may just hvae an array of categories. OTOH, there may still be a way depending on how the nav category might differ from filter categories in the query. The request can be retrieved from $_SERVER, that should help, especially if the default form request is used. Not only must the filter code know what the nav query is in order to output the right categories, but it ideally would also have the previously checked categories remain checked.

    You can output var_dumps and such from within a callback to “pre_get_posts”. You will need to have an idea of what data you are working with. This will mess up page output on the site. Once you you’ve copied the data for evaluation, you can disable the output to restore the site to normal.

    Developing code on a live site really is the worst. Ideally, you would want a local development environment. You don’t need a full data set from the site. A reasonable representation of posts and categories will suffice. Enough that you can tell if your code is working correctly or not. If you don’t wish to set that up, I recommend at the very least least working on a staging site installed in a subfolder of your site. This way, should you make some silly error that crashes the site, at least it’s not the public production site that crashed.

    Another consideration is if multiple filter selections should be logically OR’d or AND’d. I’m inclined to OR them. Using AND would mean posts returned must have all of the checked categories assigned to each post. I think most people would be expecting OR’d results, even if they don’t know it. You will want the checkbox fields to have term ID values because that is what is required to be supplied to the ‘category__in` argument, the one that uses OR logic. Of course the label the user sees would be the category name. Assign the same name attribute (not the same as category name) to all checkbox fields, a name that includes [] at the end. Let’s say the name is “activity[]” PHP will conveniently accumulate all checked values into a single array keyed as “activity”

    Custom query vars like “activity” or “location” will need to be whitelisted in the “query_vars” filter so their assigned values will be available in the “pre_get_posts” action so the passed array of IDs can be set as the value for “category__in”.

    I believe that covers most of the general category filtering considerations. I don’t know what your normal workflow is for coding. I’d say attacking the entire thing would be a mistake. I would develop a very minimal proof of concept script and focus on getting that working first. From there you can build upon that, adding in more functionality in discrete steps. Each step would be easily attainable. Once you complete enough steps, you’ll have the complete app working.

    Whatever you do, I’m available to advise and direct anytime you get stuck on something.

    No, you are reading my mind haha. My idea of working on the categories is to get rid of that right hand cat navigation so we are on the same page. It does do a little more then the left hand navigation as it goes down a third level to differentiate the continents by region. So Asia then is separated into Cambodia, China, etc.

    I sort of want to keep the navigation out of the right sidebar as if you are on mobile it shows up on the bottom of the page almost.

    I think my idea is to take the post of the main category pages like Places to Go and instead make a image grid navigation. Then when you pick Asia there will still be a image grid. Not until you pick like Cambodia, China, etc will you go to the category page. From there I want the user to be able to sort the results by the activity filters. Are the filters you speak of any better for SEO than the ones wordpress already has in place by using a URL like:

    I realize I’m not getting anything SEO from that it at that point as the Page Title is still China in my browser but at that point in the navigation I’m just trying to help the user sort all the post in China by activity if they wish. It’s really about the user at that point.

    Saying I did want to just create a number of links at the top of the category page that appends the activity term to the current category url. How do I do that just in case I decide to go that route. I have this already working to return the current category page.

    <?php $categories = get_the_category();
    if ( ! empty( $categories ) ) {
        echo '<a href="' . esc_url( get_category_link( $categories[0]->term_id ) ) . '">' . name-of-activity . '</a>';

    In the above href statement where and how to I add the term +name-of-activty so the URL
    becomes this URL

    Thanks again!

    Moderator bcworkz


    Always happy to help 🙂

    I’m unsure of the SEO impact of filtering as I envision it. I don’t know how search bots handle form submits, if they are handled at all. SEO may be more affected by what category links are in your sitemap than whatever the filtering actions might return. After all, the filtering results are basically an aggregate of individual category permalinks. What’s important is the search terms people use end up being hits to related pages in your site, not the specific results returned by filtering.

    Filtered results are analogous to local search results for search bots. The specific results shouldn’t matter because presumably all content can be accessed through other means.

    I hadn’t realized the right hand links went deeper than the left hand nav links — I didn’t dig that deeply. It may be significant that there be links somewhere in the site that lead to all content. Sitemap links alone may not be adequate. It doesn’t have to be in site navigation, only that a bot following all found links will eventually get to all content. If content is only accessed by human interaction that bots cannot follow, that might be an issue.

    Managing which filters are shown where might be a bit of a challenge. When activity filters are shown at country level locations, if these locations never have child locations, the lack of children can be the criteria for displaying activity filters. If that does not work because children might exist, you’d have to count up levels to know that at level 2 is where filters should be displayed (places to go being level 0). It’s a little cumbersome to count up. You keep getting parent categories until parent_id == 0 is found, indicating the top level has been reached. How many parents you needed to get tells you the level.

    Getting related activity categories is a curious problem, whether the terms are for filtering terms or to be appended to the page link as in /category/places-to-go/asia/china+hiking . It’s trivial to get all activity terms, but some of them could lead to nothing found. Not a good user experience. You should wish to only list activities that actually exist for the location.

    Thanks to the WP_Tax_Query class, it’s also possible to only get terms that really have posts related to them by using the “hide_empty” argument. But that does not consider only posts in a particular location. There’s no query argument available to only get terms of posts in another category. I think the only solution is to query for all posts in the location and collect any location terms. We cannot use the main location query because it only has posts for the current page. Unless you do not use pagination and any location query will always return all related posts.

    While this can be done with PHP, and there is no way to do so with WP classes, it seems like something SQL could handle on its own. I’m rather weak on SQL, so I’m not sure how to actually query for this. Something along the line of “select distinct * from wp_terms (several joins) where term_taxonomy.parent = activities term_id and posts with term has current location term”

    Doing the same in PHP entails getting all posts for the location, then looping through each of them, getting their terms and if a term has activities as parent, push the term into an array if it’s not already there. You’ll end up with an array of related terms which can be used to generate related URLs or filter terms.

    While filtering makes for a good user experience, implementing it does get a bit involved. Simply appending the terms found to the current permalink in a list of activities is certainly easier, so I wouldn’t fault you for going this route. IMO, filtering is worth the extra work for the improved user experience.

    You could do both, since establishing the proper terms is the same either way. Implement the links to have something going soon. Work on developing the filtering for later implementation.

    OK, thank you so much for all the information. I will let you know how it goes once I figure out what method of attack I’m going to use.

    Have a great day!

Viewing 8 replies - 1 through 8 (of 8 total)
  • The topic ‘Add to end of esc_url’ is closed to new replies.