Developing Social Proof Functionality for 1C-Bitrix
A product card without reviews, ratings, and real buyer photos converts worse. This is not a marketing assumption — it is measurable: A/B tests on e-commerce projects consistently show a 15–30% conversion increase when social proof blocks are added. The developer's task: integrate these elements into a Bitrix store so they do not slow the page and do not generate spam.
What Social Proof Includes on Bitrix
The set of blocks depends on the business type, but a typical list includes:
- Rating and reviews — star rating, text reviews with photos
- View/purchase counters — "This product was purchased 127 times"
- Recent purchase notifications — popup "Ivan from Moscow bought this 5 minutes ago"
- Questions and answers — Q&A section on the product card
- User photos — UGC gallery from buyers
- Badges — "Buyers' choice", "Bestseller", "New arrival"
Ratings and Reviews: Storage and Display
Bitrix includes a built-in vote (voting) module and options via info block properties. For a full-featured review system, a custom table is typically built:
CREATE TABLE b_product_reviews (
ID SERIAL PRIMARY KEY,
PRODUCT_ID INT NOT NULL,
USER_ID INT,
AUTHOR_NAME VARCHAR(255),
RATING SMALLINT CHECK (RATING BETWEEN 1 AND 5),
TITLE VARCHAR(500),
BODY TEXT,
PROS TEXT,
CONS TEXT,
STATUS VARCHAR(20) DEFAULT 'pending', -- pending|approved|rejected
DATE_CREATE TIMESTAMP DEFAULT NOW(),
HELPFUL_YES INT DEFAULT 0,
HELPFUL_NO INT DEFAULT 0
);
CREATE TABLE b_review_photos (
ID SERIAL PRIMARY KEY,
REVIEW_ID INT NOT NULL REFERENCES b_product_reviews(ID),
FILE_ID INT NOT NULL REFERENCES b_file(ID)
);
Aggregated rating (average score, review count) is cached in a separate info block field — not computed on every page request. It is updated via an event handler when a new review is approved.
Moderation is mandatory. Without it, the first spam or competitor review will damage the product's reputation. In the standard implementation: a review with pending status is not displayed; a moderator approves it via a custom section in /bitrix/admin/ or via Bitrix24.
Purchase Counters and Notifications
Purchase counter — the number of orders containing this product from b_sale_basket. A direct SQL query for every product card is an N+1 problem in listings. Solution: a separate cache table updated on each order placement:
CREATE TABLE b_product_social_counters (
PRODUCT_ID INT PRIMARY KEY,
PURCHASE_COUNT INT DEFAULT 0,
VIEW_COUNT INT DEFAULT 0,
WISHLIST_COUNT INT DEFAULT 0,
LAST_PURCHASED TIMESTAMP
);
Update via the OnSaleOrderSaved event handler:
AddEventHandler('sale', 'OnSaleOrderSaved', function($event) {
$order = $event->getParameter('ENTITY');
foreach ($order->getBasket() as $item) {
$productId = $item->getField('PRODUCT_ID');
$db->query("UPDATE b_product_social_counters SET purchase_count = purchase_count + 1,
last_purchased = NOW() WHERE product_id = $productId");
}
});
Recent purchase popup notifications — an AJAX request to a controller that returns the last N purchases of the product (with city name from b_sale_order_props, without personal data). On the frontend — a popup shown with a delay and frequency limit:
async function showRecentPurchaseNotification(productId) {
const data = await fetch(`/local/api/social-proof/recent/?product=${productId}`).then(r => r.json());
if (data.length === 0) return;
const purchase = data[Math.floor(Math.random() * data.length)];
showNotification(`${purchase.city}: purchased ${purchase.time_ago} ago`);
}
Data authenticity is critical for notifications: showing fabricated purchases is not acceptable. If real data is sparse (new product), the block is not displayed.
UGC Buyer Gallery
Photos from real buyers are the strongest social proof for fashion, furniture, and electronics. Technically: the review form includes an image upload field (via CFile::SaveFile()), uploaded photos go through moderation, and approved ones are displayed in a gallery below the main product photos.
Resizing user-uploaded images is mandatory — without it the /upload/ directory fills up with gigabytes of data within a year:
// When saving a review photo
$resized = CFile::ResizeImageGet($fileId, ['width' => 800, 'height' => 800], BX_RESIZE_IMAGE_PROPORTIONAL);
Schema.org Markup for Reviews
Reviews with correct markup are shown in search results as star ratings. Markup: Product + AggregateRating + Review:
$schema = [
'@context' => 'https://schema.org',
'@type' => 'Product',
'name' => $arResult['NAME'],
'aggregateRating' => [
'@type' => 'AggregateRating',
'ratingValue' => $arResult['RATING'],
'reviewCount' => $arResult['REVIEW_COUNT'],
'bestRating' => 5,
],
'review' => array_map(fn($r) => [
'@type' => 'Review',
'reviewRating' => ['@type' => 'Rating', 'ratingValue' => $r['RATING']],
'author' => ['@type' => 'Person', 'name' => $r['AUTHOR_NAME']],
'reviewBody' => $r['BODY'],
], $reviews),
];
echo '<script type="application/ld+json">' . json_encode($schema, JSON_UNESCAPED_UNICODE) . '</script>';
Badges on Product Cards
"Bestseller", "Buyers' choice", "Exclusive" — statuses computed from data or set manually:
-
Bestseller— ifpurchase_countis in the top 5% of the catalog (computed by an agent once per day) -
Highly rated— if the average rating is ≥ 4.5 and the review count is ≥ 10 -
Almost gone— if the product stock is ≤ 5 units
Badges are stored in a "List" type info block property (multiple). An agent updates them on schedule, without loading each page request.
Protection Against Manipulation
Without protection, both ratings and purchase counters get gamed. Basic measures:
- Reviews only from registered users who have purchased the product (verified against
b_sale_basket) - Limit: one review per product per user
- Rate limiting on the view counter API: one increment per session
- CAPTCHA or honeypot hidden field on the review form
Timelines
| Block | Scope | Timeline |
|---|---|---|
| Rating + reviews | DB, form, moderation, Schema.org | 2–3 weeks |
| Counters + notifications | Cache table, agents, popup | 1–2 weeks |
| UGC gallery | Upload, resize, moderation, display | 1–2 weeks |
| Badges | Computation agent, listing display | 3–5 days |
Social proof is not decoration — it is part of the conversion funnel. Investment in a proper implementation pays off through measurable conversion growth on the product card, easily tracked via an A/B test.







