> ## Documentation Index
> Fetch the complete documentation index at: https://dokumentation.websale.de/llms.txt
> Use this file to discover all available pages before exploring further.

# Materials: eKomi product rating

> Complete examples for the eKomi product rating: rating template with and without AJAX, AJAX template, JavaScript callback functions, and CSS for the rating bars.

The eKomi product rating shows the star ratings and customer comments for an item on the product page. This page contains the complete sample files for it: the rating template in two variants, the AJAX template, the JavaScript callback functions, and the CSS for the rating bars.

All labels in the examples are sample texts. Replace them with your own or with text placeholders from the `shop.config`.

Guide: eKomi product rating · Reference: E-PRODRATING-EKOMI tags

## Overview of the files

| File | Purpose | AJAX only |
| - | - | - |
| `incl_prodrating_ekomi.htm` | the actual rating template, in two variants | no |
| `ws_ajax_eKomi.htm` | delivers the rating block as an AJAX fragment | yes |
| `ws_design.js` | the four callback functions for the AJAX call | yes |
| `styles.css` | the styling of the rating bars | no |

## With or without AJAX

Both variants display the same thing. The only difference is what happens when paging and when filtering by "X stars".

| | without AJAX | with AJAX |
| - | - | - |
| Paging and filtering | normal links with `href` | `onclick` with `ws_AJAXloadTemplate` and `return false` |
| Page is reloaded | yes | no, only the rating block |
| Additional files | none | `ws_ajax_eKomi.htm` and `ws_design.js` |

Choose one variant and stick with it. Mixing both results in some of the links reloading the page and others not.

## The rating template

Both versions belong in the same file `incl_prodrating_ekomi.htm`. Use only one of them.

> [accordion] incl\_prodrating\_ekomi.htm, without AJAX
>
> ```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
> {E-WS-TplComment}<!-- Einstellung, wie viele Bewertungen auf einer Seite angezeigt werden sollen -->{/E-WS-TplComment}
> ~E-PRODRATING-EKOMI_Count(15)~
>
> <h1>Artikelbewertung zum Artikel ~PR-Name~</h1>
>
> {E-WS-TplComment}<!-- Anzeige der Gesamtbewertungen und der Grafik-Balken -->{/E-WS-TplComment}
> {@E-PRODRATING-EKOMI_Ratings}
>    <div class="rating_ekomi_graphic_line rating_ekomi_graphic_line_~E-PRODRATING-EKOMI_RatingVotes~">
>       <a {E-PRODRATING-EKOMI_RatingVotes}href="~PR-Link~&~E-PRODRATING-EKOMI_RatingFilterParam~"{/E-PRODRATING-EKOMI_RatingVotes}>
>          ~E-PRODRATING-EKOMI_Rating~ Sterne
>       </a>
>       <div class="rating_ekomi_graphic_line_complete">
>          <div class="rating_ekomi_graphic_line_filler" style="width: ~E-PRODRATING-EKOMI_RatingPercentage~%"></div>
>       </div>
>       <a {E-PRODRATING-EKOMI_RatingVotes}href="~PR-Link~&~E-PRODRATING-EKOMI_RatingFilterParam~"{/E-PRODRATING-EKOMI_RatingVotes}>
>          (~E-PRODRATING-EKOMI_RatingVotes~)
>       </a>
>    </div>
> {/@E-PRODRATING-EKOMI_Ratings}
>
> <hr>
>
> Gesamtbewertung: <img src="~E-PRODRATING-EKOMI_ScoreImg~"> ~E-PRODRATING-EKOMI_Score~<br>
> Anzahl der Bewertungen: ~E-PRODRATING-EKOMI_Votes~ Bewertungen<br>
> ~E-PRODRATING-EKOMI_PositivePercentage~% der ~E-PRODRATING-EKOMI_Votes~ abgegebenen Bewertungen waren positiv.<br>
>
> <hr>
>
> {E-WS-TplComment}<!-- Blätterfunktion -->{/E-WS-TplComment}
> {E-PRODRATING-EKOMI_Paging}
>    {E-PRODRATING-EKOMI_PagingBack}
>       <a href="~PR-Link~&~E-PRODRATING-EKOMI_PagingParam~"> &lt;&lt; </a>
>    {/E-PRODRATING-EKOMI_PagingBack}
>
>    {E-PRODRATING-EKOMI_PagingMoreBefore(2)}
>       {E-PRODRATING-EKOMI_PagingFirst}
>          <a href="~PR-Link~&~E-PRODRATING-EKOMI_PagingParam~">~E-PRODRATING-EKOMI_Page~</a>
>       {/E-PRODRATING-EKOMI_PagingFirst}
>    {/E-PRODRATING-EKOMI_PagingMoreBefore(2)}
>
>    {E-PRODRATING-EKOMI_PagingMoreBefore(3)}
>       ...
>    {/E-PRODRATING-EKOMI_PagingMoreBefore(3)}
>
>    {@E-PRODRATING-EKOMI_PagingBefore(2)}
>       <a href="~PR-Link~&~E-PRODRATING-EKOMI_PagingParam~">~E-PRODRATING-EKOMI_Page~</a>
>    {/@E-PRODRATING-EKOMI_PagingBefore(2)}
>
>    ~E-PRODRATING-EKOMI_Page~
>
>    {@E-PRODRATING-EKOMI_PagingAfter(2)}
>       <a href="~PR-Link~&~E-PRODRATING-EKOMI_PagingParam~">~E-PRODRATING-EKOMI_Page~</a>
>    {/@E-PRODRATING-EKOMI_PagingAfter(2)}
>
>    {E-PRODRATING-EKOMI_PagingMoreAfter(3)}
>       ...
>    {/E-PRODRATING-EKOMI_PagingMoreAfter(3)}
>
>    {E-PRODRATING-EKOMI_PagingMoreAfter(2)}
>       {E-PRODRATING-EKOMI_PagingLast}
>          <a href="~PR-Link~&~E-PRODRATING-EKOMI_PagingParam~">~E-PRODRATING-EKOMI_Page~</a>
>       {/E-PRODRATING-EKOMI_PagingLast}
>    {/E-PRODRATING-EKOMI_PagingMoreAfter(2)}
>
>    {E-PRODRATING-EKOMI_PagingNext}
>       <a href="~PR-Link~&~E-PRODRATING-EKOMI_PagingParam~"> &gt;&gt; </a>
>    {/E-PRODRATING-EKOMI_PagingNext}
>
>    <hr>
> {/E-PRODRATING-EKOMI_Paging}
>
> {E-WS-TplComment}<!-- Anzeige der Bewertungen -->{/E-WS-TplComment}
> {E-PRODRATING-EKOMI_FeedbackData}
>
>    {E-PRODRATING-EKOMI_ActiveFilter}
>       <p>~E-PRODRATING-EKOMI_RatingVotes(~E-PRODRATING-EKOMI_ActiveFilter~)~ Bewertungen mit ~E-PRODRATING-EKOMI_ActiveFilter~ Sternen</p>
>       <a href="~PR-Link~">Alle Bewertungen anzeigen</a>
>       <hr>
>    {/E-PRODRATING-EKOMI_ActiveFilter}
>
>    {@E-PRODRATING-EKOMI_FeedbackData}
>       <img src="~E-PRODRATING-EKOMI_FeedbackData_RatingImage~">
>       <h3>~E-PRODRATING-EKOMI_FeedbackData_Timestamp_day~.~E-PRODRATING-EKOMI_FeedbackData_Timestamp_month~.~E-PRODRATING-EKOMI_FeedbackData_Timestamp_year~
>          (bestätigter Kauf)</h3>
>       <p>~E-PRODRATING-EKOMI_FeedbackData_Feedback~</p>
>
>       {E-PRODRATING-EKOMI_FeedbackData_Merchant_Answer}
>          <div class="infobox">~E-PRODRATING-EKOMI_FeedbackData_Merchant_Answer~</div>
>       {/E-PRODRATING-EKOMI_FeedbackData_Merchant_Answer}
>    {/@E-PRODRATING-EKOMI_FeedbackData}
>
> {/E-PRODRATING-EKOMI_FeedbackData}
> ```

> [accordion] incl\_prodrating\_ekomi.htm, with AJAX
>
> ```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
> {E-WS-TplComment}<!-- Einstellung, wie viele Bewertungen auf einer Seite angezeigt werden sollen -->{/E-WS-TplComment}
> ~E-PRODRATING-EKOMI_Count(10)~
>
> <h1>Artikelbewertung zum Artikel ~PR-Name~</h1>
> <h2>~E-PRODRATING-EKOMI_Votes~ Bewertungen</h2>
> <p><img src="~E-PRODRATING-EKOMI_ScoreImg~"> ~E-PRODRATING-EKOMI_Score~</p>
> <p>~E-PRODRATING-EKOMI_PositiveVotes~ von ~E-PRODRATING-EKOMI_Votes~ Kunden würden diesen Artikel empfehlen</p>
>
> {@E-PRODRATING-EKOMI_Ratings}
>    <div class="rating_ekomi_graphic_line rating_ekomi_graphic_line_~E-PRODRATING-EKOMI_RatingVotes~">
>       <a {E-PRODRATING-EKOMI_RatingVotes}
>             onclick="ws_AJAXloadTemplate('~PR-Link~&tpl=ws_ajax_eKomi.htm&~E-PRODRATING-EKOMI_RatingFilterParam~',
>             '~WS-CharSet~', ws_AJAXloadRatingEkomiStart, wsAJAXloadRatingEkomiError, 'ws_AJAXloadRatingEkomiResponseSuccess()',
>             'wsAJAXloadRatingEkomiResponseError()'); return false;"
>          {/E-PRODRATING-EKOMI_RatingVotes}>
>          ~E-PRODRATING-EKOMI_Rating~ Sterne
>       </a>
>       <div class="rating_ekomi_graphic_line_complete">
>          <div class="rating_ekomi_graphic_line_filler" style="width: ~E-PRODRATING-EKOMI_RatingPercentage~%"></div>
>          {E-PRODRATING-EKOMI_RatingVotes}
>             <p class="rating_ekomi_graphic_score">
>                ~E-PRODRATING-EKOMI_RatingVotes~ Stimmen
>             </p>
>          {/E-PRODRATING-EKOMI_RatingVotes}
>       </div>
>       <div class="clear"></div>
>    </div>
> {/@E-PRODRATING-EKOMI_Ratings}
>
> <hr>
>
> {E-PRODRATING-EKOMI_FeedbackData}
>
>    {E-PRODRATING-EKOMI_ActiveFilter}
>       <p>~E-PRODRATING-EKOMI_RatingVotes(~E-PRODRATING-EKOMI_ActiveFilter~)~ Bewertungen mit ~E-PRODRATING-EKOMI_ActiveFilter~ Sternen</p>
>       <a onclick="ws_AJAXloadTemplate('~PR-Link~&tpl=ws_ajax_eKomi.htm', '~WS-CharSet~', ws_AJAXloadRatingEkomiStart, wsAJAXloadRatingEkomiError,
>          'ws_AJAXloadRatingEkomiResponseSuccess()', 'wsAJAXloadRatingEkomiResponseError()'); return false;">
>          Alle Bewertungen anzeigen
>       </a>
>    {/E-PRODRATING-EKOMI_ActiveFilter}
>
>    {@E-PRODRATING-EKOMI_FeedbackData}
>       <img src="~E-PRODRATING-EKOMI_FeedbackData_RatingImage~">
>       <h3>~E-PRODRATING-EKOMI_FeedbackData_Timestamp_day~.~E-PRODRATING-EKOMI_FeedbackData_Timestamp_month~.~E-PRODRATING-EKOMI_FeedbackData_Timestamp_year~
>       (bestätigter Kauf)</h3>
>       <p>~E-PRODRATING-EKOMI_FeedbackData_Feedback~</p>
>
>       {E-PRODRATING-EKOMI_FeedbackData_Merchant_Answer}
>          <div class="infobox">~E-PRODRATING-EKOMI_FeedbackData_Merchant_Answer~</div>
>       {/E-PRODRATING-EKOMI_FeedbackData_Merchant_Answer}
>    {/@E-PRODRATING-EKOMI_FeedbackData}
>
>    {E-WS-TplComment}<!-- Blättern mit AJAX-Aufruf -->{/E-WS-TplComment}
>    {E-PRODRATING-EKOMI_Paging}
>       {E-PRODRATING-EKOMI_PagingMoreBefore(2)}
>          {E-PRODRATING-EKOMI_PagingFirst}
>             <a onclick="ws_AJAXloadTemplate('~PR-Link~&tpl=ws_ajax_eKomi.htm&~E-PRODRATING-EKOMI_PagingParam~', '~WS-CharSet~', ws_AJAXloadRatingEkomiStart,
>                wsAJAXloadRatingEkomiError, 'ws_AJAXloadRatingEkomiResponseSuccess()', 'wsAJAXloadRatingEkomiResponseError()'); return false;">
>                ~E-PRODRATING-EKOMI_Page~
>             </a>
>          {/E-PRODRATING-EKOMI_PagingFirst}
>       {/E-PRODRATING-EKOMI_PagingMoreBefore(2)}
>
>       {E-PRODRATING-EKOMI_PagingMoreBefore(3)}
>          <div class="rating_paging_placeholder">...</div>
>       {/E-PRODRATING-EKOMI_PagingMoreBefore(3)}
>
>       {@E-PRODRATING-EKOMI_PagingBefore(2)}
>          <a onclick="ws_AJAXloadTemplate('~PR-Link~&tpl=ws_ajax_eKomi.htm&~E-PRODRATING-EKOMI_PagingParam~', '~WS-CharSet~', ws_AJAXloadRatingEkomiStart,
>             wsAJAXloadRatingEkomiError, 'ws_AJAXloadRatingEkomiResponseSuccess()', 'wsAJAXloadRatingEkomiResponseError()'); return false;">
>             ~E-PRODRATING-EKOMI_Page~
>          </a>
>       {/@E-PRODRATING-EKOMI_PagingBefore(2)}
>
>       <div class="rating_paging_actualpage">~E-PRODRATING-EKOMI_Page~</div>
>
>       {@E-PRODRATING-EKOMI_PagingAfter(2)}
>          <a onclick="ws_AJAXloadTemplate('~PR-Link~&tpl=ws_ajax_eKomi.htm&~E-PRODRATING-EKOMI_PagingParam~', '~WS-CharSet~', ws_AJAXloadRatingEkomiStart,
>             wsAJAXloadRatingEkomiError, 'ws_AJAXloadRatingEkomiResponseSuccess()', 'wsAJAXloadRatingEkomiResponseError()'); return false;">
>             ~E-PRODRATING-EKOMI_Page~
>          </a>
>       {/@E-PRODRATING-EKOMI_PagingAfter(2)}
>
>       {E-PRODRATING-EKOMI_PagingMoreAfter(3)}
>          <div class="rating_paging_placeholder">...</div>
>       {/E-PRODRATING-EKOMI_PagingMoreAfter(3)}
>
>       {E-PRODRATING-EKOMI_PagingMoreAfter(2)}
>          {E-PRODRATING-EKOMI_PagingLast}
>             <a onclick="ws_AJAXloadTemplate('~PR-Link~&tpl=ws_ajax_eKomi.htm&~E-PRODRATING-EKOMI_PagingParam~', '~WS-CharSet~', ws_AJAXloadRatingEkomiStart,
>                wsAJAXloadRatingEkomiError, 'ws_AJAXloadRatingEkomiResponseSuccess()', 'wsAJAXloadRatingEkomiResponseError()'); return false;">
>                ~E-PRODRATING-EKOMI_Page~
>             </a>
>          {/E-PRODRATING-EKOMI_PagingLast}
>       {/E-PRODRATING-EKOMI_PagingMoreAfter(2)}
>    {/E-PRODRATING-EKOMI_Paging}
>
> {/E-PRODRATING-EKOMI_FeedbackData}
> ```

> [!WARNING]
>
> `~E-PRODRATING-EKOMI_Count(n)~` isn't just a display setting. This tag loads the ratings and sets up paging. If it's missing or placed too far down, all blocks below it remain empty.
>
> So place it as the very first tag at the beginning of the template.

> [!NOTE]
>
> The AJAX version of the previous documentation contains `Count` twice, with 15 and with 10, and with two different comments. Since the second call overrides the first, effectively 10 ratings per page would be shown. Shortened to one call here.

### Other differences between the two versions

Beyond the links, the AJAX version displays some things differently. This isn't a requirement but a matter of taste, and you can mix both as you like.

* The AJAX version already states the total number in the heading and writes the number of votes inside the bar instead of next to it.
* The version without AJAX shows `~E-PRODRATING-EKOMI_PositivePercentage~` as a percentage, the AJAX version shows `~E-PRODRATING-EKOMI_PositiveVotes~` as an absolute number.
* Without AJAX, the paging bar is **above** the ratings and outside `{E-PRODRATING-EKOMI_FeedbackData}`; with AJAX, it's **below** the ratings and inside this bracketing. Inside means: without ratings, there's no paging bar either. This is the more sensible variant.
* Only the version without AJAX has arrows for one page forward and back, via `PagingBack` and `PagingNext`.

## The AJAX template

`ws_ajax_eKomi.htm` is short. It only delivers the rating block, without the rest of the page framework.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{ST-Ajax}
  <WS-Ajax-product_rating_ekomi>
           ~WS-Module(rating_ekomi)~
  </WS-Ajax-product_rating_ekomi>
{/ST-Ajax}
```

The name between the angle brackets determines which container on the product page is replaced. So give the `div` that contains the rating the ID `product_rating_ekomi`.

## The JavaScript callback functions

`ws_AJAXloadTemplate` expects four functions. Even if you don't want to do anything in them, they must exist, otherwise the call aborts with an error.

```js theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
// eKomi Produktbewertung

// Wird aufgerufen, bevor die AJAX-Anfrage abgesetzt wird.
// Hier lässt sich eine Ladeanzeige einblenden.
function ws_AJAXloadRatingEkomiStart()
{
}

// Wird aufgerufen, wenn das Nachladen der eKomi-Produktbewertung erfolgreich war.
function ws_AJAXloadRatingEkomiResponseSuccess()
{
}

// Wird aufgerufen, wenn das Nachladen der eKomi-Produktbewertung nicht erfolgreich war.
function wsAJAXloadRatingEkomiResponseError()
{
}

// Wird aufgerufen, wenn die AJAX-Kommunikation fehlschlug.
// Hier lässt sich ein allgemeiner Kommunikationsfehler anzeigen,
// beispielsweise wenn die Internetverbindung unterbrochen wurde.
function wsAJAXloadRatingEkomiError()
{
}
```

> [!NOTE]
>
> Two of the four names begin with `ws_`, the other two only with `ws`. This is inconsistent but correct: the templates call exactly these names. If you change a name, you must also change it everywhere in the template.

## The CSS for the rating bars

```css theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
.rating_ekomi_graphic_line {
   margin-bottom: 2px;
}

.rating_ekomi_graphic_line a {
   margin-right: 5px;
   text-decoration: none;
}

.rating_ekomi_graphic_line a:hover {
   text-decoration: underline;
   cursor: pointer;
}

.rating_ekomi_graphic_line_complete {
   margin-right: 5px;
   background: #f4f4f4;
   border: 1px solid #ddd;
   display: inline-block;
   vertical-align: middle;
   width: 180px;
   height: 18px;
   position: relative;
}

.rating_ekomi_graphic_line_complete a {
   font-size: 11px;
}

.rating_ekomi_graphic_line_filler {
   background: #ffc757;
   height: 100%;
}

.rating_ekomi_graphic_line_0 a,
.rating_ekomi_graphic_line_0 a:hover {
   color: #999;
   text-decoration: none !important;
   cursor: default;
}

.rating_ekomi_graphic_score {
   color: #666;
   position: absolute;
   right: 10px;
   top: 3px;
}
```

### The trick with zero

Both templates add a second class to the row that ends with the number of votes:

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<div class="rating_ekomi_graphic_line rating_ekomi_graphic_line_~E-PRODRATING-EKOMI_RatingVotes~">
```

With three votes, this results in `rating_ekomi_graphic_line_3`; with no votes, `rating_ekomi_graphic_line_0`. There's a rule in the stylesheet only for zero, and it makes the text gray and the mouse pointer normal. This way, a rating level without votes no longer looks like a link. At the same time, the bracketing around the `href` or `onclick` ensures that it isn't one either.

> [!NOTE]
>
> The templates use four additional classes that are missing from this stylesheet: `clear`, `infobox`, `rating_paging_placeholder`, and `rating_paging_actualpage`. Add them yourself, otherwise the merchant response and the paging bar appear without styling.

## Where the tags are described

This page explains the sample files, not the individual tags. The complete description of all `E-PRODRATING-EKOMI_` tags, with types, parameters, and the peculiarities of the paging bar, is on the reference page.

Reference: E-PRODRATING-EKOMI tags

Three points from there are particularly important when recreating the examples:

* `Count()` belongs at the beginning of the template as the first tag. It loads the ratings and sets up paging.
* If the numeric parameter is missing from the four paging tags, they calculate with five pages. The examples above specify `2` and `3` everywhere.
* `PagingParam` automatically includes an active filter. You don't need to append it.

> [!NOTE]
>
> Compared to the previous documentation, eight places in the listings have been corrected: a superfluous curly brace after a bracketing, an incorrectly closed loop `PagingBefore(2>`, the duplicate `Count` call in the AJAX version, a comment that referred to reloading terms and conditions instead of ratings, a character encoding error in the JavaScript, a comment stuck to the first line, a superfluous space in a class attribute, and the heading of the AJAX page, which read "without AJAX".


## Related topics

- [E-PRODRATING-EKOMI_ (eKomi product rating)](https://dokumentation.websale.de/en/v8s/referenz/tags/e-prodrating-ekomi.md)
- [Structured data and rich snippets](https://dokumentation.websale.de/en/v8s/seo/strukturierte-daten-rich-snippets.md)
- [Products, catalog, and search](https://dokumentation.websale.de/en/v8s/referenz/konfigurationen/shopkonfiguration-shop-config/produkte-katalog-und-suche.md)
- [Sorting product lists](https://dokumentation.websale.de/en/v8s/funktionen-fuer-produktlisten/produktlisten-sortieren.md)
- [$wsProductRating - Product ratings](https://dokumentation.websale.de/en/frontend/referenz/module/wsproductrating.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.