Developer notes
How the storefront gets its numbers
Section titled “How the storefront gets its numbers”Templates print only empty placeholders that are the same for every visitor:
- product page:
<div class="kv-usp kv-usp-product" data-kv-usp-p="{product_id}" data-kv-usp-view="1" hidden>(template hooksproducts:promo_textpost orproducts:product_detail_bottompost, by setting); - lists:
<span class="kv-usp-lb" data-kv-usp-l="{product_id}" hidden>appended to theproduct_labels_<prefix><id>capture ofcommon/product_data.tpl(hookproducts:product_datapost), so every core list prints it inside the image container; - cart lines:
<div class="kv-usp-cl" data-kv-usp-c="{product_id}" hidden>(hookproducts:product_additional_infopost, cart page only); - page context:
<div class="kv-usp-ctx" data-kv-usp-url data-kv-usp-dispatch data-kv-usp-lang data-kv-usp-toasts hidden>(hookindex:bodypost).
js/addons/kv_urgency_social_proof/func.js collects the placeholders on ce.commoninit (also for AJAX-loaded fragments) and sends one POST to index.php?dispatch=kv_urgency_social_proof.data:
| Parameter | Meaning |
|---|---|
lang |
Page language |
product, view=1 |
Product page product; view records the anonymous viewer signal |
only=viewers |
Minute refresh of the viewer count (max. 30 per page, only while the tab is visible) |
ids[] |
List badge products (max. 80) |
cart[], cart_page=1 |
Cart lines; promotion countdown of the shopper’s cart (session) |
toasts=1 |
Recent purchases |
The answer is JSON with final texts ({"on":true,"cfg":{…},"product":{"id":…,"items":[{"t":"countdown","text":"Sale ends in","left":172795},…]},"list":{…},"cart":{…},"toasts":[…]}); the script inserts them with textContent. {"on":false} when the add-on is switched off or not licensed.
The dispatch is not cacheable, sends Cache-Control: no-store, writes no session and no storage_data. CSRF validation is off for this mode only (schemas/security/csrf_validation.post.php), because guests on fully cached pages have no form token; the mode only reads public counts and records an anonymous viewer row.
| Table | Columns | Notes |
|---|---|---|
?:kv_usp_views |
product_id, vhash (16 hex), company_id, ts |
PK (product_id, vhash); vhash = HMAC-SHA256 of IP + user agent with the store’s crypt key and the current date; rows older than one hour are deleted on 2% of pings |
?:kv_usp_optout |
user_id, created_at |
Customers who opted out of recent-purchase toasts |
Sales: COUNT(DISTINCT order e-mail) over ?:order_details × ?:orders in the window, selected statuses, is_parent_order != 'Y', Ultimate: orders.company_id = storefront. Stock: products.amount with the effective tracking (global setting → product → default for NULL), 0 < amount <= threshold, no downloadable products. Countdown: fn_get_product_data() + fn_gather_additional_product_data(..., get_discounts) → $product['promotions'] → earliest promotions.to_date within the window; cart: promotions of $cart['promotions'] and of the cart products. Visibility of every product id passed by the browser is checked with fn_get_products() in the storefront area.
| Hook | Use |
|---|---|
update_user_profile_post |
Saves the profile opt-out checkbox (storefront only) |
delete_user |
Deletes the opt-out row |
schemas/block_manager/blocks.post.php adds settings_objects / settings_vendor_values update handlers to the cached products.view main block (the position setting changes the placeholder’s place).
License check
Section titled “License check”Tygh\Addons\KvUrgencySocialProof\License\Client (generated) verifies the license. Gate point: Config::isActive() in the data endpoint (all output and the viewer row). Not gated: the profile opt-out (a privacy choice is always stored).
Not in 1.0.0
Section titled “Not in 1.0.0”Block Manager block for free placement, per-vendor settings, “added to cart N times today”, stock per warehouse (the total product stock is used), countdowns for promotions without product conditions on list badges.
File map
Section titled “File map”| Path | Purpose |
|---|---|
app/addons/kv_urgency_social_proof/addon.xml |
Settings, tables |
init.php, func.php |
Hooks, fn_kv_urgency_social_proof_is_licensed(), opt-out helpers |
Tygh/Addons/KvUrgencySocialProof/Signals.php |
Real-data queries (sales, stock, viewers, promotions, recent purchases) |
Payload.php |
JSON answer of the data endpoint |
Config.php |
Typed settings |
License/, controllers/backend/kv_urgency_social_proof_license.php |
License check (generated) |
Upgrade/Synchronizer.php |
Self-healing upgrades (generated) |
controllers/frontend/kv_urgency_social_proof.php |
Data endpoint |
controllers/frontend/profiles.post.php |
Opt-out checkbox state |
schemas/ |
CSRF exception, block cache handlers, order status variants |
var/themes_repository/responsive/templates/addons/kv_urgency_social_proof/ |
Placeholders, opt-out checkbox, page context |
var/themes_repository/responsive/css/addons/kv_urgency_social_proof/styles.less |
Styles (scoped .kv-usp*) |
js/addons/kv_urgency_social_proof/func.js |
Loader, rendering, countdown, viewer refresh, toasts (jQuery, no external libraries) |