Reviews and Ratings Module Development for 1C-Bitrix
Bitrix includes the bitrix:catalog.element.vote component for voting and bitrix:forum with element binding — these are the standard building blocks for reviews. The result is predictable: a forum without moderation, ratings without purchase verification, and no structured data for Schema.org. A full-featured reviews module is a different story: verified reviews, multi-criteria ratings, moderation, seller replies, and aggregated stars in microdata.
Data Model
Module vendor.reviews:
-
b_vendor_review— reviews: id, entity_type (product/service/company), entity_id, user_id, author_name, author_email, order_id, title, body, pros, cons, rating (1-5), status (pending/approved/rejected/spam), is_verified_purchase, created_at, updated_at -
b_vendor_review_criteria— rating criteria: id, entity_type, name, sort -
b_vendor_review_rating— per-criteria ratings: id, review_id, criteria_id, value -
b_vendor_review_vote— "helpful/not helpful" votes: id, review_id, user_id, ip, value (1/-1), created_at -
b_vendor_review_reply— admin replies: id, review_id, author_id, body, created_at
Purchase Verification
The most valuable element of a review is the "verified buyer" badge. Verification is done against b_sale_order:
public function isVerifiedPurchase(int $userId, int $productId): bool
{
// Look for a paid order from this user containing this product
$order = \Bitrix\Sale\Internals\BasketTable::getList([
'select' => ['ORDER_ID'],
'filter' => [
'=PRODUCT_ID' => $productId,
'=ORDER.USER_ID' => $userId,
'=ORDER.PAYED' => 'Y',
'=ORDER.CANCELED' => 'N',
],
'limit' => 1,
])->fetch();
return (bool)$order;
}
When submitting a review, order_id can be passed explicitly — then verification is unambiguous. Without order_id — verification is done against any paid order containing this product.
Moderation
All reviews are created with pending status and enter the moderation queue. Two modes are available:
- Manual moderation — a moderator approves or rejects each review
- Auto-approval — reviews from verified buyers are published automatically; others go into the queue
The spam filter uses simple heuristics: links in the review body, uppercase threshold, duplicate texts, stop words. Suspicious reviews receive spam status.
class SpamDetector
{
public function check(string $text): SpamResult
{
if (preg_match('/https?:\/\//i', $text)) return SpamResult::spam('Links are not allowed');
if (similar_text($text, $this->getLastReview($text)) > 80) return SpamResult::spam('Duplicate');
foreach ($this->stopWords as $word) {
if (mb_stripos($text, $word) !== false) return SpamResult::suspicious();
}
return SpamResult::clean();
}
}
Multi-Criteria Rating
Multiple rating criteria can be defined for products (for example: "Quality", "Matches Description", "Delivery Speed"). The final rating is the average across all criteria:
SELECT
entity_id,
AVG(rr.value) AS avg_rating,
COUNT(DISTINCT r.id) AS review_count
FROM b_vendor_review r
JOIN b_vendor_review_rating rr ON rr.review_id = r.id
WHERE r.entity_type = 'product'
AND r.status = 'approved'
GROUP BY entity_id;
Aggregated data is cached with the tag review_entity_{entity_id} and invalidated when a new review is approved.
Schema.org Microdata
For SEO impact, the aggregated rating must be included in the microdata:
<div itemscope itemtype="https://schema.org/Product">
<span itemprop="name">Product Name</span>
<div itemprop="aggregateRating" itemscope itemtype="https://schema.org/AggregateRating">
<span itemprop="ratingValue">4.7</span>
<span itemprop="reviewCount">143</span>
</div>
</div>
The vendor:reviews.aggregate component generates this block from cached data.
Helpfulness Voting
Users can mark a review as "helpful" or "not helpful". Anti-manipulation protection:
- One vote per IP per day
- Authenticated users — one vote per review, permanent
- Helpfulness rating influences the display order of reviews
Development Timeline
| Stage | Duration |
|---|---|
| ORM tables, review model | 1 day |
| Purchase verification, sale integration | 1 day |
| Moderation, spam filter | 2 days |
| Multi-criteria rating, aggregation | 1 day |
| Schema.org microdata | 0.5 days |
| Helpfulness voting | 0.5 days |
| Seller replies, notifications | 1 day |
| Site components | 2 days |
| Admin interface + moderation queue | 1 day |
| Testing | 1 day |
Total: 11 working days. Importing reviews from Yandex.Market or other platforms — additional 1–2 days.







