The Product Reviews Component renders a list of reviews for a product. It is typically used on product detail pages, but it can also power recent‑reviews widgets, sidebar lists, or threaded review sections.

Activate the component by adding:

data-v-component-reviews

The component supports filtering, sorting, pagination, and nested replies.


Component Options

Options are added as HTML attributes using the data-v-* syntax.

Pagination & Sorting

Option Attribute Description Default
start data-v-start Starting offset for pagination 0
limit data-v-limit Number of reviews to display 4
page data-v-page Page number for pagination 1
order data-v-order Sort field (review_id, user_id, created_at, updated_at) created_at
direction data-v-direction Sort direction (asc, desc) desc
image size data-v-image_size xlarge, large, medium, thumb thumb

Filtering

Option Attribute Description Default
status data-v-status Review status: 1 = published, 0 = pending, 2 = spam, 3 = trash 1
product_id data-v-product_id Filter by product ID null
slug data-v-slug Filter by product slug null
user_id data-v-user_id Filter by user ID null

Additional Options

Option Attribute Description Default
language_id data-v-language_id Language for review content and product title Current language
product_title data-v-product_title Include product title (useful for recent‑reviews widgets) false

Component Properties

Each review is wrapped in:

data-v-review

The following fields are available inside each review element.

Author Information

Property Attribute Description
username data-v-review-username Username of the reviewer
email data-v-review-email Email address
first_name data-v-review-first_name First name
last_name data-v-review-last_name Last name
display_name data-v-review-display_name Display name
author data-v-review-author Full author name
avatar data-v-review-avatar Avatar filename
avatar_url data-v-review-avatar_url Full avatar URL
bio data-v-review-bio Author biography
subscribe data-v-review-subscribe Whether the user subscribed to replies

Review Metadata

Property Attribute Description
review_id data-v-review-review_id Unique review ID
product_id data-v-review-product_id ID of the product the review belongs to
user_id data-v-review-user_id ID of the user who producted the review
url data-v-review-url Author’s website URL
ip data-v-review-ip IP address (if stored)
status data-v-review-status Review status
rating data-v-review-rating Rating 1 to 5
type data-v-review-type Review type (empty for standard reviews)
parent_id data-v-review-parent_id Parent review ID (for threaded replies)
level data-v-review-level Nesting level for threaded reviews
created_at data-v-review-created_at Creation timestamp
updated_at data-v-review-updated_at Last update timestamp

Review Content

Property Attribute Description
content data-v-review-content Review text

Product Information (Optional)

Displayed only when data-v-product_title="true" is used.

Property Attribute Description
name data-v-review-name Title of the product the review belongs to
slug data-v-review-slug Slug of the product the review belongs to

HTML Example

<div data-v-component-reviews data-v-product_id="url">

  <ol data-v-if="count > 0">

    <li data-v-review>

      <div class="review-wrap">

        <figure class="author-avatar me-2">
          <img data-v-review-avatar_url
               alt="user"
               width="60"
               loading="lazy"
               src="/media/vvveb.svg" 
               data-v-if="review.avatar_url">
        </figure>

        <div class="review-author">

          <a rel="external nofollow ugc" data-v-if="review.url">
            <span data-v-review-author>John Doe<</span>
          </a>


	<div class="review-meta">
	  <span data-v-review-created_at data-filter-friendly_date>3 year ago</span>
	</div>


        </div>

      </div>

		<div data-v-review-content>This is an approved review.</div>

      <div class="reply">
        <a href="#review-form"
           class="reply-btn"
           data-v-vvveb-action="replyTo"
           data-review_id
           data-review_author>
          Reply <i class="la la-reply"></i>
        </a>
      </div>

    </li>

  </ol>

  <div class="alert" role="alert" data-v-if-not="this.default_review_status">
    <div data-v-notification-text>
      <span>Reviews are closed</span>
    </div>
  </div>

This example displays a threaded review list with avatars, author names, timestamps, content, and reply actions.

Product Review Form Component

The Review Form handles review submission on product pages. It works together with the Product Reviews Component, allowing users to submit new reviews or reply to existing ones. The form supports logged‑in users, anonymous reviewers (if enabled), CSRF protection, and threaded replies.

To use javascript to product the review without refreshing the page add the following attributes:

data-v-vvveb-action="addReview"
data-v-vvveb-on="submit"

These attributes instruct Vvveb CMS to process the form submission through javascript fetch.


How the Review Form Works

The form products data to the current page and is intercepted by the Vvveb action handler. The handler:

  • Validates required fields
  • Checks CSRF token
  • Determines whether the user is logged in or anonymous
  • Creates a new review in the database
  • Assigns the review to the correct product
  • Handles threaded replies via parent_id
  • Returns success or error notifications

If reviews require moderation, the submitted review may be stored with status = 0 (pending).


Form Fields

The form includes a mix of visible and hidden fields. These fields are required for proper review submission.

Hidden System Fields

Field Purpose
product_id Identifies the product the review belongs to
slug Product slug (used for redirects and validation)
parent_id ID of the parent review (0 for top‑level reviews)
csrf CSRF token for security
firstname-empty Honeypot anti‑spam field (must remain empty)
subject-empty Honeypot anti‑spam field
lastname-empty Honeypot anti‑spam field

Honeypot fields help block bots without affecting real users.


User Identity Fields

These fields are shown only when the user is not logged in:

Field Required Description
author Yes Name of the reviewer
email Yes Email address of the reviewer

When the user is logged in, these fields are omitted because the system already knows the user’s identity.


Review Content

Field Required Description
content Yes The actual review text

This is the main body of the review.


Replying to Reviews

The reply links in the review list use:

data-v-vvveb-action="replyTo"

This action:

  • Scrolls to the review form
  • Sets the hidden parent_id field to the ID of the review being replied to
  • Optionally displays the name of the user being replied to

This enables threaded/nested reviews.


Anonymous Reviews

The form includes:

data-v-if="this.global.user_id || this.anonymous_reviews"

This means:

  • If the user is logged in → show the form
  • If the user is not logged in but anonymous reviews are allowed → show the form
  • Otherwise → hide the form

Anonymous review settings are controlled in the site configuration.


Validation & Security

The review form includes several built‑in protections:

  • CSRF token (data-v-csrf)
  • Honeypot fields (firstname-empty, subject-empty, lastname-empty)
  • Server‑side validation of required fields
  • Status filtering (pending, spam, trash)

If moderation is enabled, reviews may not appear immediately.


HTML Example

<form id="review-form"
      method="post"
      action=""
      data-v-vvveb-action="addReview"
      data-v-vvveb-on="submit"
      data-v-if="this.global.user_id || this.anonymous_reviews">

  <input type="hidden" name="product_id" data-v-product-product_id>
  <input type="hidden" name="slug" data-v-product-slug>
  <input type="hidden" name="parent_id" value="0">
  <input type="hidden" name="csrf" data-v-csrf>

  <!-- Honeypot anti-spam fields -->
  <input type="hidden" name="firstname-empty">
  <input type="text" class="visually-hidden" name="lastname-empty" tabindex="-1">
  <input type="text" class="d-none" name="subject-empty">

  <!-- Anonymous user fields -->
  <div data-v-if-not="this.global.user_id">
    <div class="mb-3">
      <label class="form-label">Name</label>
      <input type="text" name="author" class="form-control" required>
    </div>

    <div class="mb-3">
      <label class="form-label">Email address</label>
      <input type="email" name="email" class="form-control" required>
    </div>
  </div>

  <!-- Review text -->
  <div class="mb-3">
    <textarea name="content" rows="5" class="form-control" placeholder="Review" required></textarea>
  </div>

  <!-- Submit -->
  <button type="submit" class="btn btn-primary btn-submit">
    <span class="loading d-none">
      <span class="spinner-border spinner-border-sm"></span>
      <span>Producting...</span>
    </span>

    <span class="button-text">
      <span>Product review</span>
      <i class="la la-long-arrow-alt-right ms-1"></i>
    </span>
  </button>

</form>

This example includes all required fields, anonymous user handling, CSRF protection, and reply support.