Skip Navigation

[Resolved] How to get rating average from CRED for review

This support ticket is created 10 years, 5 months ago. There's a good chance that you are reading advice that it now obsolete.

This is the technical support forum for Toolset - a suite of plugins for developing WordPress sites without writing PHP.

Everyone can read this forum, but only Toolset clients can post in it. Toolset support works 6 days per week, 19 hours per day.

Sun Mon Tue Wed Thu Fri Sat
- 9:00 – 13:00 9:00 – 13:00 9:00 – 13:00 9:00 – 13:00 9:00 – 13:00 -
- 14:00 – 18:00 14:00 – 18:00 14:00 – 18:00 14:00 – 18:00 14:00 – 18:00 -

Supporter timezone: Asia/Hong_Kong (GMT+08:00)

This topic contains 43 replies, has 11 voices.

Last updated by joeC-5 10 years, 5 months ago.

Assisted by: Luo Yang.

Author
Posts
#134622

Hi EthanO, sorry for not getting back sooner. It was my son's birthday yesterday and I was not working. If you have urgent issues I really strongly suggest you open new topics and the toolset support team will be able to help you much better than I can. As I said, I do not form part of their support team and am in no way part of their team. If I can help you I will though.

#135046

Hey Trigger, Oh no worries at all! I'm just kinda a slow leaner, but finally starting to put the pieces together.. understanding views and types and templates and how they work together more now.. Thanks a bunch for helping if you can.. I'll try not to bug you though. lol

Happy Birthday to your son!

#275186

Could a full tutorial be done on this, as I'm trying to implement this myself and getting lost in the slight code errors.

Maybe even with a video?

Thank you.
Cathie.

#382109
Screen Shot 2016-04-11 at 17.30.43.png

first: THANK YOU FOR THIS POST !!!

this was exactly what I needet. works like a charm.

on a restaurant/venue page I have child posts with ratings and I can display the total average rating. PERFECT.

I have a facebook like startpage, displaying new venue posts, with total rating.
this works fine.

than I also display new commtes/ratings for venues.
I can display the users rating, but not the total rating.
becaus the post is already the child.

I tryed

[rating-average id="$venue"]

but I know this can't work. it was just a good portion of hope 😀

how can I make it work ?

this is my function:

add_shortcode('rating-average', 'rating_average_func');
function rating_average_func()
{
    $child_posts = types_child_posts('venue-rating');
     
    $sum = 0;
    $num = 0;
    foreach ($child_posts as $child_post) {
        if(isset($child_post->fields['rating-venue']))
        {
            $sum += $child_post->fields['rating-venue'];
            $num ++;
        }
    }
    $res = '';
    if($num>0)
    {
        $res_10 = $sum/$num;
    }
	$res = $res_10/10;
    return $res;
};

(don't worry about /10 .. I user for rating 10,20,30,40,50 istead of 1,2,3,4,5)

I hope you guys understand what I mean.
maybe for better help:

hidden link

so if someone can help me to figure out how to display the total average of the parent.. that would be so AWESOME 🙂

thank you all
max

#390348

Hi,

at first i will thank triggeru571 for the great work and many thanks for sharing with us.

I have the same problem as MaximM. All works.

Only this code...

//Calculates and displays the number of reviews in a post
add_shortcode('reviews_total', 'reviews_total_func');
function reviews_total__func()
{
    global $post;
    $args = array(
'posts_per_page'   => -1,
       'post_type' => 'reviews',
        'meta_key' => '_wpcf_belongs_' . $post->post_type . '_id',
        'meta_value' => $post->ID,
    );
    $child_posts = get_posts($args);
    return count($child_posts);
}

...not working for me. Post type of "reviews" is a child post of "testprodukt" on my site.

Hope someone can Help me with this.

mira

#428361

Hey all, I'm going to resurrect this threat for a few things:

1. This is amazing. Thank you so much for all of your work @luoyang @trigger

2. Some people couldn't get the shortcodes to work. This is because there are typos in the first one - the first line should be

add_shortcode('rating_average', 'rating_average_func');

, not rating-average (unless you want to use that code).

In the second function, there is an extra underscore after "reviews_total". Change

function reviews_total__func()

to

function reviews_total_func()

3. As for star plugins, I am currently using Bootstrap Star Rating
hidden link

It's awesome because it uses bootstrap, so it works without too much code, and it's easy to customize. I use it for the cred form for reviews and the display for the ratings on restaurants.

4. There's one important consideration - I don't know how much time the query takes to get each restaurant's average rating / total review count, but if it's in a view with 12 or so total restaurants, it could slow down sites. One possible thing to mitigate this would be to store the average rating and number of reviews in a custom field on the restaurants themselves. This means that you could take that function to calculate the average rating and use it to update the custom field for avg rating and total on the restaurants each time a new review is submitted. This would slowdown the review writer only and make it easier to query ratings / reviews on the front end. It also has the *added benefit* of letting users sort restaurants by average rating!

I'll post any code / steps to implementing #4 as I make progress

Thanks again! Let's keep developing this awesome extension for ratings

#428863
sample.jpg

OK, so implementing the custom fields and updating avg rating and total reviews on the post being reviewed itself instead of making queries each time was pretty easy thanks to Trigger + Luoyang's original code. Here's what you have to do:

1. Create a new field group called: Fields for Avg and Total Ratings (or whatever you want)

2. Add two number fields: "Average Rating" and "Total Ratings" . Save the fields and make sure you make them available for the post types you are reviewing.

3. I assume you have a CRED form for creating reviews. Each time this CRED form is submitted, it will automatically calculate and update the average rating and total ratings for the post being reviewed. In order to do so, add this to your functions.php. Remember to change the number in

if ($form_data['id']==7954

to your form number, and verify your custom field slugs and post type slugs. My post type uses 'review' instead of 'ratings':

 //*Update Avg Ratings and Total # of Ratings after review submission
function update_post_ratings($post_id, $form_data)
{
    // if a specific form, change ID to the CRED "Review" ID
    if ($form_data['id']==7954)
    {
		//Get ID of Post Being Reviewed
		$current_post_id = $form_data["container_id"];	
			$post = get_post( $current_post_id );
		    $args = array(
			'post_type' => 'review',
			'meta_key' => '_wpcf_belongs_' . $post->post_type . '_id',
			'meta_value' => $post->ID,
		);
		$child_posts = get_posts($args);
			   
		$sum = 0;
		$num = 0;
		foreach ($child_posts as $child_post) {
			$ratings = get_post_meta($child_post->ID, 'wpcf-rating', true);
			if($ratings)
			{
				$sum += $ratings;
				$num ++;
			}
		}
		$average = 0;
		if($num>0)
		{
			$average = $sum/$num;
		}
		$res = $average;
		if($average==0) $res = 0;
		if($average>0.001 && $average<0.5)$res = 0.5;
		if($average>0.501 && $average<1) $res = 1;
		if($average>1.001 && $average<1.5) $res = 1.5;
		if($average>1.501 && $average<2) $res = 2;
		if($average>2.001 && $average<2.5) $res = 2.5;
		if($average>2.501 && $average<3) $res = 3;
		if($average>3.001 && $average<3.5) $res = 3.5;
		if($average>3.501 && $average<4) $res = 4;
		if($average>4.001 && $average<4.5) $res = 4.5;
		if($average>4.501 && $average<5) $res = 5;
		
		update_post_meta( $current_post_id, 'wpcf-average-rating', $res );
		update_post_meta( $current_post_id, 'wpcf-total-ratings', $num );
    }
}
add_action('cred_save_data', 'update_post_ratings',10,2);

4. Now, instead of using the shortcodes created previously, you can use types shortcodes in your views/layouts/content editor to display avg rating and total ratings on your posts. For example:

[types field='total-ratings' format='FIELD_VALUE'][/types] Review(s)

You can see an example picture of what I got it to look like on the front end with the star ratings plugin I mentioned in my previous post.

5. For the few people using WPML, we have to edit this code to make the ratings sync between languages. I'm currently working on that, but I cannot make any promises!

#429082

Edit: So there is a slight problem with the code to calculate avg rating and total reviews. Apparently the query is paginated, so it only finds the most recent 5 reviews. You have to add

'posts_per_page'   => -1,

to the $args like so:

//*Update Avg Ratings and Total # of Ratings after review submission
function update_post_ratings($post_id, $form_data)
{
    // if a specific form, change ID to the CRED "Review" ID
    if ($form_data['id']==7954)
    {
        //Get ID of Post Being Reviewed
        $current_post_id = $form_data["container_id"];  
            $post = get_post( $current_post_id );
            $args = array(
            'posts_per_page'   => -1,
            'post_type' => 'review',
            'meta_key' => '_wpcf_belongs_' . $post->post_type . '_id',
            'meta_value' => $post->ID,
        );
        $child_posts = get_posts($args);
                
        $sum = 0;
        $num = 0;
        foreach ($child_posts as $child_post) {
            $ratings = get_post_meta($child_post->ID, 'wpcf-rating', true);
            if($ratings)
            {
                $sum += $ratings;
                $num ++;
            }
        }
        $average = 0;
        if($num>0)
        {
            $average = $sum/$num;
        }
        $res = $average;
        if($average==0) $res = 0;
        if($average>0.001 && $average<0.5)$res = 0.5;
        if($average>0.501 && $average<1) $res = 1;
        if($average>1.001 && $average<1.5) $res = 1.5;
        if($average>1.501 && $average<2) $res = 2;
        if($average>2.001 && $average<2.5) $res = 2.5;
        if($average>2.501 && $average<3) $res = 3;
        if($average>3.001 && $average<3.5) $res = 3.5;
        if($average>3.501 && $average<4) $res = 4;
        if($average>4.001 && $average<4.5) $res = 4.5;
        if($average>4.501 && $average<5) $res = 5;
         
        update_post_meta( $current_post_id, 'wpcf-average-rating', $res );
        update_post_meta( $current_post_id, 'wpcf-total-ratings', $num );
    }
}
add_action('cred_save_data', 'update_post_ratings',10,2);
#430377
tax-view-filters.jpg
schema string.jpg
schema in custom fields.jpg
schema final.jpg

I wanted to provide another way of implementing Schema on your listings. I know the OP had a restaurants directory, but for those with multiple categories, I have found a way to dynamically provide the correct Schema for any type of listing. It involves the use of a taxonomy custom term field, a taxonomy view, and knowledge of proper, specific Schema for various businesses, links of which will be provided.

Step 1. Find the proper Schema for your categories -

If your directory has multiple types of listings, you probably have a taxonomy for them like "Listings Categories". In this taxonomy, you have terms such as "Restaurants," "Cafes," "Bars," and so on. Instead of just using the general "LocalBusiness" Schema term for your listings, you should be as specific as possible. The link below is an excel spreadsheet of the best Schema term to use for various businesses. If you can't find a specific term, try checking Google: just search "Your Term" - Schema.

Link: hidden link

Step 2. Create a custom term field on your taxonomy and place the correct Schema term inside of each term's custom field.

It sounds confusing, but it's really easy. Go to your Toolset dashboard, then find "Term Fields". Add a new field group called "Schema Modifier," and attach it to the taxonomy you need it for. In my case, it is called "Listings Categories". Then you will add a single line field to this field group called "Schema String". See the screenshot below of what it will look like.

Step 3. Fill in the "Schema String" field on your taxonomy's terms with the correct Schema term you found in Step 1.

Only fill in the most specific ones (for example, if you have a parent term "Art&Entertainment", leave that alone. Instead, fill in the fields for the children, e.g. "Art Galleries", "Cinemas", etc.). See screenshot below.

Step 4. Create a taxonomy view and place the Schema script in there while using views shortcodes to populate the fields automatically.

OK, so we create a taxonomy view for our taxonomy, "Listings Categories", then we set Query Filter to return "Taxonomy is set by the page where this View is inserted", so it will only output results for terms that are attached to the listing where the view is placed. To be extra, extra safe, we should only output fields where "wpcf-schema-string is a string greater than '' ", meaning no fields for terms with blank fields will be output. See the screenshot for clarification.

One thing I must stress here is that you must tell Views to only query ONE value. If on your listings, you selected multiple terms which have the Schema field filled in, that will get output multiple times and will cause errors.

Next, we have to populate the view with Schema script. For this, I used the JSON-LD method, which is different from what the OP used. JSON-LD is now what Google recommends, and worked better for my setup. For a business, an example of this script is -

<script type="application/ld+json">
{
  "@context": "<em><u>hidden link</u></em>",
  "@type": "Museum",
  "address": {
    "@type": "PostalAddress",
    "addressLocality": "Hangzhou",
    "addressRegion": "Zhejiang",
    "streetAddress": "浙江省杭州市滨江区滨文路548, Binjiang District",
  	"addressCountry": "CN"
  },
  "aggregateRating": {
    "@type": "AggregateRating",
    "ratingValue": "4",
  	"bestRating": "5",
    "worstRating": "0.5",
    "reviewCount": "5"
  },
  "name": "Zhejiang Museum of Traditional Chinese Medicine (浙江中医药博物馆)",
  "image": "",
  "openingHours": [
    ""
  ],
  "telephone": "(+86) ",
  "url": ""
}
</script>

So as you can see, I have even put my Total Ratings and Average Reviews fields inside of this, which is something Schema loves. This is the final output, but what do you need to put between <wpv-loop></wpv-loop>? The answer is below (and please do some research on Schema before deciding which fields you would like to implement as every site is different).

		<wpv-loop>
          <script type="application/ld+json">
{
  "@context": "<em><u>hidden link</u></em>",
  "@type": "[types termmeta='schema-string' output='raw'][/types]",
  "@id": "[wpv-post-url]",
  "address": {
    "@type": "PostalAddress",
    "addressLocality": "Business's City",
    "addressRegion": "Business's State/ Province",
    "streetAddress": "Business's Address, District/Town",
  	"addressCountry": "Business's Country"
  },
[wpv-conditional if="( $(wpcf-total-ratings) gt '' )"]  
"aggregateRating": {
    "@type": "AggregateRating",
    "ratingValue": "[types field='average-rating' format='FIELD_VALUE'][/types]",
  	"bestRating": "5",
    "worstRating": "0.5",
    "reviewCount": "[types field='total-ratings' format='FIELD_VALUE'][/types]"
  },
[/wpv-conditional]
  "name": "[wpv-post-title]",
  "image": "[wpv-post-featured-image output='url']",
  "openingHours": [
    "[types field='listing-hours'][/types]"
  ],
  "telephone": "[types field='listing-phone'][/types]",
  "url": "[types field='listing-website' output='raw'][/types]"
}
</script>
		</wpv-loop>

Right, so along with normal fields that I use for my listings, like phone, website, hours, etc., you can see that "aggregateRating" uses reviews shortcodes, and the custom term field we created in Step 2. goes in this string:

"@type": "[types termmeta='schema-string' output='raw'][/types]",

Please note that you will have to manually find the types shortcodes for your listings fields in another view because the plugin will not let you select them when adding a taxonomy view.

As a safeguard, if the schema-string for terms on a listing hasn't been set, you still need to output Schema, fortunately, Views let's us output something if nothing was found. In between the

[wpv-no-items-found][/wpv-no-items-found]

fields, you can use the exact same code as above, with the only exception that you set the Schema "@type" to LocalBusiness (or whatever is best for you).

Awesome, now all we need to do is...

Step 5. Place the taxonomy view in the layout or content template for your listings' SINGLE POSTS

This one is straightforward if you know how to use views. Place it anywhere in the loop. Since the only output is a script, it won't change the display of anything.

Lastly, you should verify that the script is working correctly. Use the Google structured data tester:
hidden link

And either copy + paste your page's source code (right click on page and 'view source code'), or just paste your URL if you have a live site. If you see the correct Schema terms with no errors, you've done well. See my last screenshot for what you should see. I've even implemented Schema into my reviews, so you will see those as well.

PS: Sorry if I've been bombarding everyone with email updates for new posts, but this thread will be a great resource for people building a directory site with Toolset. Any questions/ concerns/ feedback/ improvements are more than welcome.

#458656

Thanks for your updates George... this reviews/ratings thing is something I am trying to achieve.

Would you mind letting a layman understand how you install the hidden link - I have read through the install notes but its not clear to me on how this achived...
thanks

#465247

I figured it out my above message with a bit of sleep... anyone else needs to know - ping me.

#480639

I wanted to add my comment on this - if you have been following the thread here:
https://toolset.com/forums/topic/how-to-get-rating-average-from-cred-for-review/page/3/#post-429082

Thanks to @george and the many other that have contributed @luoyang @trigger

I also had trouble getting the combined code working like @jsono has in this thread
https://toolset.com/forums/topic/cred-form-does-not-save-value-into-database

This is how I did it after reading this thread and countless hours.
** If you have copied @george code from the previous mentioned post ** AND the slug, post types, CRED form ID is correct!

- If your review CRED from is on ANOTHER page!

e.g you have a review button that links to another page like this in the content somehow.

hidden link

OR using the CRED Child link method:

[cred_child_link_form form='164' parent_id='-1' text='Review' target='_self']

You need to change this in the original code (replace it)

        $current_post_id = $form_data["container_id"];  
         $post = get_post( $current_post_id );

To this:
- Take the slug in the URL of the CRED form page e.g parent_agency_id and add it here $parent_post = $_GET['HERE']
This is where my CRED form is - you can see the query parameter in the URL - use that: parent_agency_id
"hidden link"

            $parent_post = $_GET['parent_agency_id'];
            $post = get_post( $parent_post );

-- Now, you need to change one other thing in the original code.

Original (at the bottom)

        update_post_meta( $current_post_id, 'wpcf-average-rating', $res );
        update_post_meta( $current_post_id, 'wpcf-total-ratings', $num );

Replace both: $current_post_id
With: $parent_post

        update_post_meta( $parent_post, 'wpcf-average-rating', $res );
        update_post_meta( $parent_post, 'wpcf-total-ratings', $num );

---
That's it - worked for me... ?

#481427

@stuart and @george, re the total-ratings and average-reviews you mention, where are these added, in the parent post? I tried this with no success. My Cred form is linked to another page as per Stuart's example. My parent is post and my child is review.

I am assuming that we want to get the average to display in the actual post, so in my case the first line of code would be:

//*Update Avg Ratings and Total # of Ratings after review submission
function update_post_post($post_id, $form_data)

That did not work however, and neither did the original code.

Any suggestions?

#1351193

Hello all,

Thanks everyone for this essential feature! Unfortunately it's not updating those custom fields, and I'm not quite sure why...

It this still working in the current Toolset version?

I'd appreciate if you have any ideas. I'll attach the code I've added in my functions.php.

The child 'review' CRED form is attached to the bottom of the parent 'recipe' post.

Parent post type: recipe
Child post type: recipe-review
Custom field: ratings (radio buttons with 1 - 5)
Average field: average-rating
Total ratings field: total-rating

Also, what in your opinion is the most reliable way to turn the radio buttons into stars?

Thanks for any help!

//*Update Avg Ratings and Total # of Ratings after review submission
function update_post_ratings($post_id, $form_data)
{
    // if a specific form, change ID to the CRED "Review" ID
    if ($form_data['id']==63)
    {
        //Get ID of Post Being Reviewed
        $current_post_id = $form_data["container_id"];  
            $post = get_post( $current_post_id );
            $args = array(
            'posts_per_page'   => -1,
            'post_type' => 'recipe',
            'meta_key' => '_wpcf_belongs_' . $post->post_type . '_id',
            'meta_value' => $post->ID,
        );
        $child_posts = get_posts($args);
                 
        $sum = 0;
        $num = 0;
        foreach ($child_posts as $child_post) {
            $ratings = get_post_meta($child_post->ID, 'wpcf-ratings', true);
            if($ratings)
            {
                $sum += $ratings;
                $num ++;
            }
        }
        $average = 0;
        if($num>0)
        {
            $average = $sum/$num;
        }
        $res = $average;
        if($average==0) $res = 0;
        if($average>0.001 && $average<0.5)$res = 0.5;
        if($average>0.501 && $average<1) $res = 1;
        if($average>1.001 && $average<1.5) $res = 1.5;
        if($average>1.501 && $average<2) $res = 2;
        if($average>2.001 && $average<2.5) $res = 2.5;
        if($average>2.501 && $average<3) $res = 3;
        if($average>3.001 && $average<3.5) $res = 3.5;
        if($average>3.501 && $average<4) $res = 4;
        if($average>4.001 && $average<4.5) $res = 4.5;
        if($average>4.501 && $average<5) $res = 5;
          
        update_post_meta( $current_post_id, 'wpcf-average-rating', $res );
        update_post_meta( $current_post_id, 'wpcf-total-ratings', $num );
    }
}
add_action('cred_save_data', 'update_post_ratings',10,2);

This ticket is now closed. If you're a WPML client and need related help, please open a new support ticket.