Related Docs

You have seen all Documentation regarding ToolWine Reviews & Ratings.
Search the complete TukuToi Software Documentation!

How To

How to create a Rating System using Toolset

Often websites (like for example TukuToi or Booking and other service-based WebSites) require a rating or review system.

While TukuToi developed the ToolWine Reviews & Ratings plugin to facilitate this task, sometimes you might want a very minimal approach instead of installing a new plugin. This Documentation explains how to setup a Ratings System with just Toolset, and it also helps to understand how the ToolWine Reviews & Ratings Plugin is built up.


Reviews, or Ratings are usually based on a “Star Rating” with some written feedback that is left by the visitor/client and will then display on a “What people say about us” section.

There are WordPress Plugins that help you create such systems, but it is trivial enough to create it with Toolset Plugins (or even full custom PHP and HTML).

In this Document we will analyse how to create it with some Custom CSS and HTML using Toolset Forms as a submission form to leave the feedback.

Lets dive in.

  1. We use the StarAbility CSS library for the Stars Rating feature. More on that later
  2. We use Toolset Types Plugin to add a Post Type called “Testimonials” (or anything you like). This post Type features nothing else but the Title.
  3. We use the Toolset Types Plugin to add the following custom Fields:
    – Feedback (A multiple line field)
    – Name (A single line field)
    – Website (An URL field, repeatable)
    – Rating (a radio field, with 5 options: 1, 2, 3, 4, 5)
  4. We use the Toolset Forms Plugin to “add new Testimonials”. We use the “Expert Mode” Editing option, and include in the Form the Post Title Field, the Feedback Custom Field, the Name Custom Field, the Website Custom Field. For the Rating field we instead create a custom HTML Input as follows:
<label>Your Rating</label>
<fieldset class="starability-basic">
   <input type="radio" id="no-rate" class="input-no-rate" name="rating" value="0" aria-label="No rating." />
   <input type="radio" id="first-rate1" name="rating" value="1" />
   <label for="first-rate1" title="Terrible"></label>
   <input type="radio" id="first-rate2" name="rating" value="2" />
   <label for="first-rate2" title="Not good"></label>
   <input type="radio" id="first-rate3" name="rating" value="3" />
   <label for="first-rate3" title="Average"></label>
   <input type="radio" id="first-rate4" name="rating" value="4" />
   <label for="first-rate4" title="Very good"></label>
   <input type="radio" id="first-rate5" name="rating" value="5" checked/>
   <label for="first-rate5" title="Amazing"></label>
</fieldset>

Next, we add the CSS from the step 1 to the Forms CSS editor:

.wpt-form-set-radios-wpcf-rating-stars{
   display:inline-flex;
 }
 input[type=text], textarea{
   font-size: 13px !important;
 }
 .wpt-repetitive-field{
   margin-bottom: 16px;
 }
 .wpt-repdrag{
   display:none;
 }
 .starability-basic {
   display: block;
   position: relative;
   width: 150px;
   min-height: 60px;
   padding: 0;
   border: none;
 }
 .starability-basic > input {
   position: absolute;
   margin-right: -100%;
   opacity: 0;
 }
 .starability-basic > input:checked ~ label,
 .starability-basic > input:focus ~ label {
   background-position: 0 0;
 }
 .starability-basic > input:checked + label,
 .starability-basic > input:focus + label {
   background-position: 0 -30px;
 }
 .starability-basic > input[disabled]:hover + label {
   cursor: default;
 }
 .starability-basic > input:not([disabled]):hover ~ label {
   background-position: 0 0;
 }
 .starability-basic > input:not([disabled]):hover + label {
   background-position: 0 -30px;
 }
 .starability-basic > input:not([disabled]):hover + label::before {
   opacity: 1;
 }
 .starability-basic > input:focus + label {
   outline: 1px dotted #999;
 }
 .starability-basic .starability-focus-ring {
   position: absolute;
   left: 0;
   width: 100%;
   height: 30px;
   outline: 2px dotted #999;
   pointer-events: none;
   opacity: 0;
 }
 .starability-basic > .input-no-rate:focus ~ .starability-focus-ring {
   opacity: 1;
 }
 .starability-basic > label {
   position: relative;
   display: inline-block;
   float: left;
   width: 30px;
   height: 30px;
   font-size: 0.1em;
   color: transparent;
   cursor: pointer;
   background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAA8CAMAAABGivqtAAAAxlBMVEUAAACZmZn2viTHuJ72viOampqampr1viSampr3vySampqdnZ34wiX1vSSampr1vSOZmZmampr1viT2vSOampr2viT2viSampr2viSampr2vyX4vyWbm5v3vSSdnZ32wSadnZ36wCWcnJyZmZn/wSr/2ySampr2vSP2viSZmZn2vSSZmZn2vST2viSampr2viSbm5ubm5uZmZn1vSSampqbm5v2vSWampqampr3vSf5wiT5vyagoKD/xCmkpKT/yCSZmZn1vSO4V2dEAAAAQHRSTlMA+vsG9fO6uqdgRSIi7+3q39XVqZWVgnJyX09HPDw1NTAwKRkYB+jh3L6+srKijY2Ef2lpYllZUU5CKigWFQ4Oneh1twAAAZlJREFUOMuV0mdzAiEQBmDgWq4YTWIvKRqT2Htv8P//VJCTGfYQZnw/3fJ4tyO76KE0m1b2fZu+U/pu4QGlA7N+Up5PIz9d+cmkbSrSNr9seT3GKeNYIyeO5j16S28exY5suK0U/QKmmeCCX6xs22hJLVkitMImxCvEs8EG3SCRCN/ViFPqnq5epIzZ07QJJvkM9Tkz1xnkmXbfSvR7f4H8AtXBkLGj74mMvjM1+VHZpAZ4LM4K/LBWEI9jwP71v1ZEQ6dyvQMf8A/1pmdZnKce/VH1iIsdte4U8VEtY23xOujxtFpWDgKbfjD2YeEhY0OzfjGeLyO/XfnNpAcmcjDwKOXRfU1IyiTRyEkaiz67pb9oJHJb9vVqKfgjLBPyF5Sq9T0KmSUhQmtiQrJGPHVi0DoSabj31G2gW3buHd0pY85lNdcCk8xlNDPXMuSyNiwl+theIb9C7RLIpKvviYy+M6H8qGwSAp6Is19+GP6KxwnggJ/kq6Jht5rnRQA4z9zyRRaXssvyqp5I6Vutv0vkpJaJtnjpz/8B19ytIayazLoAAAAASUVORK5CYII=");
   background-repeat: no-repeat;
   background-position: 0 -30px;
 }
 .starability-basic > label::before {
   content: '';
   position: absolute;
   display: block;
   height: 30px;
   background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAA8CAMAAABGivqtAAAAxlBMVEUAAACZmZn2viTHuJ72viOampqampr1viSampr3vySampqdnZ34wiX1vSSampr1vSOZmZmampr1viT2vSOampr2viT2viSampr2viSampr2vyX4vyWbm5v3vSSdnZ32wSadnZ36wCWcnJyZmZn/wSr/2ySampr2vSP2viSZmZn2vSSZmZn2vST2viSampr2viSbm5ubm5uZmZn1vSSampqbm5v2vSWampqampr3vSf5wiT5vyagoKD/xCmkpKT/yCSZmZn1vSO4V2dEAAAAQHRSTlMA+vsG9fO6uqdgRSIi7+3q39XVqZWVgnJyX09HPDw1NTAwKRkYB+jh3L6+srKijY2Ef2lpYllZUU5CKigWFQ4Oneh1twAAAZlJREFUOMuV0mdzAiEQBmDgWq4YTWIvKRqT2Htv8P//VJCTGfYQZnw/3fJ4tyO76KE0m1b2fZu+U/pu4QGlA7N+Up5PIz9d+cmkbSrSNr9seT3GKeNYIyeO5j16S28exY5suK0U/QKmmeCCX6xs22hJLVkitMImxCvEs8EG3SCRCN/ViFPqnq5epIzZ07QJJvkM9Tkz1xnkmXbfSvR7f4H8AtXBkLGj74mMvjM1+VHZpAZ4LM4K/LBWEI9jwP71v1ZEQ6dyvQMf8A/1pmdZnKce/VH1iIsdte4U8VEtY23xOujxtFpWDgKbfjD2YeEhY0OzfjGeLyO/XfnNpAcmcjDwKOXRfU1IyiTRyEkaiz67pb9oJHJb9vVqKfgjLBPyF5Sq9T0KmSUhQmtiQrJGPHVi0DoSabj31G2gW3buHd0pY85lNdcCk8xlNDPXMuSyNiwl+theIb9C7RLIpKvviYy+M6H8qGwSAp6Is19+GP6KxwnggJ/kq6Jht5rnRQA4z9zyRRaXssvyqp5I6Vutv0vkpJaJtnjpz/8B19ytIayazLoAAAAASUVORK5CYII=");
   background-position: 0 30px;
   pointer-events: none;
   opacity: 0;
 }
 .starability-basic > label:nth-of-type(5)::before {
   width: 120px;
   left: -120px;
 }
 .starability-basic > label:nth-of-type(4)::before {
   width: 90px;
   left: -90px;
 }
 .starability-basic > label:nth-of-type(3)::before {
   width: 60px;
   left: -60px;
 }
 .starability-basic > label:nth-of-type(2)::before {
   width: 30px;
   left: -30px;
 }
 .starability-basic > label:nth-of-type(1)::before {
   width: 0px;
   left: 0px;
 }
 @media screen and (-webkit-min-device-pixel-ratio: 2), screen and (min-resolution: 192dpi) {
   .starability-basic > label {
     background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAB4CAMAAACZ62E6AAABAlBMVEUAAACZmZmampr2vSObm5v/yiufn5+ampr1viP1viSZmZn2viOZmZmampqampr2viSampqampqcnJz5vyScnJz3wSf/wyn/xiujo6Oqqqr/0C/1vSOampr2viP2viOampr2viP2vST2viOampqampqampr1vyP3viSampr2vyT4vyX3viSbm5ubm5v5wCT8xSmgoKCampqampr3vyb2wiWenp72viOampqZmZmampr2viP2viP1viSampqbm5v2vyT3viObm5v4vyadnZ34wSSbm5v2viSZmZn2viP2vST2viP2viT1viOZmZn2viT2viX3viT3vyb2vyOZmZn1vSOZmZlNN+fKAAAAVHRSTlMA9uz4PQwS8O7r5+fTw4yMelw2MB0dFRELBgbS+/Hfu7uxqKWdg4N7ZmZMPi8pKRgPs0w7Nhb14drKw6Gck21tXkNDIyMZ1rDLycTBtaqVknlfV0sGP8ZwAAADW0lEQVRYw9zWvYqDQBSG4TPDoCAqKhYKQgoVLFaIgZCkiCBBUqVazv3fyu4aEXWdM85Uy779A+LP58AfTQgw73AwtxFiZIwbxMbUfuB3H4b49YNfZrbGodoI52+cm9hH9sbZwwAXOFbo2zjDsSzWxnecuuvaM8MpdtbEPs7y9azF5phZWrjERaWOPdpLbB81cICrgv3W4mvMLbU6RmFQeA5u5HhFEEbHLdWLsMxvHJXxW16Goh+ZqPyny1Az5j79SsCJoWHsBNAxQ9sNF26bWFuMC8v1LY+mmeTadjaqtaNnnXoxWBcde1nNWnzdb68xrOqvu22/MTzuPutujpJ122NvluSb8tTWk85CclDZQwLS0oa2TQpEKacsJy0kSJaQOKJxROKKxhWJ7zS+k9ijsUdim8Y2ZWNUFBP4pMKfOv8onX9WrsI5gd3VVLXtatxcuU0znGUHCUAS2DgrS6mT6hTzrXEjfIZj5Dk2xKkihqm4wKlQfQRqalhUP9UHo3FIPAG/Et44JVLsDDf0JHmB3OEByOwZES8hSAsviGjBdh3ylh6plmMnW4IyAUVJWcE/76vTell1EIaiMBwIAcWBA9GC0lIdKFXQQUsHVVCklN7ojf3+z3JOxYqK2TH555+K6CJJQtRbr9XtDmCnjH0AX9Va8J+liIMvDtRsCk2pEs6hKVexR2g7KuDihwt5a9MfprY0fkLXU9ZmFLpoJolN6GXKWWfZx0tHCocwKJSxC22ItYUEjmBUJHFjfYz1xQxlfaLiZsBExq2IPtbkNbLtOwwuGgjTLkH43mYtSzam7+1Bsr3nm5uExBQUozEh9V7N7uvmwZcqdpm0C6vJW63bZEuXtbrV2zpDzhrpYLBWMnY1mjV7JWFtMio7zbWniWFxvHnWm1yGxXmOPXP+L3YV2ysjnNhaZNeMcHPvuL27BMnVMaujljBAYyje4niH4g2ONyh+4PiB4gOODyjWcKxh1gZBNoJjEY4R/BLhF4IDEQ4QPBoEoyxH4+bxrUsHyxwxQlg0WHXqYifVLmo67cKY/UtaXFxBV26TLjuHrkp8BPJTMij1xQejdkgO24nf7dBOCRcbzQuNOR9Qs64GzzrfQa8It2oFAA6Zrga9xEeq1KHmLUHIiCAWInsg1x/MLqkMsItF8QAAAABJRU5ErkJggg==");
     background-size: 30px auto;
   }
 }
 @media screen and (-ms-high-contrast: active) {
   .starability-basic {
     width: auto;
   }
   .starability-basic > input {
     position: static;
     margin-right: 0;
     opacity: 1;
   }
   .starability-basic .input-no-rate {
     display: none;
   }
   .starability-basic > label {
     display: inline;
     float: none;
     width: auto;
     height: auto;
     font-size: 1em;
     color: inherit;
     background: none;
   }
   .starability-basic > label::before, .starability-basic > label::after {
     display: none;
   }
 }

This will, if properly done, already display the Form as seen here. Of course, the entire Form is using Bootstrap Markup for the lay outing.

Now, this form will save everything to the “Testimonial” Post Type we created, once submitted, but it won’t save the Custom Field “Rating”, because we used a Custom HTML input and not Toolset’s Form ShortCode for the Field.

We did this, so we can have full control over the actual star display and do not need to fiddle around with the Radio Boxes that Toolset would produce. See here (the part about labels) for the reason why we do use Custom HTML.
This means, we need to craft a tiny PHP function that takes the chosen Star Rating input and updates it to the respective field, when the form is submitted
We can use Toolset’s Forms API for this. The code we came up with looks like this:

add_action('cred_save_data', 'save_rating_data_action',10,2);
 function save_rating_data_action($post_id, $form_data)
 {
     // if a specific form
     if ($form_data['id']==111)//Change this ID to the ID of your Form that creates Testimonials
     {
         if ( isset($_POST['rating']) )//If your Input Field is named differently, change this slug
         {
             // add it to saved post meta. If your Custom Field has a different name, change it
             update_post_meta($post_id, 'wpcf-rating-stars', intval( $_POST['rating'] ), true);
         }
     }
 }

This code gets placed in your theme’s functions.php file. It will react when the form is submitted, and make sure the chosen “star” gets saved to the database in the field we added for the Rating.

That’s it!
Now you can display the Testimonial Posts in any page or post you like, for example by creating a Loop using Toolset Views, or like we did on TukuToi (bottom of the page here) using a Custom WP Query and the OwlCarousel library.