AJAX Filter Posts By Tag

Info:

There is a newer version of this post, please use the new code examples: Filter WordPress posts by custom taxonomy term with AJAX and pagination

I this tutorial I will create AJAX filter for posts which will let users filter posts by tag.

1. List all tags

First thing is to get all tags and display them on a page.
I will create a function to handle that:

function tags_filter() {
	$tax = 'post_tag';
	$terms = get_terms( $tax );
	$count = count( $terms );

	if ( $count > 0 ): ?>
		<div class="post-tags">
		<?php
		foreach ( $terms as $term ) {
	 		$term_link = get_term_link( $term, $tax );
			echo '<a href="' . $term_link . '" class="tax-filter" title="' . $term->slug . '">' . $term->name . '</a> ';
	 	} ?>
		</div>
	<?php endif;
}

You should include this function in your functions.php file, and then you can use it in your template in a place where you want tags filter to appear.
This function gets all tags and then echo them with link, and term slug as a title.
Term slug is important part, because we will pass it to WP_Query to retrieve all posts that are tagged with specific tag.

2. Javascript inclusion

Next, I will create javascript file which will be responsible for handling AJAX request.
Create .js file named: ajax-filter-post.js and place it in place where you keep your js files.

We also need to have 2 variables:
1. ‘wp_nonce’ which is used to verify AJAX request
2. ‘AJAX URL’ which is location of ‘admin-ajax.php’ file where we send all our AJAX request which WordPress can then handle

This functions goes to your functions.php file as well:

function ajax_filter_posts_scripts() {
  // Enqueue script
  wp_register_script('afp_script', get_template_directory_uri() . '/js-folder/ajax-filter-posts.js', false, null, false);
  wp_enqueue_script('afp_script');

  wp_localize_script( 'afp_script', 'afp_vars', array(
        'afp_nonce' => wp_create_nonce( 'afp_nonce' ), // Create nonce which we later will use to verify AJAX request
        'afp_ajax_url' => admin_url( 'admin-ajax.php' ),
      )
  );
}
add_action('wp_enqueue_scripts', 'ajax_filter_posts_scripts', 100);

3. Catch tag which users clicked

Next, we need to find out which tag is clicked by the user so we can retrieve posts only for that tag. We will get this using jQuery.
In your .js file use this script:

jQuery(document).ready(function($) {
	$('.tax-filter').click( function(event) {

		// Prevent defualt action - opening tag page
		if (event.preventDefault) {
			event.preventDefault();
		} else {
			event.returnValue = false;
		}

		// Get tag slug from title attirbute
		var selecetd_taxonomy = $(this).attr('title');

	});
});

This script will get title attribute of clicked element. Title element is slug, and we will use that as a parameter so we can get all posts with specific tag.
First of all we want to prevent default action, if we don’t do this user will go to tag page, but since we want to catch posts and display them with AJAX we need to prevent that from happening.

4. Custom WP Query function

By now we have done following:
1. List all tags and display them on a page
2. Get selected tag and save it as variable

Next we will create function that will retrieve all posts by selected tag:

// Script for getting posts
function ajax_filter_get_posts( $taxonomy ) {

  // Verify nonce
  if( !isset( $_POST['afp_nonce'] ) || !wp_verify_nonce( $_POST['afp_nonce'], 'afp_nonce' ) )
    die('Permission denied');

  $taxonomy = $_POST['taxonomy'];

  // WP Query
  $args = array(
    'tag' => $taxonomy,
    'post_type' => 'post',
    'posts_per_page' => 10,
  );

  // If taxonomy is not set, remove key from array and get all posts
  if( !$taxonomy ) {
    unset( $args['tag'] );
  }

  $query = new WP_Query( $args );

  if ( $query->have_posts() ) : while ( $query->have_posts() ) : $query->the_post(); ?>

    <h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
    <?php the_excerpt(); ?>

  <?php endwhile; ?>
  <?php else: ?>
    <h2>No posts found</h2>
  <?php endif;

  die();
}

add_action('wp_ajax_filter_posts', 'ajax_filter_get_posts');
add_action('wp_ajax_nopriv_filter_posts', 'ajax_filter_get_posts');

Function accepts one parameter ‘taxonomy’ which is tag user has clicked and then creates WP_Query to get all posts tagged with selected tag.
Before we do that we should verify nonce, if nonce is invalid function will return error and will not make any queries.

5. Display posts

Last thing would be to send AJAX request, retrieve data and display it on the page.
This is done in .js file

jQuery(document).ready(function($) {
	$('.tax-filter').click( function(event) {

		// Prevent default action - opening tag page
		if (event.preventDefault) {
			event.preventDefault();
		} else {
			event.returnValue = false;
		}

		// Get tag slug from title attirbute
		var selecetd_taxonomy = $(this).attr('title');

		// After user click on tag, fade out list of posts
		$('.tagged-posts').fadeOut();

		data = {
			action: 'filter_posts', // function to execute
			afp_nonce: afp_vars.afp_nonce, // wp_nonce
			taxonomy: selecetd_taxonomy, // selected tag
			};

		$.post( afp_vars.afp_ajax_url, data, function(response) {

			if( response ) {
				// Display posts on page
				$('.tagged-posts').html( response );
				// Restore div visibility
				$('.tagged-posts').fadeIn();
			};
		});
	});
});

You will notice here that response is displayed in div with class ‘tagged-posts’, so in order to display results on your page you need to have div with this class on the page.

Final result

To see this in action check out working example.
I have added fadeOut and fadeIn effect to make this look little bit nicer.

Download

AJAX Filter Posts

Update

Fixed bug in firefox, thanks to Mike’s comment

Info:

There is a newer version of this post, please use the new code examples: Filter WordPress posts by custom taxonomy term with AJAX and pagination

187 Comments

  1. Thanks for this :) How could I manually specify the categories instead of printing out all the tags/categories in step 1? For example, I only want to list “All”, “category 1”, “category 3” (even though I have 10 other categories). Thoughts?

    – Lil

  2. It would be very kind of you If you posted the html/php we have to put in our pages so as to make the all thing work.

    Thank you for this tutorial

    1. Hi Maxime,

      I have updated post, there is now link to download files.
      There is .js and .php file inside of .zip folder, just be sure to update path to .js file in enqueue function.

      BR
      Vlado

  3. I am trying to get the same post effect that they achieved here: http://news.harvard.edu/gazette/section/campus-n-community/news/. I want my categories to be filtered by the viewer. On this page – Latest, Editor’s Pick, Audio/Video, Photography, and Popular buttons filter the vertical menu to the left without the page reloading. Everytime you click a new category button the post are able to be filtered by the same horizontal nav. Is this possible with some variation of what you have done above?

    Thanks!

  4. Thank you! Really great posts around here. I’ve been searching for a working example on how to filter posts with ajax to use with my cpt.

    1. hI SIR, i got it but my questio is how can i show the tags to page as shown in example so i can also show tags to pages as it shown in the demo

  5. Hey! Great tip about filtering with tags.

    I just have few questions:
    We have a few CPT (books, magazines, etc) and to show them we are using a separately page for each one, what about if we want to use the same function to filter with tags those CPT?

    Right now your code works only with post_type = post.
    Is there a way we can rewrite the function to allow calling the filter based on the post type?

    1. Hi, thanks.
      Sure thing, it works by modifying wp query in step 4, where you have: function ajax_filter_get_posts( $taxonomy ).
      You can modify function and pass post_type param, so you can filter by any post type ajax_filter_get_posts( $taxonomy, $type ), eg: http://pastebin.com/eJvH9vcu

    2. Thank you Bobz!

      The $type variable is being send through out the ajax-filter-posts.js, right?
      Right now I’ve added an attribute to the link with the name of the post_type, and include that attribute in
      data = {
      action: ‘filter_posts’,
      afp_nonce: afp_vars.afp_nonce,
      taxonomy: selected_taxonomy,
      type: post_type,
      };

      Is that the right thing to do?
      Thanks again in advance.

    3. Hi Elie,

      Sounds like you got it working with a custom post type. Would you be able to post your code into Pastebin or something similar?

      Just so I can see what I’m doing wrong… I’d appreciate it a lot.

      Many thanks,

      S

    4. Thank you for the help.
      I did everything like we talked, but I’m getting this warning:

      Warning: Missing argument 2 for ajax_filter_get_posts() in…

      I think it has to be something with the post_type variable, which is being send properly as we said before :sigh:
      What could be wrong?

      Check my code over here: http://tny.cz/ea12c747
      Hope you can help me figure it out.

      Regards

    5. I think you don’t need that second param, because you pass all things in $data array, so just remove it, and everything should be fine.

  6. Thanks for posting this up. It’s exactly the start I need to create what I’d like to do.

    One thing I’m trying to work out. How do I call this into a custom page template?
    Do I just call the functions inside the loop?
    tags_filter ();
    ajax_filter_get_posts ();

    Thats what I’m currently trying to do and I get the “Permission Denied” because (I’m guessing) it can’t verify nonce.

    I appreciate you’re probably really busy and didn’t really want this to turn into a support Q&A, but any help would be appreciated.

    How do I call this feature on a page template?

    Thanks,

    1. You just display tags_filter() somewhere on page, and you need div where returned data will be displayed.
      Download files and check the code how I did it.

    2. Thanks for your response. I’ve got it working with my own custom post type and taxonomy for that type. The only thing I’m trying to work out now is why, no matter what tag filter I click, the results only show the standard post type (blog posts), not my custom posts…

    3. Oh, I’ve done that and have it displaying what I need i.e. my custom post type (cars) and their categories (car manufacturers). Your pastebin code was very helpful. Thank you.

      It’s just that when I click a filter (a car manufacturer), the javascript is fading out my posts (cars) in the .tagged-posts div and rather than getting the title of the filter I clicked (let’s say “Subaru”, which I can see from the source code is there) and displaying the “Subaru” category, I get my standard “post” type displayed (currently “Hello World” and another test blog post).

      I really can’t see what it is!

      Anyway, please don’t feel you have to respond, I’m sure this is the last thing you want to deal with! Thanks so far for your help, it’s really kickstarted learning what I need to do.

    4. Cool.
      You need to understand that you ‘talk’ to php over AJAX, and that is in ajax-filter-posts.js file.
      So fade effect is in .js file, I have added this effect just to make it little bit visual better, if you click and have to wait 3 second to get data, then if there is no fade in/out, for user would feel like it is broken.
      Check out what is done in js file before and after data is received from php.
      I think something like this would do the trick in .js file:

      var clicked = $(this).text(); // this will get text of tag clicked
      $('.title-of-div').html( clicked ); // this will add title to div you want in to a div you want

    5. Thanks again for your reply.

      That is not quite what I meant. In your .js file when the user clicks on a tax-filter, the title of that filter link is put into a var called “selecetd_taxonomy”
      var selecetd_taxonomy = $(this).attr(‘title’);
      The title has come from $term->slug in my custom taxonomy.
      I’ve printed console.logs throughout the .js script and I can see that these vars are getting the category title. e.g. “subaru”.

      Where I’m lost is that the category (“subaru”) should then be sent back to a PHP function and where all the posts in http://myurl.com/car_manufacturers/suburu/ are collected and then should be displayed.

      Thats not happening.

      Instead it’s getting the default wordpress post type posts. Not my custom ones. I can’t work out where this is happening in the function.

      I’ll continue to try and figure this out, I’m working locally so I can’t share a link at the moment. But thanks for you continued help! :)

    6. I don’t understand what are you trying to say. But anyway, practice makes perfect, so keep up and you will come to a solution

    7. Yes no worries.

      It’s all working just returning the wrong category as results and I can’t figure out why.

    8. Hello again,

      I’ve put my code into pastebin. If you have a spare minute I’d love it if you could take a look. I’ve put comments to explain a few things. http://pastebin.com/7nYq76wJ

      The part of code that is confusing me is the end of the javascript. Would you be able to explain the $.post and response part. I’ve tried looking online but can’t find anything.

      Again really sorry to keep bothering you, I’m so close to this but can’t understand why I’m not getting my custom post type returned! Your blog post is the only good tutorial on how to do this, for that I thank you.

    9. One other thing, in the JS you have a line:
      action: ‘filter_posts’, // function to execute

      Where is this function, I don’t understand what it is calling… :(

    10. It is calling ‘ajax_filter_get_posts’ via
      add_action('wp_ajax_filter_posts', 'ajax_filter_get_posts');
      add_action('wp_ajax_nopriv_filter_posts', 'ajax_filter_get_posts');

      This is how AJAX works in WP.

      If you get wrong data back, then something is wrong with you wp_query.
      You need to learn how to debug things.

      1. First of all check if this post_type you are passing is getting in function.
      2. Try to manually add post type you wish and see if it will work
      3. print_r your query and args to see what is going on

    11. Got it working! Sorry for spamming your comments…

      Couple of things, I needed to to change ‘tag’ to to my taxonomy (I don’t have tags) and I had the PHP looking for the wrong variables from the ajax.

      Right, now onto making only pull in the parent categories not all the child ones too.

      Thank you.

  7. Awesome tutorial! Quick question though. Would it be an easy modification to use entries from a custom meta box instead of post tags?

    Like if that first function were modified to pull all unique entries that exist in a get_post_meta() field?

    Thanks!

    1. Thanks.
      You can do anything. In function ajax_filter_get_posts is wp_query, so you modify it per your needs, and instead of tags you pass other parameters with ajax.

  8. Great tutorial! For some reason, the example isn’t working in Firefox though and I don’t have Javascript turned off. The links just go right to their page. Other popular browsers I tried have it working. Check it out & let me know if you find the same. I tried getting rid of the href attribute in my own example & still nothing happened. Thanks!

    1. I tested on a PC & Mac. PC has the latest version of Firefox. Mac has an older version. I’m not the most experienced with debugging via console, but when I went into the tab, I did not see any errors and again, this is on your example (& my own implementation). Weird. Thanks for the help!

    2. Okay, found an error when I click on a tag. Firebug is highlighting line 5 – “if (event.preventDefault) {“& saying the event is not defined.

    3. So “$(‘.tax-filter’).click( function() {” just needed to be changed to “$(‘.tax-filter’).click( function(event) {” :-)

    4. Hi Mike, yes this is right. I have updated post, thanks!
      Funny thing is that I have just hour ago fixed same issue on one other project i’m currently working on.
      Exactly the same problem.

    5. haha Gotta love those minute details that can make such a big difference. Glad we figured it out! I don’t want to trouble you anymore with this, but it looks like there might be something wrong with your query now as it keeps showing “no posts found”.

    6. Yes, thanks.
      It’s not query problem, thing is I have improved my workflow a little bit and I have rewritten this same script in a better way and now I uploaded wrong file.
      Thanks once again, it is working now.

      Current script only checks if there is response, but nothing else, which is bad.
      You can download updated files from link in post and take a look.
      Basically everything is the same, just it is JSON encoded and I return all required data for debug, just uncomment console.log lines and you will have full insight.

      I will rewrite the post during the weekend with updated code.

      Cheers

    7. Okay, I implemented the new method & got it working! There’s only one problem I’m seeing with the new code which is that only the first result from each query loop is returned when a tag is clicked. Not sure why.

    8. It was a bug on line 48 in wp qurey.
      It was like $result['response'] = post data.., but it should be $result['response'][] = post data... You only got last post in loop because it was overwriting everytime. Response index should contain another array of posts, it is fixed now in files.

  9. Thank you very much for this tutorial. It’s exactly what I need but although I have no problem in understanding how to change post types and categories and styling, I’m really struggling to work out exactly what goes into the template file. Am I right in thinking that the php file in the downloads gets copied into my function.php? S’s comment above, I believe asks the same question but I’m afraid I can’t figure it out from the download what I need to put in the template file.
    I’ll continue to try to figure it out myself – best way to learn :) but would really appreciate if you can set me straight if you have the time to reply.
    Cheers!

    1. Me again, sorry, have been on this for 2 days and really disappointed with myself. My background is design rather than code and seems the harder I try, the less I feel I understand…
      I have a custom post type ‘a_and_h_cheese’. I’m using tags as the filter like your example . That’s it. What goes in function.php and what goes in my template page please? The best got was an ‘access denied’ message. I looked at various pastebin links in your comments but just can’t figure it out :(

    2. Thanks again Bobz, have tried again – with the sample template you pasted and just with standard example posts and tags (before I get clever with my cpt and taxonomies and styling up etc)
      First I got: Fatal error: Cannot redeclare tags_filter() (previously declared in… (my function.php). I think I get this – it’s because this function is already in the function file and we don’t need it again in the template, just in the template. If I delete one or other the page loads and I’ve got my tag list and I got all my posts, that’s great, but clicking tags results in ‘No posts found’. Similarly a bit confused about the query/loop in the functions.php and again in the template… Where am I going wrong?

    3. Hi, you need to learn how to debug.
      1. Open inspector ‘network’ tab
      2. Refresh page
      3. click on one tag and wait to return something
      4. in inspector look for ‘admin-ajax.php’

      There you can see what you are sending and what you are receiving as a response.
      You can also do print_r in function ‘ajax_filter_get_posts’ which returns posts, instead of echo, do var_dump or print_r, then again refresh page and check inspector.
      You will get an error on page, but you will see what is causing error, what kind of query do you send, etc. everything is in there, just need to learn how to read it.

  10. Bobz, this is a fantastic tutorial.

    I’m convinced I’ve done everything correctly, but I’m getting the admin-ajax.php (failed) and (canceled) in Inspector > Network when clicking the tag and so it’s skipping the event.preventDefault and bringing me to the tag page… have any wisdom you might impart as to why the admin-ajax.php is acting up?

  11. Hey there!

    Is there a way to add/include a link to all posts in the tag lists generated?
    That way if someone clic a specific tag and want to return to all posts, can do it by just clicking the tag “All”.

    Peace

    1. True that! But what parameters should I use in the link to call “all posts”?
      Can you help me out please?

  12. Thanks for the tutorial! it has really help me a lot. I do have one question: I want to paginate the results with a “load more posts” button. Can you point me to the right direction or get me starter on how I can approach this problem?

    1. Hi Alonso.
      Well hm, you maybe try something like this: http://designaeon.com/2012/05/wordpress-ajax-pagination/
      In this case in my query is missing ‘paged’, then when you click on ‘load more’ you need to send to query which page number you want to get.
      I think you need hidden field here to store next page number.

      I have not tested non of above, but this is what I see as a way to go, hope you get the idea.

    2. Thanks Bobz, the link provided didn’t help, but adding the missing paged pointed me in the right direction and in the end I got it working. :)

    3. Alonso: I’m actually trying to accomplish the same thing; pagination after clicking on a tag. Would you mind sharing how you were able to get it working? I’d really appreciate it. Thanks!!

      Bobz: Thank you for the tutorial! Aside from the pagination issue I’m having, it’s working exactly as it should.

  13. only for expert developer… the best solution is to buy or download a simple free plugin… more easy to install and “developer-fanatic” free

  14. Hi Bobz, great tutorial this serves as a great starting point for integrating ajax into all aspects of wordpress as a beginner.

    I am using this code on a site we are developing and will be modifying it to remember the previous tag clicked so it begins filtering down on more and more tags until you reset it.

    I have changed the code to work with a custom post type and tax, however it keeps running the loop twice and giving the results twice. I unfortunately can’t share the site with you but is there anything off the top of your head that could be causing this?

    Thanks for any response.

    1. Fixed this: It was my own fault.

      Two divs were being created on the page with the class tagged-posts, DOH!

      Again thanks for the tutorial Bobz, don’t think this will be the last you’ve heard of me though!

  15. Hello Vlado,

    regarding the comment of Chris at February 9, 2014, you wrote:

    ” Hi Chris,
    Yes it is possible, it would be something like: $terms = get_terms(“my_taxonomy”);
    Check out in WP codex: http://codex.wordpress.org/Function_Reference/get_terms
    BR
    Vlado ”

    Ho can realize this taxonomy? so, i wil get terms of ALL tags used in my posts related ONLY to my category with id 5, or name “category name”. Thanks a lot for your reply. regards Giombattista

    1. Hi Giombattista,
      I’m not sure I understand your question. Anyway you should stick to WP Reference and test it out yourself as I’m not sure what are you trying to get.

    2. I want to show only tags that i use in my posts belong to a particular category (example “animals”). So, my question is how can i refine the tags list, so i not show all tags, but only the tags related to posts of a single category?

    3. Dear Vlado, i have realized my scope! i used the argument EXCLUDE to exclude the tags that i don’t interest me. So, a custom tassonomy. So, thanks to this new get_terms i got only the tags of my interest. It’s a manual refine, but the result is great. Now, my next step is: i wish i create also a “Show all” in my tags list, also with ajax effect. So, i can refine the list with one tag or click upon “Show all” to see again all the posts, as i see thanks to WP_Query, when i load the page for first time. Do you think i can realize it? could you help me with the code? thanks a lot, Giombattista

  16. Hey,
    great work here ;)
    i have a question, i have many custom content templates, can i load the template with ajax too?
    like get_template_part( ‘content’, get_post_format() );
    can’t add it to the $result in the functions.php
    hope somebody can help me.

    – David

    1. Hi David, I don’t think it is possible to do it like that.
      You can get page by ID via AJAX, and then in output include this template to display data in correct format.

    2. Hey Bob, thanks for the fast reply.

      Well, it kinda works, the right content, using the right content template is coming.
      I can see it in chrome developer tools under response.
      Problem is, that the content stands above and the response is:{“response”:[null],”status”:”success”}
      so it always shows “no posts found”.

  17. Hey,

    I’m looking to be able to do this, but with multiple tags.

    E.g Tag 1 – English / Maths
    Tag 2 – Maths Easy, Maths Hard, English Easy, English Hard

    If Tag 1 is Set to English, I want to only show “English Easy, English Hard” as a selection for Tag 2.

    Is this possible?

    1. Hy
      Well, it is, but you need different approach.
      1. You need to list all tags
      2.1. On tag click you need to make it ‘active’, add class active (second click on same tag would make it inactive)
      2.2. Need to lookup all active tags, store them in array
      2.3. Do WP_Query by multiple tags, consult wp codex for correct syntax of wp query

    1. Something is wrong with nonce name probably.
      Check that nonce is passed to function correctly.
      ‘afp_nonce’ => wp_create_nonce( ‘afp_nonce’ )
      and
      wp_verify_nonce( $_POST[‘afp_nonce’], ‘afp_nonce’ )

  18. Thanks for the tutorial,
    it’ exactly what I’m trying to accomplish.
    I am getting “No posts found” all the time though, and no errors in the console. I know the ajax-filter-posts.js is being called though since I modified the “no post found” message to something else and I can see that echoed in my page.
    Is there anything I could look into to understand what’s going wrong?
    thanks!

    1. Hi, thanks.
      Looks like your query returned no posts, so it means it is not an error but you have 0 posts with tag you selected.
      Test the WP_Query until you get desired results.

  19. Thanks Bobz,
    I do have posts tagged with those tags though, I’m just testing with 4 tags and 4 posts, each post is tagged with couple of them.
    I’m not sure what you mean when you say “Test the WP_Query until you get desired results”.
    Any indications of things I could try out would be much appreciated. :-)

  20. I actually just ran into the same problem when editing tag.php and trying to pass the tag variable to a WP_Query. I always get ‘Sorry, no posts matched your criteria.’ Except if I manually specify the tag as an argument in the WP_Query. Then I get the posts associated with that tag. It’s really weird but I’m pretty sure this is the same problem I’m getting with the “tag filter”.

  21. Dear Bobz, this is my question: how can i improve delay time of the response when i click on a tag and after i retrieve post list result? i wish i obtain a result that is fastest than possible.. thanks a lot. Regards, giombattista

    1. Hi, I’m not sure i’m following you, there is no way to assign term to a term.
      Anyway, you should try to get desired results with WP_Query first.

  22. Thanks for the tutorial. I’ve got the tag filters working, but when I load the page (which should display all posts), I get a Permission Denied response and I have no idea why. I’ve pasted the code (that I’ve lightly modified) here: http://pastebin.com/AdUWK4NB

    Thanks in advance for any help!

    1. Hi Patricia,
      There is something wrong with verifying nonce, you don’t post it with ajax or you use different name probably.
      Check that and then you will be fine.

  23. Hello, It’s Giombattista. i used and customized your code with success. But now, i have a question for you:

    Suppose to have n. 2 Archive page with this tag filter system; for n. 1 page i want to show, for example, Title and Excerpt. For the second one instead i want to show only the thumbnail of filtered posts.

    I created n. 2 different div class -> Class “Layout A” and Class “Layout B”, with success. But, actually i cannot create n. 2 different layout because i cannot explain to my code where my taxonomy (in the function ajax_filter_get_posts( $taxonomy )) came from (from first or second archive page?). I think i can insert some if-else inside the function ajax_filter_get_posts( ) function, before the result while. But exactly i don’ know how.

    If you have some suggestions for me, it would be fantastic.

    Thanks a lot, Waiting for your reply. :-)

    1. I’m not sure I understand your problem, but try to use hidden fields, or data attributes for additional data you need to pass via AJAX:

      BR
      V

  24. Hi, I want to do what you show here, but with post CATEGORY, not tag(s).
    Can you explain how to do this? I assume it’s very similar to this?

    Thanks :)

  25. Is there a way to do this via a shortcode instead of adding it to the template file. I want this to just take up a small portion of one of my pages

  26. Thanks for this tutorial, was wondering how i would go about creating a select filter ? where the user can select the tags to be displayed all from one taxonomy and then display them accordingly ?

    1. Sure, you can. You would need to modify tags_filter() function to output select menu instead, and then fire js function on(‘change’)

  27. Hello,

    This script really helps a lot though I have an issue displaying default contents or when page load, I would like to display few posts. Right now it’s only the tags being displayed and only the content will display when any of the tags will be clicked. Can you please help as to how it should be done? or what should I missed?

    Thanks a lot.

    Rheejee

    1. Hello,

      I would do something like:
      $(.tax-filter[title=tag-slug]).trigger('click').

      This will trigger a click on a specific tag and populate the content area.
      Other than that you can do another wp_query inside of a template.

      Cheers

    1. Oh and my error is:
      Warning: Missing argument 1 for ajax_filter_get_posts(), called in /home/firstdraftnews/public_html/wp-content/themes/firstdraft/tag.php on line 19 and defined in /home/firstdraftnews/public_html/wp-content/themes/firstdraft/functions.php on line 52
      Permission denied

    2. Hi,

      You are missing ‘Tag filter’ function under #1, you should place that function in your template file.
      ajax_filter_get_posts is function you call on ‘click’ of tag which returns posts and displays them in template.

  28. Thanks for this, I have been trying to implement the history api but can’t figure it out. i can get the url to change but not the back and forward buttons. Any chance you could show how to do this. Very much appreciated. H

    1. Hi,
      This code doesn’t provide paging functionality.
      I will have to write another post since it is a little bit outdated which will include paging.
      I’m not sure about history, will that work.

  29. Hi Bobz,

    First of all, thanks for sharing this really nice function. I have customised it a little for my needs and it’s working great.

    The only thing which I would like to change is when the page is loaded all the posts are displayed first then when the tag filters are clicked it only shows the tagged posts.

    Is that possible with this code?

    Many thanks.

    Rick

    1. i must be too new. I’m not sure what goes where…
      you have 5 steps above:
      1 list tags: goes in functions
      2. include javascript: goes in functions.php
      3. Catch tag which users clicked: goes in js file.
      4. wp function: where does this go?
      5. display posts. in js file.

      what do i put in my template file?

      I downloaded your zip and there are only 2 files, but they seem to have different slightly codes than those in the steps above. which should i use?

  30. Hi, thank you very much for this great tutorial. I have two questions, if you have the time to answer.
    1) I’m trying to work with categories instead of tags. You mentioned that it’s just update the WP Query. I did it, but I can’t make it work. It keeps returning all posts instead of return the post of the clicked category.

    2) Also I’m trying to create a link to “show all” but all I can get is a link that refreshes the page… I can’t figure out how to accomplish this.

    If you may not answer these questions, thanks anyway for the tutorial.

    1. Hi Gisele,

      // WP Query
      $args = array(
      ‘tag’ => $taxonomy,
      ‘post_type’ => ‘post’,
      ‘posts_per_page’ => 10,
      );

      and replace ‘tag’ with ‘category’ following the WP_Query codex.
      You can always do print_r($query); to see what’s going on in there.

      Regarding the second if the link contains eg: ‘all-posts’, then before making wp_query do check if( $cat = ‘all-posts’ ) { unset( $args[‘cat] ); }

    2. i should say, I changed the line in the template flie from ‘$tax = ‘post_tag’ to ‘$tax =’category’. and this changed the filter buttons to my categories, but if i click any of the category buttons it says that no posts were found.

      I would also love to know how to implement that “show all” button.

    3. Hi Josh! Sorry, I replied to Bobz but didn’t see your question.

      To work with categories, as Bobz explained you should update the WP Query section in his code at ajax-filter-posts.php file. Change “tag” to “category_name” (this is his mention on “…following the WP_Query codex”). I was changing to “category” not “category_name” and this won’t work. Only newbies like me can understand why we do such mistakes and insist on them…

      To create a “Show all” I did three things (I don’t know if this is the best method, but it worked):
      1) On your template file, create the a variable “$cat = all-posts”.
      Obs.: Somehow it works without the var, but I think it’s better to declare. Maybe it works because Bobz created a check when taxonomy is not set (line 39).

      2) Then, create the link that passes the “all-posts” value as a category, something like “echo ‘slug . ‘”>Show All ‘;”.

      3) Then, similar to what he did on line 39 in ajax-filter-posts.php file, you should declare what happens when the value “all-posts” is passed. Again, as Bobz mentioned:
      if( $cat = ‘all-posts’ ) {
      unset( $args[‘cat] );
      }

      If it doesn’t work for you let me know. And if I did something awfully bad in this code, please someone let me know…

    4. Thanks for replying Gisele,
      I tried adding :category_name and am getting the same thing. No post avaiable. If i put this code directly in my template file i do get my posts though.

      I posted my code here:
      http://pastebin.com/6QiUWTnG

      Is it similar to yours or am i missing anything? I would love to see your code too, if that’s not too forward. :)

    1. Hi Tina,

      I would do a toggleClass(‘active’) on each tag, and on each toggle call function to retrieve posts.
      Please not that function in this tutorial is not the one you need to call, but instead you need to modify it to suit your needs.

      BR
      V

  31. Hi, thank you for this tutorial, i add all functions and script, and in my .tagged-posts in index.php i get the posts in my selected tag, but when i add class tagged-posts only to my loop, i get only title-links, my get-template-parts > content, don’t work, i want to display thumbnails and content, when selecting tag, also, if i select tag-1(used only once) my pagination don’t dissapear, like if i got still >50 posts on page, how can i fix this, to get proper content of post in tag, and fix pagination? Also is it possible to add selected tag to my coockie and add class active to it?

  32. What should put in template file to get like in live example? I put all what you said in functions.php, js folder. If I put only function tags_filter() function, I get only all tags. But how I can get all posts and then filter by click on tag’s link? I got all posts but how to call another function from functions.php and javascript file to generate only selected post by tag?

    1. In template file you should put function tags_filter().
      If you wan’t to display certain tag posts on page load, quickest way to do it would be using jquery, trigger click on tag which you want to show.

  33. Thanks for the great tutorial.

    Have you had any success integrating the pagination tutorial from Designaeon.info, or pagination via another method?

    1. Hi Simon, I didn’t try to integrate pagination.
      There are some things about this post that can be improved, will try to sum up everything and rewrite this tutorial.

  34. Thank you for this useful snippets. I will add it to my website 1stwebsite. I want to add it of a customs post type. Will it work for my custom post types “code”

  35. Hello Vlado,

    I notice that my code doe not work anymore. I think it’s an ajax problem, maybe due to the continue WP updates.

    Can you suggest me how to fix the problem and the code to work properly again? Thanks a lot in advance, Best Regards.

  36. Are you sure something didn’t happen that broke he code Bobz? When I click the link to the ‘working example’ – there is no content displayed. I know I looked at this post a couple months ago and it worked. I came back to it today to try and study it but it no longer functions on my PC, not in any of the 3 major browsers.

    1. Hi lbob, I’ve moved to digital ocean but the live example obviously didn’t come along :)
      I have fixed it now, it works; thanks for comment.
      By the way I do have in mind to rewrite this tutorial, should be soon online with more options and customizations.

  37. Hello Bobz,

    The tutorial is great. It helped me a lot with what I wanted to do, I just need to paginate the results of each label. I see that another person has asked about the same, but I had already come to that solution. Any more ideas?

    Thanks in advance.

  38. Hi Vlado,

    Just curious if there was another link to the .zip file available. Am getting a 404 error and would really like to try this out.

    Any help is greatly appreciated,
    Daniel

  39. VIDEO test 2

    Idk why all of these links have all the extra \ after I click each tag. Any idea? I have removed everything so it will only display the title and not even an anchor tag or the permalink.

  40. I have figured out what was going on with the links displaying extra \ and /. In combination with other functions it was returning all of that when using the get_the_title();. Dont know if it just me but I can seem to get the $output = ‘‘. the_title().’‘; working, it keeps filtering the html in the functions.php.

    Any help would be greatly appreciated, have added a category filter and this is the last hill I have to climb. I am at a loss as to why it is happening.

    1. Hi Daniel,

      You cannot do $output = the_title(); because function the_title() prints out title of post, and instead you need function to return data, and that would be $output = get_the_title();

    2. Even when using get_the_title(); the html to turn it into a link is being filtered or not working within the output variable.

  41. I apologize if I am bothering you with too many questions.

    I am having a bugger of a time getting this to work correctly, dont know the exact way to get this functioning and to filter by region and topic(category,tag).

    I feel as though I have made some progress and with a few minor changes it could be working and could be soemthing anybody could use to get those pesky AJAX post filter pages working correctly.

    I am working off of your design and know that I still have to add the correct if statements in order to get this to filter by tag and category. I appears to make the ajax call but does not filter the posts.

    Link to my code on pastebin

    Any help in this would be greatly appreciated.

  42. Hi i read a lot of tutorials about using ajax in WP, and i read this tutorial after implementing this one:
    http://carlofontanos.com/wordpress-front-end-ajax-pagination-with-search-and-sort/
    Can i ask you, what will be the best way to change foreach loop to standard if have post, while have post,
    so i can use get template-parts with ajax call?
    I want to use this tutorial with carlofontanos.com ajax pagination, but using if have post loop.
    Is there a better way to get template-parts with ajax without using plugins?

    1. Please check out the new post, it uses output buffer which you can use to achieve that.
      Just instead of html part you should be able to use get_template_part to include your markup

  43. Hi Bobz,

    Thanks for the tutorial. It’s been a huge help! I have it implemented on my site and it’s working as it should. The tags are ajaxing underneath after clicking.

    My website is using the Advanced Custom Fields date time picker to only show posts that are in the future because it lists upcoming film screenings. So I have tailored your code to only ajax in posts that are future posts/screenings and not past posts/screenings.

    I would only like the tags that have future posts attached to them to display. For example the ‘animated film festival’ tag on my site does not have future posts and therefore returns zero posts on click. Is there a quick way to remove this kind of tag from the list conditionally?

    For your reference:
    http://pigcine.pamrosel.com/

    1. It’s not possible to get tags in that way.
      One thing that comes to my mind is that you create a cron job with wp_schedule_event.
      That cron should:
      1. run every day in the morning 1 time
      2. get all terms
      3. for each term get_posts (posts_per_page=1) that have film screening date today or in the future
      3.1 if there are posts then update term meta ‘have_posts’ => have

      This way all tags that have posts will have term meta ‘have_posts’ = have.
      Then you use get_terms function with meta_query to get only terms that have this meta_tag and value ‘have’.

      It’s a lot of queries but you do that once a day with scheduler in the background.

      Or the second solution would be to try to write your own SQL query to get terms, but it would be a difficult one

  44. Thanks so much for this tutorial! I got it working with my CPT, by modifying the $args variable like so.

    // WP Query
      $args = array(
        'event-type' => $taxonomy,
        'event' => $type,
        'posts_per_page' => 10,
      );
    
    1. It would be possible, but you need to alter the script a bit. This is more a showcase how things work, it’s nearly impossible to make ‘one fits all’.

  45. Hi I have a Question:
    In your Working Example the created WP-Query gets his own url. When I use this, it does not create or direct to its own url. Can you may tell me why? The website is only tested localy on my Computer with MAMP.
    Thx for your Answer.

  46. Great tutorial! It’s the first time I manage make something like this work.
    Any idea why, if I substitute “category” for “tag”, it doesn’t work anymore?

    I also changed it here:
    function tags_filter() {
    $tax = ‘category’;
    instead of $tax = ‘post_tag’;

    and here:

    $taxonomy = $_POST[‘taxonomy’];

    // WP Query
    $args = array(
    ‘cat’ => $taxonomy, (instead of ‘tag’)
    ‘post_type’ => ‘post’,
    ‘posts_per_page’ => 10,
    );

    I know this is an old post but any help would be greatly appreciated!

  47. Hello Bobz,
    I followed the tutorial! Super filtering works well except with the exception, I have only one result when I click on a link tags … while I would like to have all the articles in with the tag.

    I modified a little code to put a custom taxonomy, in the demo there is also only one example.

    Would you have a solution please?

    thank you
    Olivier

    1. Hi Olivier, glad you find it helpful.
      Are you sure posts_per_page in WP_Query is set to return more than 1 post?

  48. yes !

    $args = array(
    'post_type' => 'post',
    'category_name' => 'retail',
    'posts_per_page' => 100;
    'tax_query' => array(
    array(
    'taxonomy' => 'retailly',
    'field' => 'slug',
    'terms' => $taxonomy,
    ),
    ),
    );

    1. Would you mind to try modifying the loop in this:

      ob_start();
      while( the_query->have_posts() )
      ...
      endwhile;
      $html = ob_get_clean();
      wp_send_json_success($html);

      And you might need to update js part to display data to response.data
      Best is to do console.log(response) so you can see exactly what you get returned from WP.

    1. So that means there is no javascript variable afp_vars on window object. Check wp_localize_script and verify what’s the name of your variable.
      And please next time use external service for pasting large parts of code, thanks.

    2. hi vlado,

      can’t find any reference for afp_vars in the source code.

      my functions.php

      function ajax_filter_posts_scripts() {
      // Enqueue script
      wp_register_script('afp_script', get_stylesheet_directory_uri() . '/javascript/ajax-filter.js', false, null, false);
      wp_enqueue_script('afp_script');

      wp_localize_script( 'afp_script', 'afp_vars', array(
      'afp_nonce' => wp_create_nonce( 'afp_nonce' ), // Create nonce which we later will use to verify AJAX request
      'afp_ajax_url' => admin_url( 'admin-ajax.php' ),
      )
      );
      }
      add_action('wp_enqueue_scripts', 'ajax_filter_posts_scripts', 100);

  49. hi vlado,

    i include the two function and it fix the reference error for afp_vars, but it not working correctly for my case. I fixed my issue with using isotope.js to filter my posts.

    hvala

    1. There are few possible options:
      – either you have only one post
      – you have pre_get_posts filter somewhere active
      – you are requesting only one post (inspect network for admin-ajax.php and check vars)

Leave a Reply

Your email address will not be published. Required fields are marked *